# BuildWithThis check script for 'Check grammar and spelling' (test script v1, frozen 2026-10-16).
# Usage: python grammar-checks.py <results.json> <gnu-time-v file> <tool>; reads testset.json (published as grammar-test-set.json).
# Check script for check-grammar-and-spelling (frozen v1). Usage: check_grammar.py <results.json> <time-v file> <tool>
import json, re, sys, statistics
d=json.load(open('testset.json')); R=json.load(open(sys.argv[1])); tool=sys.argv[3]
def span(e):
    m=re.search(r'(?<!\w)'+re.escape(e['err'])+r'(?!\w)', e['text']) if e['err'][0].isalnum() else re.search(re.escape(e['err']),e['text'])
    return m.start(), m.end()
def apply(text,f,sug):
    a,b=f['offset'],f['offset']+f['length']
    if isinstance(sug,str): return text[:a]+sug+text[b:]
    if sug['kind']=='remove': return text[:a]+text[b:]
    if sug['kind']=='insert_after': return text[:b]+sug['text']+text[b:]
    return text[:a]+sug['text']+text[b:]
def norm(s): return re.sub(r'\s+',' ',s).strip()
res={'per_item':{}}; caught=fixed=0; cat={}
for e in d['errors']:
    a,b=span(e); want=e['text'][:a]+e['fix']+e['text'][b:]
    flags=R['results'][e['id']]; hit=[f for f in flags if f['offset']<b and f['offset']+f['length']>a]
    c=bool(hit); fx=any(f['suggestions'] and norm(apply(e['text'],f,f['suggestions'][0]))==norm(want) for f in hit)
    caught+=c; fixed+=fx; cat.setdefault(e['cat'],[0,0]); cat[e['cat']][0]+=c; cat[e['cat']][1]+=1
    res['per_item'][e['id']]={'caught':c,'fixed':fx,'flags':[(f['offset'],f['length'],f['message'][:80],[s if isinstance(s,str) else s['text'] for s in f['suggestions'][:2]]) for f in flags]}
fa=[k for k in R['results'] if k.startswith('cl') and R['results'][k]]
for k in fa: res['per_item'][k]={'flags':[(f['offset'],f['length'],f['message'][:80]) for f in R['results'][k]]}
allflags=[f for v in R['results'].values() for f in v]
med=statistics.median(R['ms'].values())
tv=open(sys.argv[2]).read(); kb=int(re.search(r'Maximum resident set size \(kbytes\): (\d+)',tv).group(1))
res['G1']={'pass':len(R['results'])==60}
res['G2']={'pass':caught>=28,'caught':caught}
res['G3']={'pass':fixed>=24,'fixed':fixed}
res['G4']={'pass':cat['spelling'][0]>=9,'spelling_caught':cat['spelling'][0]}
res['G5']={'pass':len(fa)<=3,'false_alarm_sentences':len(fa),'ids':fa}
res['G6']={'pass':med<=200,'median_ms':round(med,1)}
res['G7']={'pass':kb<=2*1024*1024,'peak_mb':round(kb/1024)}
res['Q5_auto']={'pass':all(f['message'].strip() for f in allflags),'flags':len(allflags)}
res['by_category']=cat; res['passed']=sum(res[f'G{i}']['pass'] for i in range(1,8)); res['tool']=tool
out=sys.argv[1].replace('.json','-checks.json'); json.dump(res,open(out,'w'),indent=1)
print(json.dumps({k:v for k,v in res.items() if k!='per_item'},indent=1))
