# サイトの試算（SimPy）と Unity の3Dシミュレーションの数字を、同じ条件で並べる。
# 入力：KIOXIA の台帳 unity_ledger_v1.csv（Unity の値と、同じ条件の試算の値 site_* が1行に入っている）
# 対象：直近の2つの夜（20261106_busy・20261107_staff）。どちらも6店 × 条件 × 種10
import csv, sys, statistics as st
from collections import defaultdict

LEDGER = sys.argv[1] if len(sys.argv) > 1 else 'unity_ledger_v1.csv'
NIGHTS = ('20261106', '20261107')
STORE = {'fam_p0': '②定番の郊外型', 'fam_p1': '③効率重視・入口が角', 'fam_p2': '④効率重視・小さめの店',
         'fam_p3': '⑤ゆったり・入口が正面', 'fam_p4': '⑥ゆったり・入口が横', 'fam_p5': '⑦効率重視・席を詰めた店'}

rows = [r for r in csv.DictReader(open(LEDGER, encoding='utf-8'))
        if r['run_folder'].startswith(NIGHTS) and r['status'] == 'completed']
f = lambda r, k: float(r[k]) if r[k] not in ('', None) else None

# 条件ごとに種10本を平均する
g = defaultdict(list)
for r in rows:
    key = (r['run_folder'][:8], r['store'], int(r['staff']), int(r['robots']), int(r['arrivals_per_h']))
    g[key].append(r)

def mean(rs, k):
    v = [f(r, k) for r in rs if f(r, k) is not None]
    return st.mean(v) if v else None

print(f'行数 {len(rows)}・条件 {len(g)}（種ごとの平均で比べる）')
print()
print('■ 条件ごとの平均（分）。U=Unity・S=サイトの試算')
print('夜,店,スタッフ,ロボット,来店/時,種,入店待ちU,入店待ちS,料理の待ちU,料理の待ちS,会計待ちU,会計待ちS,動けなくなった/往復')
for key in sorted(g):
    rs = g[key]
    trips = sum(f(r, 'trips') or 0 for r in rs); stuck = sum(f(r, 'stuck_count') or 0 for r in rs)
    vals = [mean(rs, k) for k in ('entry_wait_mean', 'site_entry_wait_mean', 'dish_wait_mean', 'site_dish_wait_mean', 'pay_wait_mean', 'site_pay_wait_mean')]
    print(','.join([key[0], STORE[key[1]], str(key[2]), str(key[3]), str(key[4]), str(len(rs))] +
                   ['' if v is None else f'{v:.2f}' for v in vals] + [f'{stuck/trips:.3f}' if trips else '']))

# 人だけ（ロボット0台）の条件で、Unity が試算の何倍か
print()
print('■ ロボット0台の条件で、Unity ÷ 試算（入店待ちが試算で0.5分以上の条件だけ）')
ratios = defaultdict(list)
for key, rs in g.items():
    if key[3] != 0: continue
    u, s = mean(rs, 'entry_wait_mean'), mean(rs, 'site_entry_wait_mean')
    if u is not None and s and s >= 0.5: ratios[key[1]].append(u / s)
for k in sorted(ratios):
    v = ratios[k]; print(f'{STORE[k]}：{len(v)}条件・中央値 {st.median(v):.2f} 倍（{min(v):.2f}〜{max(v):.2f}）')

# 0台 → 2台で入店待ちが増えるか減るか、向きがそろうか
print()
print('■ 0台 → 2台で、入店待ちが減るか増えるかの向き（差が0.1分未満は「変わらない」）')
def sign(d): return 0 if abs(d) < 0.1 else (1 if d > 0 else -1)
same = total = 0; diff = []
for key, rs in g.items():
    if key[3] != 0: continue
    k2 = (key[0], key[1], key[2], 2, key[4])
    if k2 not in g: continue
    du = mean(g[k2], 'entry_wait_mean') - mean(rs, 'entry_wait_mean')
    ds = mean(g[k2], 'site_entry_wait_mean') - mean(rs, 'site_entry_wait_mean')
    total += 1
    if sign(du) == sign(ds): same += 1
    else: diff.append((key, round(du, 2), round(ds, 2)))
print(f'向きが同じ {same} / {total} 組')
for key, du, ds in sorted(diff):
    print(f'  違う：{key[0]} {STORE[key[1]]} スタッフ{key[2]} 来店{key[4]}/時　Unity {du:+.2f} 分・試算 {ds:+.2f} 分')

# ロボットが動けなくなった（60秒）割合を店ごとに
print()
print('■ ロボットありの回で、動けなくなった（60秒）回数 ÷ 往復の回数（店ごと）')
acc = defaultdict(lambda: [0.0, 0.0])
for r in rows:
    if int(r['robots']) == 0: continue
    acc[r['store']][0] += f(r, 'stuck_count') or 0; acc[r['store']][1] += f(r, 'trips') or 0
T = [0, 0]
for k in sorted(acc):
    s, t = acc[k]; T[0] += s; T[1] += t
    print(f'{STORE[k]}：{s:.0f} / {t:.0f} = {s/t:.1%}')
print(f'6店まとめて：{T[0]:.0f} / {T[1]:.0f} = {T[0]/T[1]:.1%}')
