from ops import *
out={}
for phase in ('two-reader','three','mixed'):
    d=json.loads((HERE/(phase+'-result.json')).read_text());assert d['result']=='PASS'
    first,last=d['samples'][0],d['samples'][-1];dt=last['t']-first['t'];models={};lanes=[]
    for sid,b in last['groups'].items():
        a=first['groups'][sid];assert a['run_id']==b['run_id']
        amap=a['metadata_path'];bmap=b['metadata_path']
        aa=amap['providers'] if amap.get('mode')=='provider-process' else {'single':amap}
        bb=bmap['providers'] if bmap.get('mode')=='provider-process' else {'single':bmap}
        for key,bpath in bb.items():
            apath=aa[key]
            for provider,bt in bpath['providers'].items():
                at=apath['providers'][provider];n=bt['responses']-at['responses'];late=bt['late']-at['late']
                m=models.setdefault(provider,dict(completed=0,late=0,lanes=0,rejections={}))
                m['completed']+=n;m['late']+=late;m['lanes']+=1
                for k,v in bpath.items():
                    if k.startswith('rejected_'):m['rejections'][k]=m['rejections'].get(k,0)+v-apath.get(k,0)
                lanes.append(dict(channel=sid,provider=provider,completed_fps=round(n/dt,2),accepted_fps=round((n-late)/dt,2)))
    for v in models.values():
        v['completed_fps']=round(v['completed']/dt,2);v['accepted_fps']=round((v['completed']-v['late'])/dt,2)
        v['rejected_pct']=round(v['late']*100/v['completed'],2) if v['completed'] else None
    assert all(r['last_cleanup']['completed'] and r['last_cleanup']['child_reaped'] for r in d['after_stop'])
    out[phase]=dict(seconds=round(dt,2),models=models,lanes=lanes,
        gpu_peak_mib=max(float(s['gpu'].split(',')[1]) for s in d['samples']),
        gpu_mean_util=sum(float(s['gpu'].split(',')[0]) for s in d['samples'])/len(d['samples']),normal_cleanup=True)
save('summary.json',out)
print(json.dumps({k:{x:y for x,y in v.items() if x!='lanes'} for k,v in out.items()}))
