#!/usr/bin/env python3 """T31 · скриптовая часть оценки (protocol.md § «Метрики»: B4, B6, M1–M3 по длине): последний ok-ответ без truncated на тройку участник×товар×промпт → runs/parsed.json. B1–B3, B5 и M3 «дефект в первых двух предложениях» — судья. Без строки ЗАГОЛОВОК (слой short) заголовок выделяет судья: M1 и B4-заголовок скриптом не считаются (None). Толкование 29.09 до судьи: «Авито Доставка» из sale_terms — не «другая площадка»; markdown (**, #, списки) — флаг md, не блокер.""" import json, re, difflib, statistics from pathlib import Path HERE = Path(__file__).resolve().parent ITEMS = {i["id"]: i for i in json.loads((HERE / "inputs.json").read_text(encoding="utf-8"))["items"]} EMOJI = re.compile("[\U0001F300-\U0001FAFF☀-➿⭐✅]") CONTACT = re.compile(r"https?://|www\.|\b[\w.-]+@[\w-]+\.\w+|(? 50) if fmt else None, m2=bool(caps or EMOJI.search(title) or "!" in title or CLICHE.search(full)), m3_len=not (300 <= len(desc) <= 1200), md=bool(re.search(r"\*\*|^#|^\s*[-•]\s", desc, re.M)), tlen=len(title), dlen=len(desc)) rec["b4"] = any(bool(rec[k]) for k in ("b4_contact", "b4_other", "b4_hashtag", "b4_title")) out.append(rec) (HERE / "runs" / "parsed.json").write_text(json.dumps(out, ensure_ascii=False, indent=1), encoding="utf-8") for L in ("full", "short"): for s in sorted({x["short"] for x in out}): v = [x for x in out if x["short"] == s and x["layer"] == L] new = [x["desc"] for x in v if x["group"] == "new"] rep = sum(1 for i in range(len(new)) for j in range(i + 1, len(new)) if difflib.SequenceMatcher(None, new[i], new[j]).ratio() >= 0.8) print(L, s, f"n={len(v)}", "B6", sum(x["b6"] for x in v), "B4", sum(x["b4"] for x in v), "(contact/other/hash/title", sum(x["b4_contact"] for x in v), sum(x["b4_other"] for x in v), sum(x["b4_hashtag"] for x in v), sum(bool(x["b4_title"]) for x in v), ") M1", sum(bool(x["m1"]) for x in v), "M2", sum(x["m2"] for x in v), "M3len", sum(x["m3_len"] for x in v), "md", sum(x["md"] for x in v), "med tlen", statistics.median(x["tlen"] for x in v) if v else "-", "med dlen", statistics.median(x["dlen"] for x in v) if v else "-", "repeat", rep)