#!/usr/bin/env python3 """Ревью посылки пробы A: метрика посадок считала ИСЧЕЗНОВЕНИЕ, а не ВОССТАНОВЛЕНИЕ. `editor_wire_probe.cmd_score` зачитывает дефект исправленным по `not re.search(bad_rx, out)`. Удаление куска текста целиком тоже даёт `not still` ⇒ выпадение фразы засчитывалось как правка. Здесь считаю три величины из того же сырья, $0: снят = bad_rx больше не совпадает (прежняя метрика) восстановлен = снят И fix_rx совпадает (строгая метрика) выпал = снят, но fix_rx НЕ совпадает (кандидат в «фразу удалили») Плюс валидация самих регексов на исходном черновике: fix_rx ОБЯЗАН совпадать с оригиналом, иначе строгая метрика штрафует за корректную работу. """ from __future__ import annotations import json import re import sys from pathlib import Path REPO = Path("/home/ubuntu/projects/textmachine") sys.path.insert(0, str(REPO / "eval" / "bank_arbitration")) RAW = Path.home() / "books" / "gu-zhenren" / "bank-arbitration" import editor_wire_probe as P # noqa: E402 def out_of(tag: str): f = RAW / f"{tag}.json" if not f.exists(): return None return json.loads(f.read_text(encoding="utf-8"))["content"] def validate_regexes() -> int: """fix_rx должен ловить ОРИГИНАЛ, bad_rx — НЕ ловить его; на посаженном — наоборот.""" bad = 0 print("=== валидация регексов посадок на исходном черновике ===") for k in sorted(P.DEFECTS): draft = P.draft_of(k) planted, _ = P.planted_draft(k, draft) for cls, old, new, bad_rx, fix_rx in P.DEFECTS[k]: fix_on_orig = bool(re.search(fix_rx, draft)) bad_on_orig = bool(re.search(bad_rx, draft)) bad_on_plant = bool(re.search(bad_rx, planted)) ok = fix_on_orig and not bad_on_orig and bad_on_plant if not ok: bad += 1 print(f" ⚠ w{k}/{cls}: fix_rx на оригинале={fix_on_orig} " f"bad_rx на оригинале={bad_on_orig} bad_rx на посаженном={bad_on_plant}") print(f" дефектных регексов: {bad} из {sum(len(v) for v in P.DEFECTS.values())}") return bad def score(arm: str) -> None: print(f"\n=== арм {arm} ===") for cls in ("k1", "k2"): snyat = vosst = vypal = tot = 0 rows = [] for k in sorted(P.DEFECTS): o = out_of(f"{arm}-w{k}") if o is None: continue for c, old, new, bad_rx, fix_rx in P.DEFECTS[k]: if c != cls: continue tot += 1 still = bool(re.search(bad_rx, o)) restored = bool(re.search(fix_rx, o)) if not still: snyat += 1 if restored: vosst += 1 rows.append(f"w{k}:восст") else: vypal += 1 rows.append(f"w{k}:ВЫПАЛ") else: rows.append(f"w{k}:жив") if tot: print(f" {cls}: снят {snyat}/{tot} · ВОССТАНОВЛЕН {vosst}/{tot} · выпал {vypal} " + " ".join(rows)) if __name__ == "__main__": validate_regexes() for arm in sys.argv[1:] or ["edp-A0", "edp-A1", "edp-A2", "edp-A3", "edp-A4", "edp-A5"]: score(arm)