"""SoftwareInspect synthetic queue exercise, 2026-10-27. Python 3 stdlib.
Run: python3 replay.py > results.json
No network, accounts, credentials, customer data, or real API requests.
All jobs arrive at t=0. Fixed windows of 10 seconds, 12 accepts per window.
Input order: 96 bulk jobs, then 24 urgent jobs. Each job is one request.
No service time, concurrency, daily budget, token costs or random failures.
"""
import json

WINDOW_SECONDS = 10
CAPACITY = 12
JOBS = [(f"bulk-{i:03}", "bulk") for i in range(1, 97)] + [
    (f"urgent-{i:03}", "urgent") for i in range(1, 25)
]


def replay(policy):
    pending = list(JOBS)
    if policy == "paced_priority":
        pending.sort(key=lambda job: job[1] != "urgent")
    clock = 0
    attempts = rejected = 0
    completed = []
    windows = []
    while pending:
        sent = pending[:] if policy == "retry_all_fifo" else pending[:CAPACITY]
        accepted = sent[:CAPACITY]
        failures = len(sent) - len(accepted)
        attempts += len(sent)
        rejected += failures
        for job_id, kind in accepted:
            completed.append({"id": job_id, "kind": kind, "at_seconds": clock})
        pending = pending[len(accepted):]
        windows.append({"at_seconds": clock, "attempts": len(sent),
                        "accepted": len(accepted), "rejected": failures,
                        "pending_after": len(pending)})
        clock += WINDOW_SECONDS
    assert len({j["id"] for j in completed}) == len(JOBS)
    return {"policy": policy, "completed": len(completed), "attempts": attempts,
            "rejected": rejected,
            "last_urgent_seconds": max(j["at_seconds"] for j in completed if j["kind"] == "urgent"),
            "last_job_seconds": max(j["at_seconds"] for j in completed),
            "windows": windows, "completion_order": completed}


def main():
    runs = [replay(p) for p in ("retry_all_fifo", "paced_fifo", "paced_priority")]
    assert [(r["attempts"], r["rejected"], r["last_urgent_seconds"], r["last_job_seconds"])
            for r in runs] == [(660, 540, 90, 90), (120, 0, 90, 90), (120, 0, 10, 90)]
    print(json.dumps({"date": "2026-10-27", "kind": "synthetic discrete-time queue exercise",
                      "inputs": {"bulk_jobs": 96, "urgent_jobs": 24, "arrival_seconds": 0,
                                 "window_seconds": WINDOW_SECONDS, "accepts_per_window": CAPACITY},
                      "runs": runs}, indent=2))


if __name__ == "__main__":
    main()
