"""Exact, synthetic set-mining payoff sensitivity. Python 3.10+, standard library.
Run in this directory. Outputs are deterministic; no random seed or sampled data.
"""
from fractions import Fraction as Q
from math import comb
from pathlib import Path
import csv,json
ROOT=Path(__file__).resolve().parent
p=Q(comb(50,3)-comb(48,3),comb(50,3))
P,C=Q(9,2),Q(2)
def ev(q,f,l):
    return p*(q*(P+f)-(1-q)*(C+l))-(1-p)*C
def threshold(q,l):
    return (((1-p)*C/p)+(1-q)*(C+l))/q-P
def number(x):return round(float(x),6)
cases=[]
for name,q,f,l in [('A',Q(9,10),Q(20),Q(20)),('B',Q(9,10),Q(20),Q(97)),('C',Q(1),Q(0),Q(0)),('D',Q(1),Q(20),Q(0))]:
    h=q*(P+f)-(1-q)*(C+l)
    cases.append(dict(case=name,hit_win_probability=str(q),win_future_opponent_bb=str(f),loss_future_hero_bb=str(l),hit_mean_net_bb=number(h),call_model_ev_bb=number(ev(q,f,l)),exact_call_ev=str(ev(q,f,l))))
grid=[dict(hit_win_probability=str(q),loss_future_hero_bb=str(l),required_win_future_opponent_bb=number(threshold(q,l)),exact_required=str(threshold(q,l))) for q in [Q(1),Q(9,10),Q(4,5)] for l in [Q(0),Q(20),Q(97)]]
result=dict(method='Exact finite counting and rational payoff arithmetic; synthetic assumptions, no solver or population data.',flops=comb(50,3),rank_matching_flops=comb(50,3)-comb(48,3),hit_probability=str(p),hit_probability_percent=number(p*100),pot_before_call_bb=str(P),incremental_call_bb=str(C),remaining_stack_after_call_bb=97,required_mean_hit_net_bb=number((1-p)*C/p),exact_required_mean_hit_net=str((1-p)*C/p),cases=cases,thresholds=grid)
(ROOT/'results.json').write_text(json.dumps(result,indent=2)+'\n',encoding='utf-8',newline='\n')
for name,rows in [('cases.csv',cases),('thresholds.csv',grid)]:
    with (ROOT/name).open('w',encoding='utf-8',newline='') as f:
        w=csv.DictWriter(f,fieldnames=list(rows[0]),lineterminator='\n');w.writeheader();w.writerows(rows)
print(json.dumps(result,indent=2))
