"""LOG401: 2026-10-29 の π0.5 実機の回をすべて 1 行ずつの表にする (読むだけ).
runs/pi05_policy/pi05_20261029_*/log.jsonl を読み, 回ごとに
 写り方の確認 (response と, 確認を外したか) / 動かしたチャンク数 / 閉じる指令・開く指令のチャンク /
 推論時間 (中央値・最大) / 中継点の未到達 (8 秒以内に着かなかった数) /
 閉じる前と閉じたあとの, 手首 j4 の目標と実測の差の最大
を出す. 結果 (入った・入らなかった) は, 目で見た結果をここに書き写したもの.
"""
import json, glob, os
import numpy as np
ROOT = os.environ.get("R2R2R_DATA", "/Volumes/KIOXIA/r2r2r-data")
RUNS = ROOT + "/runs/pi05_policy"
# 目で見た結果 (エイイチの報告と横からの動画). 位置と何回目か, 結果, ひとこと
SEEN = {
    "115823": ("C", 1, "入った", "持ち上げて箱の上で離した"),
    "120644": ("C", 2, "入った", "離す前に爪から抜け, 箱の中に落ちた"),
    "121202": ("C", 3, "入った", "箱の上で離した"),
    "121650": ("C", 4, "入った", "箱の上で離した"),
    "122156": ("C", 5, "入った", "つかむときブロックが爪に引っかかったが, 箱に入れた"),
    "122909": ("D", 1, "入らなかった", "爪がブロックの手前で閉じた"),
    "123158": ("D", 2, "入らなかった", "爪の先でつかみ, 持ち上げた瞬間に手先が跳ね上がって落とした"),
    "124104": ("D", 3, "入らなかった", "爪の先でつかみ, 持ち上げた瞬間に手先が跳ね上がって落とした"),
    "124830": ("D", 4, "入った", "箱の上で離した"),
    "125314": ("D", 5, "入らなかった", "つかみ損ね"),
    "125528": ("D", 6, "数に入れない", "5 回の外. 手首 j4 が 36.5 度手前で止まり, ブロックの上に来る前に閉じたので止めた"),
    "145207": ("E", 1, "入った", "箱の上で離した"),
    "145641": ("E", 2, "入らなかった", "爪がブロックの奥側に下りて閉じた"),
    "145851": ("E", 3, "入った", "箱の上で離した"),
    "150534": ("E", 4, "入った", "箱の上で離した"),
    "150950": ("E", 5, "入らなかった", "爪がブロックの奥側に下りて閉じた"),
}
def vias_of(c):
    return [v for v in (c.get("vias") or []) if v.get("called")]
print("run       位置 回 結果          写り方(resp/外した) chunk 閉 開  推論ms(中央/最大) 未到達 j4差(閉じる前/後) ひとこと")
for d in sorted(glob.glob(RUNS + "/pi05_20261029_*")):
    stem = os.path.basename(d)[-6:]
    L = [json.loads(l) for l in open(d + "/log.jsonl")]
    fr = [l for l in L if l.get("type") == "framing"]
    ch = [l for l in L if "chunk" in l]
    ex = [c for c in ch if c.get("executed")]
    resp = f"{fr[0]['response']:.3f}/{'外した' if fr[0].get('ignored') else '-'}" if fr else "-"
    if not fr or (not fr[0]["ok"] and not fr[0].get("ignored")):
        why = "写り方の確認で止まった (アームは動いていない)" if fr else "記録なし"
    elif not ch:
        why = "最初のチャンクを送る前に止めた (アームは動いていない)"
    else:
        why = ""
    close = [c["chunk"] for c in ch if c.get("grip_cmd") == 1]
    opn = [c["chunk"] for c in ch if c.get("grip_cmd") == 0]
    lat = [c["latency_s"] * 1000 for c in ch if "latency_s" in c]
    miss = sum(1 for c in ex for v in vias_of(c) if not v.get("success"))
    c0 = close[0] if close else 10**9
    pre = [abs(v["actual_after"][4] - v["target"][4]) for c in ex if c["chunk"] <= c0 for v in vias_of(c) if v.get("actual_after")]
    post = [abs(v["actual_after"][4] - v["target"][4]) for c in ex if c["chunk"] > c0 for v in vias_of(c) if v.get("actual_after")]
    pos, n, res, note = SEEN.get(stem, ("-", "-", "-", why))
    lat_s = f"{np.median(lat):5.0f}/{max(lat):5.0f}" if lat else "    -/    -"
    print(f"{stem}   {pos}   {n}  {res:12s}  {resp:18s} {len(ex):3d}  {str(close[0]) if close else '-':>2s} {str(opn[0]) if opn else '-':>2s}  {lat_s}       {miss}     "
          f"{(max(pre) if pre else 0):5.1f}/{(max(post) if post else 0):5.1f}   {note}")
print()
print("位置ごとのまとめ (数に入れない回を除く)")
for p in "CDE":
    rs = [v for v in SEEN.values() if v[0] == p and v[2] != "数に入れない"]
    print(f"  位置{p}: {sum(1 for v in rs if v[2] == '入った')}/{len(rs)}")
allr = [v for v in SEEN.values() if v[2] != "数に入れない"]
print(f"  合計: {sum(1 for v in allr if v[2] == '入った')}/{len(allr)}")
