#!/usr/bin/env python3 """Offline inspection: histogram of scenario_title_score for catalog plays. Helps tune ``SCENARIO_TITLE_SURFACE_THRESHOLD`` in ``backend/scenarios.py``. Usage: KINK_SKIP_HEAVY_WARM=1 python scripts/inspect_scenario_title_surface.py --db data/store_slim.db KINK_SKIP_HEAVY_WARM=1 python scripts/inspect_scenario_title_surface.py --db data/store_slim.db --near 0.38 --sample 25 """ from __future__ import annotations import argparse import os from collections import Counter from pathlib import Path def main() -> int: ap = argparse.ArgumentParser(description=__doc__) ap.add_argument("--db", type=Path, required=True, help="path to SQLite store (e.g. data/store_slim.db)") ap.add_argument( "--bin", type=float, default=0.05, help="histogram bucket width in score units (default 0.05)", ) ap.add_argument( "--near", type=float, default=0.0, help="if > 0, print up to --sample rows with score in [near-bin, near+bin]", ) ap.add_argument("--sample", type=int, default=20, help="max rows to print for --near") args = ap.parse_args() db = args.db.resolve() if not db.is_file(): raise SystemExit(f"database not found: {db}") os.environ.setdefault("KINK_SKIP_HEAVY_WARM", "1") from backend.core import Backend from backend.scenarios import SCENARIO_TITLE_SURFACE_THRESHOLD, scenario_title_fields b = Backend(db) b._catalog() plays = [k for k in b._catalog()["detail_by_id"].values() if b._content_kind(k) == "play"] rows: list[tuple[float, bool, bool, str, str]] = [] for k in plays: score, surf = scenario_title_fields(str(k.get("name", ""))) rows.append((score, surf, bool(k.get("is_scenario")), str(k.get("id", "")), str(k.get("name", "")))) print(f"plays: {len(rows)} threshold: {SCENARIO_TITLE_SURFACE_THRESHOLD}") surf_n = sum(1 for r in rows if r[1]) linked_n = sum(1 for r in rows if r[2]) print(f"title_surface_as_scenario (computed): {surf_n} is_scenario (DB): {linked_n}") w = max(args.bin, 1e-6) hist: Counter[str] = Counter() for score, _, _, _, _ in rows: bkt = int(score / w) * w hist[f"{bkt:.3f}-{bkt + w:.3f}"] += 1 print("\nhistogram (score range -> count):") for label in sorted(hist.keys(), key=lambda s: float(s.split("-")[0])): print(f" {label}: {hist[label]}") if args.near > 0: lo, hi = args.near - w, args.near + w near = [(s, sid, name) for s, _, _, sid, name in rows if lo <= s <= hi] near.sort(key=lambda t: t[0], reverse=True) print(f"\nsample scores in [{lo:.4f}, {hi:.4f}] (up to {args.sample}):") for s, sid, name in near[: args.sample]: print(f" {s:.4f}\t{sid}\t{name}") return 0 if __name__ == "__main__": raise SystemExit(main())