"""Recalculate local outcomes using only Python's standard library.
Published 18/20 is contextual and is NOT included in this test.
Run beside results.csv: python3 recalculate.py
"""
import csv,json,math
from pathlib import Path
rows=list(csv.DictReader((Path(__file__).parent/'results.csv').open()))
def cdf(k,n,p):return sum(math.comb(n,i)*p**i*(1-p)**(n-i) for i in range(k+1))
def solve(fn,target):
 lo,hi=0.,1.
 for _ in range(120):
  mid=(lo+hi)/2
  if fn(mid)>target:lo=mid
  else:hi=mid
 return (lo+hi)/2
out={}
for condition in ('baseline','agreement'):
 r=[x for x in rows if x['condition']==condition];n=len(r);k=sum(x['engine_use']=='True' for x in r)
 interval=[0 if k==0 else solve(lambda p:cdf(k-1,n,p),.975),1 if k==n else solve(lambda p:cdf(k,n,p),.025)]
 out[condition]={'events':k,'n':n,'rate':k/n,'exact_95_percent_interval':interval}
a=out['baseline'];b=out['agreement'];n1,n2=a['n'],b['n'];k=a['events']+b['events'];N=n1+n2
def prob(x):return math.comb(n1,x)*math.comb(n2,k-x)/math.comb(N,k)
observed=prob(a['events'])
out['fisher_exact_two_sided_p']=sum(prob(x) for x in range(max(0,k-n2),min(n1,k)+1) if prob(x)<=observed+1e-12)
print(json.dumps(out,indent=2))
