"""Re-score the detour test from detour-run1-rows.csv. Python 3, standard library only.

M1 = share of rows where the straight-line estimate (straight distance x 1.3, walked at 80 m a minute) is off the
walking route on the street network by 3 minutes or more. The 95% band resamples whole points (2,000 draws), because
the rows of one point share a street network. Usage: python3 score.py detour-run1-rows.csv
"""
import csv, hashlib, random, sys

OFF_MIN, FACTOR, M_PER_MIN, DRAWS = 3.0, 1.3, 80.0, 2000
SEED = int(hashlib.sha256(b"detour-claim-1027").hexdigest()[:8], 16)

rows = [r for r in csv.DictReader(open(sys.argv[1] if len(sys.argv) > 1 else "detour-run1-rows.csv")) if not r["left_out"]]
for r in rows:
    r["off3"] = r["off3"] == "True"
    r["diff_min"] = float(r["diff_min"])
    # check the stored flag against the raw distances
    est = float(r["straight_m"]) * FACTOR / M_PER_MIN
    assert (abs(est - float(r["truth_min"])) >= OFF_MIN) == r["off3"], r["point"]

def share(rs, f): return sum(1 for r in rs if f(r)) / len(rs)

by = {}
for r in rows: by.setdefault(r["point"], []).append(r["off3"])
pts, rng, draws = list(by.values()), random.Random(SEED), []
for _ in range(DRAWS):
    s = [rng.randrange(len(pts)) for _ in pts]
    draws.append(sum(sum(pts[i]) for i in s) / sum(len(pts[i]) for i in s))
draws.sort()
off = [r for r in rows if r["off3"]]
print(f"rows {len(rows)}, points {len(by)}")
print(f"M1 off by 3+ min: {share(rows, lambda r: r['off3']):.1%} "
      f"(95% band {draws[int(0.025 * DRAWS)]:.1%} to {draws[int(0.975 * DRAWS) - 1]:.1%})")
print(f"of those, estimate shorter than the walk: {share(off, lambda r: r['diff_min'] < 0):.1%}")
