"""Build the Cycle 26 forecast register (CSV) and summary from c26_forecasts.jsonl (compiled 2026-10-02).
Output: c26_register.csv, printed summary."""
import json, csv, os, numpy as np
HERE = os.path.dirname(os.path.abspath(__file__))
D = [json.loads(l) for l in open(os.path.join(HERE, 'c26_forecasts.jsonl'), encoding='utf-8')]
def f(x):
    try: return float(str(x).strip())
    except ValueError: return None
rows = []
for d in sorted(D, key=lambda d: d.get('issued_date', '')):
    v, lo, hi = f(d.get('amp_value')), f(d.get('amp_low')), f(d.get('amp_high'))
    rows.append(dict(issued=d.get('issued_date', ''), authors=d.get('authors', ''), method_class=d.get('method_class', ''),
                     amp=v if v is not None else '', low=lo if lo is not None else '', high=hi if hi is not None else '',
                     interval_meaning=d.get('interval_meaning', ''), smoothing=d.get('smoothing', ''), sn_version=d.get('sn_version', ''),
                     qualitative=d.get('qualitative', ''), source_checked=d.get('source_checked', ''), doi_or_url=d.get('doi_or_url', ''),
                     quote=d.get('quote', ''), notes=d.get('notes', '')))
with open(os.path.join(HERE, 'c26_register.csv'), 'w', newline='', encoding='utf-8') as fh:
    w = csv.DictWriter(fh, fieldnames=list(rows[0])); w.writeheader(); w.writerows(rows)
N = [r for r in rows if r['amp'] != '']
v = np.array([r['amp'] for r in N])
print(f'{len(rows)} records, {len(N)} numeric; median {np.median(v):.1f}, mean {v.mean():.1f}, IQR {np.percentile(v,25):.0f}-{np.percentile(v,75):.0f}, '
      f'range {v.min():.0f}-{v.max():.0f}; below climatology 178: {np.mean(v < 178):.0%}; below C25 160.9: {np.mean(v < 160.9):.0%}')
I = [r for r in N if r['low'] != '' and r['high'] != '']
hw = np.array([(r['high'] - r['low']) / 2 for r in I])
print(f'{len(I)} numeric with bounds; half-widths: median {np.median(hw):.1f}; <25: {np.sum(hw < 25)}; >=40: {np.sum(hw >= 40)}')
for r, h in sorted(zip(I, hw), key=lambda t: t[1]):
    print(f"   {r['issued']} {r['authors'][:28]:28s} {r['amp']:7.1f} [{r['low']}, {r['high']}] half-width {h:5.1f} ({r['interval_meaning']}, {r['method_class']})")
