"""図版を生成する。数値は experiment/results/*.jsonl から読む。light: <name>.svg / dark: <name>.dark.svg（viewBoxは同一）。"""
import json
from pathlib import Path
from xml.sax.saxutils import escape
import sys
sys.path.insert(0, str(Path(__file__).parent / "experiment"))
from analyze import load, wilson

OUT = Path(__file__).parent
THEMES = {
    "": dict(text="#1f2937", sub="#4b5563", line="#9ca3af", card="#f3f4f6", acc="#1d4ed8", warn="#b45309", bad="#b91c1c", ok="#15803d", vio="#6d28d9", barbg="#e5e7eb"),
    ".dark": dict(text="#f3f4f6", sub="#d1d5db", line="#6b7280", card="#1f2937", acc="#93c5fd", warn="#fbbf24", bad="#fca5a5", ok="#86efac", vio="#c4b5fd", barbg="#374151"),
}
FONT = "sans-serif"

def t(x, y, s, size=15, fill="text", weight="normal", anchor="start"):
    return f'<text x="{x}" y="{y}" font-family="{FONT}" font-size="{size}" font-weight="{weight}" fill="{{{fill}}}" text-anchor="{anchor}">{escape(s)}</text>'

def svg(w, h, title, body):
    return (f'<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 {w} {h}" role="img" aria-label="{escape(title)}">'
            f'<title>{escape(title)}</title>' + "".join(body) + "</svg>\n")

def cum(name, k):
    rows = load(name); ok = sum(r["steps"][k-1]["cum_ok"] for r in rows); return ok, len(rows)

def fig_concept():
    w, h = 800, 330
    p = 0.9
    b = [t(24, 34, "段数が増えると、成功率は「1段の成功率の掛け算」で減っていく", 20, weight="bold"),
         t(24, 58, "例：1段の成功率が90%、各段が独立だと仮定した計算値（実測ではない）", 14, "sub")]
    x0, bw, gap, base, hmax = 40, 52, 22, 270, 170
    for k in range(1, 11):
        v = p ** k; x = x0 + (k - 1) * (bw + gap); bh = hmax * v
        col = "ok" if v >= 0.8 else ("warn" if v >= 0.5 else "bad")
        b.append(f'<rect x="{x}" y="{base-hmax}" width="{bw}" height="{hmax}" rx="6" fill="{{barbg}}"/>')
        b.append(f'<rect x="{x}" y="{base-bh:.0f}" width="{bw}" height="{bh:.0f}" rx="6" fill="{{{col}}}"/>')
        b.append(t(x + bw/2, base - hmax - 8, f"{round(v*100)}%", 15, "text", "bold", "middle"))
        b.append(t(x + bw/2, base + 22, f"{k}段", 14, "sub", "normal", "middle"))
    b.append(t(24, 318, "1段で10%外すだけで、10段なら3回に2回は、どこかで外れる", 14, "text", "bold"))
    return svg(w, h, "1段の成功率が90%のとき、1段で90%、3段で73%、6段で53%、10段で35%と、段数に応じて全体の成功率が下がる計算", b)

def fig_lines():
    w, h = 800, 470
    series = [("B_haiku_8", "Haiku 4.5・各段8行", "bad", 100), ("B_haiku_3", "Haiku 4.5・各段3行", "warn", 60), ("B_sonnet_8", "Sonnet 5.5・各段8行", "ok", 30)]
    L, R, T, B = 70, 640, 90, 400
    X = lambda k: L + (k - 1) * (R - L) / 9
    Y = lambda v: B - (B - T) * v
    b = [t(24, 34, "段数を増やすと、成功率は落ちた。落ち方は「1段の強さ」で決まる", 20, weight="bold"),
         t(24, 58, "実線＝実測（最終累計が正解の割合）／点線＝1段の正答率pから計算したp^段数", 14, "sub")]
    for v in (0, .25, .5, .75, 1):
        b.append(f'<line x1="{L}" y1="{Y(v):.0f}" x2="{R}" y2="{Y(v):.0f}" stroke="{{line}}" stroke-width="1" stroke-opacity="0.5"/>')
        b.append(t(L - 10, Y(v) + 5, f"{int(v*100)}%", 13, "sub", "normal", "end"))
    for k in range(1, 11):
        b.append(t(X(k), B + 24, f"{k}", 13, "sub", "normal", "middle"))
    b.append(t((L + R) / 2, B + 48, "段数（前の段の出力を次の段に渡す）", 14, "sub", "normal", "middle"))
    labely = {}
    for name, label, col, n in series:
        rows = load(name)
        ys = [sum(r["steps"][k-1]["cum_ok"] for r in rows) / len(rows) for k in range(1, 11)]
        pl = sum(s["local_ok"] for r in rows for s in r["steps"]) / (10 * len(rows))
        pts = " ".join(f"{X(k):.0f},{Y(ys[k-1]):.0f}" for k in range(1, 11))
        th = " ".join(f"{X(k):.0f},{Y(pl**k):.0f}" for k in range(1, 11))
        b.append(f'<polyline points="{th}" fill="none" stroke="{{{col}}}" stroke-width="2" stroke-dasharray="5 5" stroke-opacity="0.7"/>')
        b.append(f'<polyline points="{pts}" fill="none" stroke="{{{col}}}" stroke-width="3"/>')
        for k in (1, 3, 6, 10):
            b.append(f'<circle cx="{X(k):.0f}" cy="{Y(ys[k-1]):.0f}" r="5" fill="{{{col}}}"/>')
        ly = Y(ys[9]) + 5
        b.append(t(R + 14, ly, f"{round(ys[9]*100)}%", 16, col, "bold"))
        b.append(t(R + 14, ly + 18, label, 12, "sub"))
        b.append(t(R + 14, ly + 33, f"N={n}・1段あたり正答 {round(pl*100)}%", 12, "sub"))
    return svg(w, h, "段数別の最終成功率。Haiku 4.5で各段8行は1段81%から10段14%、各段3行は98%から68%、Sonnet 5.5は100%から87%", b)

