"""Original deterministic CPU event simulation; one-second iterations and 0.1-second switches are synthetic.
Run with Python 3.10+; standard library only. Writes results.json in the current directory.
"""
def simulate(quantum, switch_cost=0.1):
    remaining = [4] * 8
    first_feedback = {}
    queue = list(range(8))
    now = 0.0
    previous = None
    switches = 0
    while queue:
        job = queue.pop(0)
        if previous is not None and previous != job:
            now += switch_cost
            switches += 1
        count = min(quantum, remaining[job])
        first_feedback.setdefault(job, now + 1)
        now += count
        remaining[job] -= count
        if remaining[job]:
            queue.append(job)
        previous = job
    assert all(value == 0 for value in remaining)
    assert abs(now - (32 + switches * switch_cost)) < 1e-9
    return max(first_feedback.values()), now, switches

for quantum in (1, 2, 4):
    feedback, finish, switches = simulate(quantum)
    print(f"q={quantum}: last_first_feedback={feedback:.1f}, "
          f"finish={finish:.1f}, switches={switches}")
assert simulate(1)[0] < simulate(4)[0]
assert simulate(1)[1] > simulate(4)[1]

# Extended experiment: deterministic parameter sweep and invariants.
def feedback_schedule(quantum, switch_cost, threshold):
    done=[0]*8; queue=list(range(8)); now=0.; previous=None; feedback={}; events=[]; switches=0
    while queue:
        job=queue.pop(0)
        if previous is not None and previous != job:
            now+=switch_cost; switches+=1
        for _ in range(min(quantum,4-done[job])):
            start=now; now+=1; done[job]+=1
            events.append(dict(job=job,iteration=done[job],start=start,finish=now))
            if done[job]==threshold: feedback[job]=now
        if done[job]<4: queue.append(job)
        previous=job
    assert len(events)==32 and len(feedback)==8
    assert abs(now-32-switches*switch_cost)<1e-10
    return dict(quantum=quantum,switch_cost=switch_cost,threshold=threshold,
                last_feedback=max(feedback.values()),makespan=now,switches=switches,events=events)
sweep=[feedback_schedule(q,c,t) for t in [1,3,4] for c in [0.,0.1,0.5,1.] for q in [1,2,3,4]]
data=dict(sweep=sweep, jobs=8,iterations_per_job=4,iteration_seconds=1)
for threshold in [1,3,4]:
    candidates=[r for r in sweep if r['threshold']==threshold and r['switch_cost']==0.1]
    best=min(candidates,key=lambda r:r['last_feedback'])
    print(f"feedback threshold={threshold}: best tested quantum={best['quantum']}, last feedback={best['last_feedback']:.1f}s")

import json
from pathlib import Path
Path("results.json").write_text(json.dumps(data,indent=2,allow_nan=False)+"\n",encoding="utf-8")
