"""CoSER's published GCA results, read from the LaTeX source of arXiv:2502.09082v3 (Tables/main_exp.tex, tab:model-comparison).
Writes the same TypeScript module into the server and the worker adapters (published.ts). Run from the project root:
  curl -sL https://arxiv.org/e-print/2502.09082v3 -o src.tar.gz && mkdir src && tar -xzf src.tar.gz -C src
  python3 -I tools/experiments/coser_paper.py src
Each cell is "mean ± spread over three runs" (the paper averages three runs; the ± is not defined further). Checks every row is
complete and records, without changing any number, where the printed Average Score differs from the mean of the four printed
LLM-judged dimensions by more than rounding can explain (0.01 on two-decimal values)."""
import hashlib, json, re, sys
from pathlib import Path

COLS = ['sc', 'an', 'cf', 'sq', 'avg', 'bleu', 'rouge']
SECTIONS = {'Close-source Models': 'closed', 'Open-source Models': 'open'}


def cell(s: str):
    s = re.sub(r'\\(textbf|underline)\{', '', s)
    m = re.match(r'\s*([\d.]+)\\scriptsize\{\$\\pm([\d.]+)\$\}', s)
    assert m, s
    return float(m.group(1)), float(m.group(2))


if __name__ == '__main__':
    src = Path(sys.argv[1])
    tex = (src / 'Tables/main_exp.tex').read_text()
    rows, section = [], None
    for line in tex.split('\n'):
        line = line.strip()
        m = re.search(r'\\textit\{([^}]*)\}', line)
        if line.startswith('\\multicolumn') and m and m.group(1) in SECTIONS:
            section = SECTIONS[m.group(1)]
            continue
        if not line.endswith('\\\\') or '\\scriptsize' not in line:
            continue
        parts = [p.strip() for p in line.removesuffix('\\\\').split('&')]
        assert len(parts) == 8, parts
        vals = [cell(p) for p in parts[1:]]
        scores = {k: v[0] for k, v in zip(COLS, vals)}
        spread = {k: v[1] for k, v in zip(COLS, vals)}
        mean = sum(scores[k] for k in ('sc', 'an', 'cf', 'sq')) / 4
        mismatch = [] if abs(mean - scores['avg']) <= 0.01 else [{'printed': scores['avg'], 'mean': round(mean, 4)}]
        for x in mismatch:
            print(f"  average mismatch: {parts[0]}: printed {x['printed']}, mean of dimensions {x['mean']}")
        rows.append({'key': re.sub(r'[^a-z0-9.]+', '-', parts[0].lower()).strip('-'), 'name': parts[0], 'section': section,
                     'scores': scores, 'spread': spread, 'avgMismatch': mismatch})
    digest = hashlib.sha256(tex.encode()).hexdigest()
    print(f'{len(rows)} models ({sum(r["section"] == "closed" for r in rows)} closed); source sha256 {digest[:16]}')
    ts = ('/** Generated by tools/experiments/coser_paper.py from the LaTeX source of arXiv:2502.09082v3 (Table: model comparison);\n'
          f' * do not edit by hand. Source file Tables/main_exp.tex, sha256 {digest}. Scores in %, means of three runs; `spread` is the\n'
          ' * printed ± (not defined further in the paper). */\n'
          "import type { PaperRow } from './meta.ts';\n\n"
          f'export const SOURCE_SHA256 = {json.dumps(digest)};\n'
          f'export const PAPER_ROWS: PaperRow[] = {json.dumps(rows, ensure_ascii=False, indent=1)};\n')
    for side in ('server', 'worker'):
        Path(f'{side}/src/benchmarks/coser').mkdir(exist_ok=True)
        Path(f'{side}/src/benchmarks/coser/published.ts').write_text(ts)
