#!/usr/bin/env python3
"""exp15 — BLIND reading packets for the owner (§D3 human endpoint: metrics NOMINATE, blind read RATIFIES,
planка = <=2 claims/chapter). Presents the SAME opening source passage translated 3 ways — flat-A0-30
(blind-greedy baseline), oracle-30 (seam-aligned), q3a-src (source-carryover arm) — under SHUFFLED neutral
labels (V1/V2/V3), with a separate key. The owner reads without knowing which is which and counts claims.

Deterministic shuffle (fixed seed). Outputs to exp15/monitor/ (blind packet + key, key kept separate).
Run: python blind_packets.py
"""
from __future__ import annotations
import json
import random
import sqlite3
import sys
from pathlib import Path

sys.path.insert(0, str(Path(__file__).resolve().parent))
from chunker import greedy_chunks

SD = Path("/home/ubuntu/books/gu-zhenren/exp15")
AH = SD / "anchors"
MON = SD / "monitor"
N_CHUNKS = 6   # ~first 3-4 节 of the opening (readable passage)


def db_finals(db):
    con = sqlite3.connect(db)
    out = {}
    for ck, txt in con.execute("SELECT chunk_idx, response_text FROM checkpoints WHERE stage='edit' ORDER BY chunk_idx, attempt"):
        out[ck] = txt
    con.close()
    return out


def main():
    MON.mkdir(parents=True, exist_ok=True)
    flat_src = greedy_chunks((SD / "S2prime_big_flat.txt").read_text(encoding="utf-8"))
    oracle_src = greedy_chunks((SD / "S2prime_big_blanklines.txt").read_text(encoding="utf-8"))
    flat_fin = db_finals(AH / "flat_a0_30.db")
    oracle_fin = db_finals(AH / "oracle_30.db")

    # source span covered by the first N flat chunks (used for oracle coverage matching AND now shown as
    # the fidelity reference — the reader compares each version against this original for omissions/errors)
    src_span = "".join(flat_src[:N_CHUNKS])
    src_display = "\n\n".join(flat_src[:N_CHUNKS])   # paragraph-joined for readability
    # flat + q3a-src share flat chunking; oracle differs -> take oracle chunks until it covers ~the same source len
    flat_text = "\n\n".join(flat_fin[i] for i in range(N_CHUNKS) if i in flat_fin)
    arm_dir = SD / "arms" / "q3a-src"
    src_arm = "\n\n".join((arm_dir / f"{i:02d}.final.txt").read_text(encoding="utf-8")
                          for i in range(N_CHUNKS) if (arm_dir / f"{i:02d}.final.txt").exists())
    # oracle: chunks whose cumulative source length ~covers src_span
    cov, oi, otexts = 0, 0, []
    target = len(src_span)
    while oi < len(oracle_src) and cov < target:
        if oi in oracle_fin:
            otexts.append(oracle_fin[oi])
        cov += len(oracle_src[oi]); oi += 1
    oracle_text = "\n\n".join(otexts)

    arms = {"flat-A0-30 (blind greedy baseline)": flat_text,
            "oracle-30 (seam-aligned)": oracle_text,
            "q3a-src (source-carryover)": src_arm}
    labels = ["V1", "V2", "V3"]
    keys = list(arms.keys())
    rnd = random.Random("exp15-blind-2026-07-18")
    rnd.shuffle(keys)
    mapping = dict(zip(labels, keys))   # V1->arm, ...

    # blind packet (no arm names) — original source at top for FIDELITY comparison, then the 3 versions
    pkt = [f"# exp15 — СЛЕПОЙ ПАКЕТ для чтения (открывающий фрагмент 蛊真人, ~{N_CHUNKS} чанков)",
           "",
           "Три версии перевода ОДНОГО фрагмента под нейтральными метками (V1/V2/V3, перемешаны; ключ отдельно).",
           "Оцени: (а) художественность/связность и (б) ВЕРНОСТЬ — сверяя каждую версию с китайским ОРИГИНАЛОМ",
           "ниже (ничего не потеряно; смысл/род/референт/порядок событий переданы). Планка: ≤2 претензии на главу.",
           "Примечание: V1/V2/V3 переводились с разной нарезкой на чанки, поэтому у одной из версий хвост",
           "фрагмента может слегка отличаться по границе — это часть эксперимента, не ошибка перевода.",
           "", "---", "",
           "## ОРИГИНАЛ — китайский исходник (эталон для сверки верности)",
           "",
           src_display,
           "", "---", ""]
    for lab in labels:
        pkt += [f"## {lab}", "", arms[mapping[lab]], "", "---", ""]
    (MON / "blind_read_packet.md").write_text("\n".join(pkt), encoding="utf-8")
    (MON / "blind_read_KEY.json").write_text(json.dumps(
        {"_warning": "KEY — не показывать читающему до вынесения вердикта",
         "mapping_label_to_arm": mapping, "n_chunks": N_CHUNKS,
         "source_span_runes": len(src_span)}, ensure_ascii=False, indent=2), encoding="utf-8")
    print(f"blind packet -> {MON}/blind_read_packet.md  (key -> blind_read_KEY.json)")
    print(f"  labels: {mapping}")
    print(f"  lengths: flat {len(flat_text)}c, oracle {len(oracle_text)}c, q3a-src {len(src_arm)}c")


if __name__ == "__main__":
    main()
