# -*- coding: utf-8 -*-
"""原创离线合成样例；不连接模型、不读取账户。输出位于脚本旁。
已有输入保留，修改输入后可以重跑。失败边界由 --negative 单独演示。
"""
from pathlib import Path
import sys, json, csv, math, io, hashlib, html, base64, re
sys.stdout.reconfigure(encoding='utf-8')
sys.stderr.reconfigure(encoding='utf-8')
BASE = Path(__file__).resolve().parent
NEG = '--negative' in sys.argv
def write(name, value):
    p=BASE/name; p.parent.mkdir(parents=True,exist_ok=True)
    if isinstance(value,bytes): p.write_bytes(value)
    else: p.write_text(value,encoding='utf-8',newline='')
def seed(name,value):
    if not (BASE/name).exists(): write(name,value)
def jwrite(name,value): write(name,json.dumps(value,ensure_ascii=False,indent=2))
def jseed(name,value):
    if not (BASE/name).exists(): jwrite(name,value)
def load(name): return json.loads((BASE/name).read_text(encoding='utf-8'))
def table(name,heads,rows):
    f=io.StringIO(newline='');w=csv.writer(f);w.writerow(heads);w.writerows(rows);write(name,f.getvalue())
def page(name,title,body):
    write(name,'<!doctype html><html lang="zh-CN"><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1"><title>'+html.escape(title)+'</title><style>body{max-width:1000px;margin:2rem auto;padding:0 1rem;font:17px/1.7 system-ui}table{border-collapse:collapse}td,th{border:1px solid #aaa;padding:.5rem}pre{white-space:pre-wrap;overflow-wrap:anywhere}img,svg{max-width:100%;height:auto}a{color:#125caa}</style><h1>'+html.escape(title)+'</h1>'+body+'</html>')
def emit(data): print(json.dumps(data,ensure_ascii=False))

seed('reviewer-a.csv','id,label\n1,yes\n2,yes\n3,yes\n4,no\n5,no\n6,no\n')
seed('reviewer-b.csv','id,label\n1,yes\n2,yes\n3,no\n4,no\n5,no\n6,yes\n')
a={r['id']:r['label'] for r in csv.DictReader((BASE/'reviewer-a.csv').open())};b={r['id']:r['label'] for r in csv.DictReader((BASE/'reviewer-b.csv').open())}
if NEG: b.pop('6',None)
if a.keys()!=b.keys() or not a: raise ValueError('双人标注ID不齐或空表')
n=len(a);labels=sorted(set(a.values())|set(b.values()));po=sum(a[i]==b[i] for i in a)/n;pe=sum(sum(x==l for x in a.values())*sum(x==l for x in b.values()) for l in labels)/n**2
k=None if pe==1 else (po-pe)/(1-pe);conf=[[x,y,sum(a[i]==x and b[i]==y for i in a)] for x in labels for y in labels]
table('cross-counts.csv',['reviewer_a','reviewer_b','count'],conf);dis=[[i,a[i],b[i]] for i in a if a[i]!=b[i]]
page('disagreements.html','两人标注争议',f'<p>观察一致率 {po:.6f}，期望一致率 {pe:.6f}，kappa {k}</p><pre>'+html.escape(json.dumps(dis,ensure_ascii=False,indent=2))+'</pre><p>此处没有第三方真值，不能裁定谁正确。</p>')
emit({'po':po,'pe':pe,'kappa':k,'disagreement_ids':[x[0] for x in dis]})
