from ops import *
import csv
groups={};details={}
for label in ('pose','mixed','mixed-resume','mixed-compact'):
    path=HERE/label/'analysis.json'
    if not path.exists():continue
    value=json.loads(path.read_text());details[label]=value
    for row in value['summary']:
        arm='pose' if label=='pose' else 'mixed';key=(arm,row['level'],row['provider'])
        assert key not in groups,('DUPLICATE_MEASURED_STAGE',key)
        groups[key]=dict(row,arm=arm,trial=label)
rows=[groups[k] for k in sorted(groups)]
with (HERE/'comparison-sot.json').open('w') as f:
    json.dump(dict(rows=rows,definitions=dict(fps='counter delta / actual monotonic stable seconds / channel count',
        source_drift='monotonic progression minus unwrapped RTP progression; fixed first observed anchor per run/provider/SSRC',
        redis_drift='Redis arrival progression minus RTP progression; per run/provider; not absolute capture latency',
        age='ingress wall time to Redis entry wall time; not pre-ingress video latency',
        batch_ratio='batch execution count / all executions, not frame-weighted',
        approximate_10fps='9.5FPS as a reporting reference; all-lane minimum separately reported',
        interrupted='mixed8 partial and mixed-resume warmup are not benchmarks'),
        conditions=dict(latest=True,no_capture=True,queue_seconds=1,queue_capacity=32,batch=8,instances=8,
            target_fps=10,sender='provider-independent',freshness=False,medium_called=False,
            input_cohort='3,5,6,8,9,10,11,12,13,14,15,16,17,18,19,20',
            pose_scenarios=['INTRUSION','LOITERING','FALL','FIGHT'],mixed_scenarios='all6',
            pose_and_mixed1to7='image c294b5fda6; global status query; timeline8',
            mixed8plus='if measured: image d9a7f28185; per-stream query; timeline2; new anchors'),
        history=dict(A='result-queue-bc/pose-a:queue1,latestOff,captureOn',
            B='result-queue-bc/pose:queue2,latestOff,captureOn',
            closest='input-lag/candidate stage8:queue1,latestOn,captureOn;120s; input-lag-f12524504a'),
        files={k:dict(native_points=v['native_points'],redis_points=v['redis_points'],
                      unmatched_native=v['unmatched_native'],resets=v['resets']) for k,v in details.items()}),f,indent=2)
columns=('arm','trial','level','provider','seconds','complete_fps','redis_fps','redis_min','redis_std',
         'queue_expired','max_redis_silence_s','source_drift_mean_s','redis_drift_mean_s','cpu_busy_pct','gpu_util_pct')
with (HERE/'comparison-sot.csv').open('w',newline='') as f:
    w=csv.DictWriter(f,fieldnames=columns,extrasaction='ignore');w.writeheader();w.writerows(rows)
lines=['| 채널 | Pose 단독 완료/Redis | 복합 Pose Redis | Fire Redis | Crowd Redis |',
       '| --- | --- | --- | --- | --- |']
for n in range(1,17):
    p=groups.get(('pose',n,'pose'))
    cells=[str(n),f"{p['complete_fps']:.2f}/{p['redis_fps']:.2f}" if p else '미측정']
    for key in ('pose','fire','crowd'):
        row=groups.get(('mixed',n,key));cells.append(f"{row['redis_fps']:.2f}" if row else '미측정')
    lines.append('| '+' | '.join(cells)+' |')
with (HERE/'table.md').open('w') as f:f.write('\n'.join(lines)+'\n')
print('\n'.join(lines))
