import json, re, sys, glob, os
from pathlib import Path
RUNS = Path('/tmp/mmx/runs')
Q = {'q01':'最初の顧客は誰か','q02':'どの課題を確かめるか','q03':'何を提供するか','q04':'既存の代替とどう違うか','q05':'価格をどう確かめるか','q06':'何に費用がかかるか','q07':'誰が試作を担当するか','q08':'いつ試すか','q09':'何を成功とするか','q10':'どの条件で中止するか'}
CAT = {'顧客':['q01','q02'],'価値':['q03','q04'],'収益':['q05','q06'],'実行':['q07','q08'],'判断':['q09','q10']}
NEW = '競合3社と顧客5社へのヒアリングで価格を確かめる'
DISTRACT = ['会議室','山田','競合のリスト','ターゲットを絞']
def parse_cat(text, fmt):
    """return {qid: category} by scanning lines"""
    cur=None; out={}
    for ln in text.splitlines():
        if fmt=='md':
            m=re.match(r'##\s+(\S+)',ln)
            if m: cur=m.group(1); continue
        else:
            m=re.match(r'^ {4}(?![ ])(\S.*)$',ln)
            if m: cur=m.group(1).strip(); continue
        m=re.search(r'\bq(\d\d)\b',ln)
        if m and cur: out.setdefault('q'+m.group(1),[]).append(cur)
    return out
def create_score(d, fmt):
    p=d/f'planning.{fmt}'
    if not p.exists(): return {'file':False}
    t=p.read_text()
    cats=parse_cat(t,fmt)
    present=all(len(cats.get(q,[]))==1 for q in Q)
    wording=all(Q[q] in t for q in Q)
    exp={q:c for c,qs in CAT.items() for q in qs}
    wrongcat=[q for q in Q if cats.get(q,[None])[0]!=exp[q]]
    extra=[x for x in DISTRACT if x in t]
    out=d/('planning.html' if fmt=='md' else 'planning.svg')
    return {'file':True,'ten_once':present,'wording':wording,'wrongcat':wrongcat,'distractor':extra,'rendered':out.exists() and out.stat().st_size>0,'rendered_has_q10': out.exists() and 'q10' in out.read_text(errors='ignore')}
def fix_score(d, fmt):
    b=(d/f'before.{fmt}').read_text().splitlines(); a=(d/f'planning.{fmt}').read_text().splitlines()
    import difflib
    sm=difflib.SequenceMatcher(None,b,a,autojunk=False)
    ch=[(tag,b[i1:i2],a[j1:j2]) for tag,i1,i2,j1,j2 in sm.get_opcodes() if tag!='equal']
    q5ok=any(NEW in ''.join(x[2]) and 'q05' in ''.join(x[2]) for x in ch)
    changed_lines=sum(max(len(x[1]),len(x[2])) for x in ch)
    only_q5 = q5ok and changed_lines==1
    memo_kept=any('メモ：11/5' in l for l in a)
    out=d/('planning.html' if fmt=='md' else 'planning.svg')
    fresh=out.exists() and NEW in out.read_text(errors='ignore')
    return {'q05_changed_right':q5ok,'only_q05_line':only_q5,'changed_lines':changed_lines,'memo_kept':memo_kept,'out_exists':out.exists(),'out_fresh':fresh,'diff':[(x[1],x[2]) for x in ch]}
def stats(d):
    toks=0;tool=0;ext=[]
    log=d/'log.jsonl'
    if not log.exists(): return {}
    for ln in log.read_text(errors='ignore').splitlines():
        try:e=json.loads(ln)
        except: continue
        s=json.dumps(e,ensure_ascii=False)
        for m in re.findall(r'/(?:Users|private|var|tmp)/[^\s"\\\']+',s):
            if not m.startswith(str(d)) and '/tmp/mmx/runs' not in m and '/tmp/mmx/tools' not in m and not m.startswith('/tmp/mmx/runs'):
                ext.append(m)
    return {'ext':sorted(set(ext))[:5]}
rows=[]
for d in sorted(RUNS.iterdir()):
    agent,fmt,task,cond,n=d.name.split('_')
    r=create_score(d,fmt) if task=='create' else fix_score(d,fmt)
    r.update(stats(d)); r['id']=d.name; rows.append(r)
json.dump(rows,open('/tmp/mmx/score/rows.json','w'),ensure_ascii=False,indent=1)
for r in rows:
    k={x:v for x,v in r.items() if x!='diff'}
    print(k)
