# /// script
# requires-python = ">=3.10"
# dependencies = ["numpy", "scipy"]
# ///
# Copyright (c) 2026 Aayush Sharma · SPDX-License-Identifier: MIT
# https://thedataengineering.com/lab-code/LICENSE.txt
"""Alert fatigue by arithmetic.

12,000 checks, each firing with probability 0.001 on clean data, for 90
days. Then a Bonferroni correction (fire only below 0.001 / 12,000), and one
injected real defect of moderate size per week: how many does each setting catch?
"""
import argparse, json
import numpy as np
from scipy.stats import norm

p = argparse.ArgumentParser(description=__doc__.splitlines()[0])
p.add_argument("--checks", type=int, default=12_000, help="Checks in the suite.")
p.add_argument("--alpha", type=float, default=0.001, help="Per-check false-positive rate.")
p.add_argument("--days", type=int, default=90, help="Days simulated.")
p.add_argument("--effect", type=float, default=3.5, help="Size of an injected defect, in standard errors of its check's statistic.")
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)

z_plain = norm.isf(args.alpha / 2); z_bonf = norm.isf(args.alpha / args.checks / 2)
defect_days = list(range(3, args.days, 7))
rows, caught = [], {"plain": 0, "bonferroni": 0}
for d in range(args.days):
    z = rng.standard_normal(args.checks)                      # each check's statistic on clean data
    real = d in defect_days
    if real: z[rng.integers(args.checks)] += args.effect * rng.choice([-1, 1])  # one check sees a real defect
    fires_plain = int(np.sum(np.abs(z) > z_plain)); fires_bonf = int(np.sum(np.abs(z) > z_bonf))
    rows.append({"day": d + 1, "alerts_plain": fires_plain, "alerts_bonferroni": fires_bonf})
    if real:
        hit = np.abs(z) > z_plain
        caught["plain"] += bool(np.max(np.abs(z)) > z_plain)
        caught["bonferroni"] += bool(np.max(np.abs(z)) > z_bonf)
summary = {"alerts_per_day_plain": float(np.mean([r["alerts_plain"] for r in rows])),
           "alerts_per_day_bonferroni": float(np.mean([r["alerts_bonferroni"] for r in rows])),
           "defects": len(defect_days), "caught_plain": caught["plain"], "caught_bonferroni": caught["bonferroni"]}
print(f"per-check threshold {args.alpha}: {summary['alerts_per_day_plain']:.1f} alerts/day on clean data; "
      f"caught {caught['plain']} of {len(defect_days)} real defects (each among ~12 false alarms that day)")
print(f"Bonferroni ({args.alpha} / {args.checks:,}): {summary['alerts_per_day_bonferroni']:.2f} alerts/day; "
      f"caught {caught['bonferroni']} of {len(defect_days)} real defects")

if args.json:
    with open(args.json, "w") as f:
        json.dump({"tables": {"days": rows, "summary": [summary]}}, f)
