"""Count how many name / jargon mentions survive in a transcript set (English corpus).

Matching: case-insensitive, whole word (regex \b...\b). A possessive counts as a mention ("Aoife's" contains the name
spelled right, and \b stops at the apostrophe), so "Aoife's intern weekly report" is one Aoife mention in the script
and is correct in a transcript only if the transcript also has "Aoife" (with or without 's). Spaces inside multi-word
terms may also be hyphens or missing ("KV cache" = "KV-cache" = "KVcache"). "terminal" is in the terms list for 2.6 but
is not scored. A memo's mention count is correct up to min(script count, transcript count).
Because matching ignores case, "Lora" counts as LoRA and "VLLM" as vLLM; the strict (case-sensitive) count is reported
alongside as `correct_case_sensitive`.
Usage: score_names.py [transcripts_grok.json ...]  (default: every transcripts_*.json here) -> name_scores.json"""
import json, pathlib, re, sys
HERE = pathlib.Path(__file__).resolve().parent
d = json.load(open(HERE / 'memos.json', encoding='utf-8'))
NAMES, TERMS = list(d['people']), [t for t in d['terms'] if t != 'terminal']

def pat(v, flags):
    body = r'[\s-]*'.join(re.escape(w) for w in v.split())
    return re.compile(rf'\b{body}\b', flags)

def score(trans, vocab, flags=re.I, ids=None):
    tot = hit = 0; misses = {}; survived = {}
    for m in d['memos']:
        if ids and m['id'] not in ids:
            continue
        for v in vocab:
            p = pat(v, flags)
            n = len(p.findall(m['text']))
            if not n: continue
            k = min(n, len(p.findall(trans.get(m['id'], ''))))
            tot += n; hit += k
            if k: survived[v] = survived.get(v, 0) + k
            if k < n: misses[v] = misses.get(v, 0) + n - k
    return tot, hit, misses, survived

if __name__ == '__main__':
    out = {}
    wl = {m['id'] for m in d['memos'] if m['set'] in 'WL'}
    for f in sys.argv[1:] or sorted(p.name for p in HERE.glob('transcripts_*.json')):
        t = json.load(open(HERE / f, encoding='utf-8'))
        for label, vocab in [('names', NAMES), ('terms', TERMS)]:
            tot, hit, miss, surv = score(t, vocab, ids=wl)
            _, strict, _, _ = score(t, vocab, flags=0, ids=wl)
            out[f'{f}:{label}'] = {'total': tot, 'correct': hit, 'correct_case_sensitive': strict, 'misses': miss, 'survived': surv}
            print(f'{f:28s} {label:5s} {hit}/{tot} (case-sensitive {strict})  survived={surv}  misses={miss}')
    json.dump(out, open(HERE / 'name_scores.json', 'w', encoding='utf-8'), ensure_ascii=False, indent=1)
