#!/usr/bin/env python3
"""compare_nights.py — LOG384 の比べ（busycheck・すれ違い入と切・v3 と v4）

service_sim/unity/ の中で動かす（台帳と各回の summary.json を読むだけ。何も書かない）。
  python3 compare_nights.py
順位の比べ（U）は「左が右より大きい組の数」。n=5 と 8 なら両側5%で U<=6 か U>=34、
n=10 と 10 なら U<=23 か U>=77、n=20 と 19 ならおよそ U<=120 か U>=260 が目安。
"""
import csv, json, os, statistics as st

ROWS = list(csv.DictReader(open('unity_ledger_v1.csv', encoding='utf-8')))
BY = {r['run_folder']: r for r in ROWS}


def summary(folder):
    try:
        d = json.load(open(os.path.join(folder, 'summary.json'), encoding='utf-8'))
    except (OSError, ValueError):
        return {}
    flat = {}
    def walk(x):
        for k, v in x.items():
            if isinstance(v, dict):
                walk(v)
            else:
                flat.setdefault(k, v)
    walk(d)
    return flat


def U(a, b):
    return sum((x > y) + 0.5 * (x == y) for x in a for y in b)


def med(v):
    return st.median(v) if v else float('nan')


def show(title, a_rows, b_rows, a_name, b_name, metrics):
    print('== %s（%s %d回 / %s %d回）' % (title, a_name, len(a_rows), b_name, len(b_rows)))
    for key, label, src in metrics:
        if src == 'ledger':
            a = [float(r[key]) for r in a_rows]
            b = [float(r[key]) for r in b_rows]
        else:
            a = [float(summary(r['run_folder']).get(key) or 0) for r in a_rows]
            b = [float(summary(r['run_folder']).get(key) or 0) for r in b_rows]
        print('  %-24s %s 中央 %9.3f（%.3f〜%.3f） %s 中央 %9.3f（%.3f〜%.3f） U(%s>%s)=%.1f/%d'
              % (label, a_name, med(a), min(a), max(a), b_name, med(b), min(b), max(b),
                 a_name, b_name, U(a, b), len(a) * len(b)))


LEDGER = [('stuck_count', '動けなくなった', 'ledger'), ('gave_up', '人のあきらめ', 'ledger'),
          ('entry_wait_mean', '入店待ち（分）', 'ledger'), ('robot_share', 'ロボットが運んだ割合', 'ledger'),
          ('rescues', '助けに行った', 'ledger'), ('late_staff_dishes', '店員が遅れて運んだ皿', 'ledger')]

# 1. busycheck（③1台・種1）
b1 = [r for r in ROWS if '_busy1_' in r['run_folder']]
b4 = [r for r in ROWS if '_busy4_' in r['run_folder']]
show('busycheck ③1台・種1', b1, b4, '1本ずつ', '4本同時', LEDGER)

# 2. すれ違い入と切（③2台・2夜分、全員が帰った回だけ）
def p1r2(prefix, on):
    out = []
    for s in range(10):
        f = '%s_fam_p1_r2_s%d%s' % (prefix, s, '_passon' if on else '')
        r = BY.get(f)
        if r and r['everyone_left'] == '1':
            out.append(r)
    return out
off = p1r2('20261027_night_cs21', False) + p1r2('20261028_night_cs25', False)
on = p1r2('20261027_night_cs21', True) + p1r2('20261028_night_cs25', True)
show('すれ違い ③2台・2夜', off, on, '切', '入', LEDGER + [
    ('face_stop_max_s', '向かい合って止まった最長（秒）', 'summary'),
    ('face_stop_count', '向かい合って止まった回数', 'summary'),
    ('timeouts', '往復の時間切れ', 'ledger')])

# 3. v3 と v4（条件ごと）
def night(prefix, on):
    g = {}
    for r in ROWS:
        f = r['run_folder']
        if f.startswith(prefix) and f.endswith('_passon') == on:
            g.setdefault('%s_r%s' % (r['store'], r['robots']), []).append(r)
    return g
v3 = night('20261027_night_cs21_', False)
v4 = night('20261029_night_cs26_', True)
for k in sorted(v4):
    show('v3 と v4 ' + k, v3[k], v4[k], 'v3', 'v4', [
        ('entry_wait_mean', '入店待ち（分）', 'ledger'), ('dish_wait_mean', '料理の待ち（分）', 'ledger'),
        ('stuck_count', '動けなくなった', 'ledger'), ('robot_share', 'ロボットが運んだ割合', 'ledger'),
        ('gave_up', '人のあきらめ', 'ledger'), ('warped', '瞬間移動', 'ledger'),
        ('timeouts', '往復の時間切れ', 'ledger'),
        ('face_stop_max_s', '向かい合って止まった最長（秒）', 'summary')])
