"""Version 3 public workload/event generation. No forced query count.
Neither local policy nor runtime imports this evaluator/task-history module.
"""
import random
from common import seed,GAP
VERSION='weighted-signed-last-write-select-settled-v3'
def workloads(namespace,group,K):
    r=random.Random(seed(namespace,'importance',group,K));iw=[r.choice((1,2,4)) for _ in range(K)];iq=[r.choice((1,2,4)) for _ in range(K)]
    den=4*sum(iw)*sum(iq);out=[]
    for rho in (1,3):
        wi=[(4-rho)*x*sum(iq) for x in iw];qi=[rho*x*sum(iw) for x in iq]
        assert sum(wi+qi)==den and min(wi+qi)>0
        out.append(dict(rho=rho/4,importance_write=iw,importance_query=iq,wi=wi,qi=qi,denominator=den,w=[x/den for x in wi],q=[x/den for x in qi]))
    return out

def sequence(commands,rng):
    t=0;out=[]
    for i,(kind,a,v) in enumerate(commands):
        out.append(dict(index=i,id=i%64,t=t,kind=kind,a=a,v=v));t+=GAP+rng.randrange(101)
    return out

def episodes(namespace,group,K,w):
    out=[]
    for ep in range(2):
        rng=random.Random(seed(namespace,'ordinary',group,K,w['rho'],ep));init=[('W',a,rng.choice((-1,1))) for a in range(K)];commands=[]
        for _ in range(64):
            pick=rng.random();cumulative=0.;selected=None
            for kind,weights in (('W',w['w']),('Q',w['q'])):
                for a,prob in enumerate(weights):
                    cumulative+=prob
                    if selected is None and pick<cumulative:selected=(kind,a)
            assert selected is not None
            kind,a=selected;commands.append((kind,a,rng.choice((-1,1)) if kind=='W' else 0))
        out.append(sequence(init+commands,rng))
    return out

def short(namespace,group,K):
    rng=random.Random(seed(namespace,'short',group));commands=[('W',a,rng.choice((-1,1))) for a in range(K)]+[('Q',a,0) for a in range(K)]+[('W',0,-1),('Q',0,0),('W',0,1),('Q',0,0)]
    return sequence(commands,rng)

def diagnostics(K):
    # Fixed all-address queries, all-address opposite overwrites, then reset and
    # query all zero cells. Two opposite-answer pairs branch an identical bank.
    cmds=[('W',a,1 if a%2==0 else -1) for a in range(K)]+[('Q',a,0) for a in range(K)]+[('W',a,-1 if a%2==0 else 1) for a in range(K)]+[('Q',a,0) for a in range(K)]
    return sequence(cmds,random.Random(431)),sequence([('Q',a,0) for a in range(K)],random.Random(432))