def fig_split():
    w, h = 800, 400
    names = [("A_haiku_1", "1段", "1回で全部"), ("A_haiku_3", "3段", "4+3+3件"), ("A_haiku_6", "6段", "2件×4段＋1件×2段"), ("A_haiku_10", "10段", "1件ずつ")]
    L, B, T, bw, gap = 70, 320, 100, 110, 50
    Y = lambda v: B - (B - T) * v
    b = [t(24, 34, "同じ仕事を細かく分けても、成功率は上がらなかった", 20, weight="bold"),
         t(24, 58, "注文10件の請求額を足し込む仕事（Haiku 4.5、各60本）。棒の線は95%信頼区間", 14, "sub")]
    for v in (0, .5, 1):
        b.append(f'<line x1="{L}" y1="{Y(v):.0f}" x2="760" y2="{Y(v):.0f}" stroke="{{line}}" stroke-opacity="0.5"/>')
        b.append(t(L - 10, Y(v) + 5, f"{int(v*100)}%", 13, "sub", "normal", "end"))
    for i, (name, lab, sub) in enumerate(names):
        rows = load(name); ok = sum(r["steps"][-1]["cum_ok"] for r in rows); n = len(rows)
        v = ok / n; lo, hi = wilson(ok, n); x = L + 30 + i * (bw + gap)
        col = "acc"
        b.append(f'<rect x="{x}" y="{Y(v):.0f}" width="{bw}" height="{B-Y(v):.0f}" rx="6" fill="{{{col}}}"/>')
        cx = x + bw / 2
        b.append(f'<line x1="{cx}" y1="{Y(lo):.0f}" x2="{cx}" y2="{Y(hi):.0f}" stroke="{{text}}" stroke-width="2"/>')
        b.append(t(cx, Y(hi) - 8, f"{round(v*100)}%", 17, "text", "bold", "middle"))
        b.append(t(cx, B + 24, lab, 15, "text", "bold", "middle"))
        b.append(t(cx, B + 43, sub, 12, "sub", "normal", "middle"))
        b.append(t(cx, B + 61, f"{sum(r['wall'] for r in rows)/n:.0f}秒・${sum(r['cost'] for r in rows)/n:.3f}", 12, "sub", "normal", "middle"))
    return svg(w, h, "同じ仕事を1・3・6・10段に分けたときの成功率。1段67%、3段67%、6段58%、10段38%", b)

def fig_fixes():
    w, h = 800, 430
    L, B, T = 70, 320, 100
    Y = lambda v: B - (B - T) * v
    conds = [("B_haiku_8", "bad", "AIが全部やる（1回）"), ("B_haiku_8_v3", "warn", "AIが全部やる（3回多数決）"), ("C_haiku_8_parse", "ok", "AIは読み取りだけ・計算はコード")]
    b = [t(24, 34, "効いたのは、多数決より「計算をAIに任せない」ことだった", 20, weight="bold"),
         t(24, 58, "Haiku 4.5・各段8行の10段チェーン。最終累計が正解の割合（N=100／40／60）", 14, "sub")]
    for v in (0, .5, 1):
        b.append(f'<line x1="{L}" y1="{Y(v):.0f}" x2="760" y2="{Y(v):.0f}" stroke="{{line}}" stroke-opacity="0.5"/>')
        b.append(t(L - 10, Y(v) + 5, f"{int(v*100)}%", 13, "sub", "normal", "end"))
    bw = 42
    for i, k in enumerate((1, 3, 6, 10)):
        gx = L + 24 + i * 165
        for j, (name, col, _) in enumerate(conds):
            ok, n = cum(name, k); v = ok / n; x = gx + j * (bw + 6)
            b.append(f'<rect x="{x}" y="{Y(v):.0f}" width="{bw}" height="{B-Y(v):.0f}" rx="5" fill="{{{col}}}"/>')
            b.append(t(x + bw/2, Y(v) - 7, f"{round(v*100)}", 13, "text", "bold", "middle"))
        b.append(t(gx + 1.5 * bw + 6, B + 24, f"{k}段", 15, "text", "bold", "middle"))
    for j, (name, col, lab) in enumerate(conds):
        rows = load(name); c = sum(r["cost"] for r in rows) / len(rows); wl = sum(r["wall"] for r in rows) / len(rows)
        y = B + 48 + j * 20
        b.append(f'<rect x="{L}" y="{y-12}" width="14" height="14" rx="3" fill="{{{col}}}"/>')
        b.append(t(L + 22, y, f"{lab}：10段1本あたり ${c:.2f}・約{wl:.0f}秒", 13, "sub"))
    return svg(w, h, "10段チェーンの最終成功率の比較。AIが全部やる1回は1段81%から10段14%、3回多数決は88%から32%、計算をコードに任せると100%から98%", b)

FIGS = {"fig01-concept": fig_concept, "fig02-lines": fig_lines, "fig03-split": fig_split, "fig04-fixes": fig_fixes}
for name, fn in FIGS.items():
    raw = fn()
    for suffix, th in THEMES.items():
        s = raw
        for k, v in th.items(): s = s.replace("{" + k + "}", v)
        (OUT / f"{name}{suffix}.svg").write_text(s)
print("ok")
