#!/usr/bin/env python3
"""Every headline figure in claim355.txt, reformatted out of profile.json and grepped for.

The claim description is the one artifact I hand-write -- the page and the card are both
rendered from profile.json and so cannot drift, but prose typed by hand can. This turns each
number back into the exact string the claim ought to contain and fails if it is missing.
One figure was wrong when I first ran this ("90% of pixels bright" against a measured 0.8946).

    python3 check_claim.py
"""
import json, sys

WORDS = "zero one two three four five six seven eight nine ten".split()

p = json.load(open("profile.json"))
t = open("claim355.txt").read()
made, claimed, cad, lang, img, x = (p["made"], p["claimed"], p["cadence"],
                                    p["language"], p["images"], p["extras"])
M = img["metrics"]
by_id = {c["id"]: c for c in claimed["list"]}
big3 = sorted(made["list"], key=lambda b: -b["eth"])[:3]
dark = max(claimed["list"], key=lambda c: c["colour"]["dark_frac"])

checks = [
    ("wallet",        p["wallet"]),
    ("escrowed",      f'{made["escrowed_eth"]:.4f} ETH'),
    ("n_made",        f'across {made["n"]} bounties'),
    ("share",         f'{made["share_of_all_v1_eth"]*100:.1f}% of every ETH'),
    ("rank",          f'#{made["rank_by_eth_escrowed"]} of {made["n_issuers"]} funders'),
    ("earned",        f'{claimed["earned_eth"]:.4f} ETH earned back'),
    ("n_claims",      f'{claimed["n"]} claims'),
    ("big3",          ", ".join(f'{b["eth"]:.4f}' for b in big3)),
    ("ratio",         f'{x["biggest_to_smallest_ratio"]}x apart'),
    ("security",      f'{x["security_share"]*100:.1f}% of all ETH'),
    ("accepted",      f'{claimed["n_accepted"]} accepted'),
    ("corpus_rate",   f'{p["corpus"]["accepted"]}/{p["corpus"]["claims"]} = '
                      f'{x["corpus_accept_rate"]*100:.1f}%'),
    ("actions",       f'{cad["n_actions"]} actions on {cad["active_days"]} distinct days'),
    ("span",          f'{cad["span_days"]:.0f} days, {cad["first"]} to {cad["last"]}'),
    ("median_gap",    f'Median gap {cad["median_gap_days"]:.1f} days'),
    ("longest_gap",   f'longest {cad["longest_gap_days"]:.0f}'),
    ("words_bounty",  f'{lang["bounties"]["mean_words_per_doc"]:.0f} words per bounty'),
    ("words_claim",   f'{lang["claims"]["mean_words_per_doc"]:.0f} per claim'),
    ("sentence_case", f'{lang["bounties"]["sentence_case_starts"]} of '
                      f'{lang["bounties"]["docs"]} descriptions start with a capital'),
    ("baseline",      f'{img["baseline_n"]} of the other {img["baseline_of"]}'),
    ("seed",          f'seed {img["sample_seed"]}'),
    ("grey_his",      f'{M["grey_frac"]["his_median"]*100:.0f}% near-grey'),
    ("grey_base",     f'corpus median of {M["grey_frac"]["base_median"]*100:.0f}%'),
    ("extremity",     f'than {M["val_extremity"]["pct_of_his_median"]:.0f}% of the corpus'),
    ("p_grey",        f'p = {M["grey_frac"]["test"]["p_two_sided"]:.4f}'),
    ("p_sat",         f'p = {M["sat"]["test"]["p_two_sided"]:.4f}'),
    ("p_extremity",   f'p = {M["val_extremity"]["test"]["p_two_sided"]:.4f}'),
    ("n_metrics",     f'{len(M)} metrics'),
    ("bonferroni",    f'Bonferroni line is {0.05/len(M):.4f}'),
    ("nfts_stuck",    f'{x["nfts_still_in_contract"]} of v1\'s {x["nfts_total"]} NFTs'),
    ("handback",      f'On {x["nft_events"][3]["when"]}'),
    ("bright269",     f'({by_id[269]["colour"]["bright_frac"]*100:.0f}% of pixels bright)'),
    ("darkest",       f'{dark["colour"]["dark_frac"]*100:.0f}% dark pixels'),
    # the sentence spells both numbers out, and it says 'tag @artlu.eth' -- counting bare
    # 'artlu' instead gives 5, because bounty #107 mentions the handle without tagging it.
    ("tagcount",      f'{WORDS[sum(1 for b in made["list"] if "@artlu.eth" in b["desc"])]} of its '
                      f'{WORDS[made["n"]]} bounty descriptions'),
]

bad = 0
for name, s in checks:
    hit = s in t
    bad += not hit
    print(("OK   " if hit else "MISS ") + f"{name:<14} -> {s}")
print(f"\n{len(checks)-bad}/{len(checks)} present")
sys.exit(1 if bad else 0)
