# /// script
# requires-python = ">=3.10"
# ///
# Copyright (c) 2026 Aayush Sharma · SPDX-License-Identifier: MIT
# https://thedataengineering.com/lab-code/LICENSE.txt
"""An autoscaler that arrives too late.

A reactive autoscaler whose capacity at time t equals the demand it saw DELAY
seconds earlier (never below a floor of 100 × (1 + headroom)), against a
demand curve with two 90-second bursts. Unserved and idle demand-seconds for
headroom from 0% to 200%.
"""
import argparse, json

p = argparse.ArgumentParser(description=__doc__.splitlines()[0])
p.add_argument("--delay", type=int, default=240, help="Seconds between seeing demand and having the capacity.")
p.add_argument("--headrooms", default="0,0.3,1.0,2.0", help="Permanent headroom fractions.")
p.add_argument("--json", help="Also write the results to this JSON file.")
args = p.parse_args()

demand = [100] * 100 + [300] * 90 + [100] * 400 + [300] * 90 + [100] * 300   # one value per second
def evaluate(headroom):
    unserved = idle = 0; cap_series = []
    for t, d in enumerate(demand):
        seen = demand[max(0, t - args.delay)]                              # what the scaler saw DELAY seconds ago
        cap = max(seen, 100 * (1 + headroom))                              # reactive capacity, plus a floor
        unserved += max(0, d - cap); idle += max(0, cap - d); cap_series.append(cap)
    return unserved, idle, cap_series
rows, timeline = [], []
burst = sum(max(0, d - 100) for d in demand)
for h in map(float, args.headrooms.split(",")):
    u, i, caps = evaluate(h)
    rows.append({"headroom_pct": h * 100, "unserved": u, "unserved_pct_of_burst": u / burst * 100, "idle": i})
    if h in (0.0, 2.0): timeline += [{"second": t, "series": f"capacity, headroom {h:.0%}", "value": c} for t, c in enumerate(caps) if t % 5 == 0]
timeline += [{"second": t, "series": "demand", "value": d} for t, d in enumerate(demand) if t % 5 == 0]
for r in rows: print(f"headroom={r['headroom_pct']:4.0f}%  unserved={r['unserved']:6.0f} ({r['unserved_pct_of_burst']:5.1f}% of the bursts)  idle={r['idle']:7.0f}   (demand-seconds)")

if args.json:
    with open(args.json, "w") as f:
        json.dump({"tables": {"headroom": rows, "timeline": timeline}}, f)
