"""judges.py -- a panel of judges that look at a finished build and nothing else (Ivy, Oct 23 2026, after the outside reviews: "Could
have three judges. One cares about complexity, another about elegance, another about surprising use of lego etc.").

Each judge sees ONLY the build's picture: no title, no notebook, no player -- so nothing Pin wrote can talk a judge into a score
(the reviewers' guard). Each returns 0-10 and one line why. Kept separate, never summed into one number: a build can win one voice.

    python3 judges.py RUN [RUN ...]      -> scores to stdout and runs/RUN/judges.json
Written by Iris."""
import os, sys, json, re, glob, time
HERE = os.path.dirname(os.path.abspath(__file__))
sys.path.insert(0, os.path.join(os.path.dirname(HERE), 'favorites'))
os.environ.setdefault('HAIKU', 'claude-haiku-4-5-20251001')
import haiku as H

JUDGES = {
    'complexity': "You judge COMPLEXITY in Lego builds: how intricate and ambitious the construction is -- many parts working "
                  "together, layers, depth front to back, sub-assemblies, structure you have to look at twice to understand.",
    'elegance':   "You judge ELEGANCE in Lego builds: how much it achieves with how little -- economy, clean lines, every piece "
                  "earning its place, a confident idea said simply. Lots of parts is not a virtue here.",
    'npu':        "You judge NPU -- 'nice part usage', as Lego fans say: parts used as something they were never made for (a slope "
                  "as a beak, a wheel as an eye), clever or unexpected techniques, connections a builder would grin at.",
    'fun':        "You judge FUN in Lego builds: would a stranger looking at this smile, laugh, or say 'oh, that's fun!'? "
                  "Character, wit, charm, a sense that something is happening.",
}

def picture(run):
    """the LAST frame of the build (its multi-view picture if that frame has one). Oct 23 2026: preferring any *_views picture first
    showed the judges the scarecrow's turn-0 base, because that run only made a views picture for frame 00."""
    d = os.path.join(HERE, 'runs', run)
    if os.path.exists(os.path.join(d, 'frame_end.png')): return os.path.join(d, 'frame_end.png')
    nums = sorted({int(m.group(1)) for f in os.listdir(d) for m in [re.match(r'frame_(\d\d)(_views)?\.png$', f)] if m})
    if not nums: return None
    n = nums[-1]; v = os.path.join(d, f'frame_{n:02d}_views.png')
    return v if os.path.exists(v) else os.path.join(d, f'frame_{n:02d}.png')

def judge(run, who=tuple(JUDGES)):
    png = picture(run)
    if not png: return None
    out = {}
    for name in who:
        q = (JUDGES[name] + " Look ONLY at this picture of a Lego build (it may show several views of the same build). You are "
             "told nothing else about it. Be a real judge: most builds are middling, use the whole 0-10 range. Answer ONLY with JSON: "
             '{"score": <0-10>, "why": "<one sentence about what you actually see>"}')
        for wait in (0, 15, 45):
            time.sleep(wait)
            try:
                t, _ = H.ask(q, [png], 150)
                m = re.search(r'\{.*\}', t, re.S); a = json.loads(m.group(0)); out[name] = {'score': float(a['score']), 'why': a.get('why', '')}
                break
            except Exception as e: out[name] = {'score': None, 'why': f'failed: {str(e)[:60]}'}
    json.dump({'picture': os.path.basename(png), **out}, open(os.path.join(HERE, 'runs', run, 'judges.json'), 'w'), indent=1)
    return out

if __name__ == '__main__':
    for run in sys.argv[1:]:
        r = judge(run)
        if r is None: print(run, 'no picture'); continue
        print(run + ':  ' + '  '.join(f"{k} {v['score']}" for k, v in r.items()))
        for k, v in r.items(): print(f'    {k:10s} {v["why"]}')
