# /// script
# requires-python = ">=3.10"
# dependencies = ["numpy"]
# ///
# Copyright (c) 2026 Aayush Sharma · SPDX-License-Identifier: MIT
# https://thedataengineering.com/lab-code/LICENSE.txt
"""Test the commitment sizing rule.

A year of skewed daily demand (mean 60, peak 100). Committed units cost 0.6
each whether used or not; the rest cost 1.0 on demand. Total cost for every
commitment level, against the demand distribution's percentiles; then a
different shape, and a 20% yearly price fall over a 3-year commitment.
"""
import argparse, json
import numpy as np

p = argparse.ArgumentParser(description=__doc__.splitlines()[0])
p.add_argument("--mean", type=float, default=60, help="Mean daily demand.")
p.add_argument("--peak", type=float, default=100, help="Peak daily demand.")
p.add_argument("--committed-price", type=float, default=0.6, help="Price of a committed unit, used or not.")
p.add_argument("--price-fall", type=float, default=0.2, help="Yearly fall of the on-demand price, for the 3-year case.")
p.add_argument("--seed", type=int, default=0, help="Random seed.")
p.add_argument("--json", help="Also write the results to this JSON file.")
args = p.parse_args()
rng = np.random.default_rng(args.seed)

def shaped(kind, days=365):
    x = rng.gamma(3, 1, days) if kind == "right-skewed (gamma)" else rng.beta(5, 2, days)
    x = (x - x.min()) / (x.max() - x.min())                  # scale to [0, 1]
    lo = (args.mean - args.peak * x.mean()) / (1 - x.mean())  # then to [lo, peak] with the requested mean
    return lo + (args.peak - lo) * x

def cost(demand, c, years=1):
    total = 0.0
    for y in range(years):
        on_demand = (1 - args.price_fall) ** y if years > 1 else 1.0
        total += c * args.committed_price * len(demand) + np.maximum(demand - c, 0).sum() * on_demand
    return total

rows, best = [], []
levels = list(range(20, 101, 2))
for kind in ("right-skewed (gamma)", "left-skewed (beta)"):
    d = shaped(kind)
    for years, label in ((1, "1 year"), (3, f"3 years, on-demand price -{args.price_fall:.0%}/yr")):
        costs = [cost(d, c, years) for c in levels]
        for c, v in zip(levels, costs): rows.append({"demand": kind, "term": label, "commit": c, "cost": v / years})
        bc = levels[int(np.argmin(costs))]
        pct = float(np.mean(d < bc) * 100)
        best.append({"demand": kind, "term": label, "best_commit": bc, "percentile": pct, "mean": float(d.mean())})
        print(f"{kind:<22} {label:<32} best commitment {bc:>3} = P{pct:.0f} of demand (mean {d.mean():.0f})")

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