#!/usr/bin/env python3
"""analyze_gamepad_runs.py — 2026-11-03 のゲームパッドの実機の記録 (log.jsonl) 5 本を読み, 送る間隔・長押しの速さ・止まった所を数える (LOG436)

  python3 analyze_gamepad_runs.py <gamepad_teleop のフォルダ>
"""
import json
import os
import statistics as st
import sys

RUNS = ["teleop_20261103_071424", "teleop_20261103_074936", "teleop_20261103_075657",
        "teleop_20261103_080648", "teleop_20261103_080930"]


def load(root, run):
    rows = [json.loads(l) for l in open(os.path.join(root, run, "log.jsonl"), encoding="utf-8")]
    meta = json.load(open(os.path.join(root, run, "meta.json"), encoding="utf-8"))
    return rows, meta


def fmt(a):
    return " ".join("{:+7.2f}".format(x) for x in a)


def main(root):
    print("## 1. 記録ごとのまとめ")
    print("| 記録 | コミット | 1押しの刻み | 行 | 送った | 受付なし(busy) | 長押しの送る間隔 中央/90% (秒) | 届くまで1秒超 | 押してから送るまで 中央/最大 (秒) |")
    print("|---|---|---|---|---|---|---|---|---|")
    for run in RUNS:
        rows, meta = load(root, run)
        mv = [r for r in rows if r["kind"] == "move"]
        sent = [r for r in mv if r.get("sent") is True]
        busy = sum(1 for r in mv if r.get("reason") == "busy")
        by = {}
        for r in sent:
            if r.get("hold_id") is not None:
                by.setdefault(r["hold_id"], []).append(r)
        gaps = []
        for rs in by.values():
            ts = sorted(x["t_send"] for x in rs if x.get("t_send"))
            gaps += [b - a for a, b in zip(ts, ts[1:])]
        lat = [r["t_send"] - r["t_unix"] for r in sent if r.get("t_send")]
        long_ = sum(1 for r in sent if (r.get("elapsed_sec") or 0) > 1)
        g = "{:.3f} / {:.3f}".format(st.median(gaps), sorted(gaps)[int(len(gaps) * 0.9)]) if gaps else "-"
        print("| {} | {} {} | {}° | {} | {} | {} | {} | {} | {:.3f} / {:.2f} |".format(
            run, meta["git"]["commit"][:7], "" if meta["git"]["script_status"] == "clean" else "(変更あり)",
            meta["motion"]["step_fine_deg"], len(rows), len(sent), busy, g, long_, st.median(lat), max(lat)))

    print("\n## 2. 長押し (5 回以上送ったもの) の速さ = 動かした関節の進んだ角度 ÷ かかった時間")
    for run in RUNS[1:]:
        rows, _ = load(root, run)
        by = {}
        for r in rows:
            if (r["kind"] == "move" and r.get("sent") is True and r.get("hold_id") is not None
                    and (r.get("hold_n") or 0) >= 1 and r.get("measured_before")):
                by.setdefault(r["hold_id"], []).append(r)
        sp = []
        for rs in by.values():
            if len(rs) < 5:
                continue
            j = rs[0]["joint"]
            d = abs(rs[-1]["measured_before"][j] - rs[0]["measured_before"][j])
            t = rs[-1]["t_send"] - rs[0]["t_send"]
            if t > 0:
                sp.append(d / t)
        if sp:
            print("- {}: 長押し {} 回・中央 {:.1f}°/秒・最小 {:.1f}・最大 {:.1f}".format(run, len(sp), st.median(sp), min(sp), max(sp)))
        else:
            print("- {}: 5 回以上の長押しなし".format(run))

    print("\n## 3. 届くまで 1 秒を超えた送信 (指令が無視されたもの)")
    for run in RUNS:
        rows, _ = load(root, run)
        t0 = rows[0]["t_unix"]
        for r in rows:
            if r["kind"] == "move" and r.get("sent") is True and (r.get("elapsed_sec") or 0) > 1:
                print("- {} {:7.2f}秒 j{} {:+.1f}° 長押し {}/{} 届くまで {} 秒 ずれ {}°".format(
                    run, r["t_unix"] - t0, r["joint"], r["delta"], r.get("hold_id"), r.get("hold_n"),
                    r["elapsed_sec"], r.get("reach_err")))
                print("    送る前   " + fmt(r["measured_before_send"]))
                print("    指令     " + fmt(r["command"]))
                print("    届いた   " + fmt(r["reached_angles"]))

    print("\n## 4. 押してから送るまで 1 秒を超えたもの (角度の読み取りが続けて失敗した)")
    for run in RUNS:
        rows, _ = load(root, run)
        t0 = rows[0]["t_unix"]
        for r in rows:
            if r["kind"] == "move" and r.get("t_send") and r["t_send"] - r["t_unix"] > 1:
                print("- {} {:7.2f}秒に押した j{} → 送ったのは {:.2f}秒 ({:.2f} 秒あと)".format(
                    run, r["t_unix"] - t0, r["joint"], r["t_send"] - t0, r["t_send"] - r["t_unix"]))

    print("\n## 5. 0.5° の押しで, 送る前と届いた角度が変わったか (1 押し 0.5° の 2 本)")
    for run in RUNS[:2]:
        rows, _ = load(root, run)
        moved = same = 0
        for r in rows:
            if r["kind"] == "move" and r.get("sent") is True and abs(r["delta"]) == 0.5 and r.get("reached_angles"):
                j = r["joint"]
                if abs(r["reached_angles"][j] - r["measured_before_send"][j]) < 0.2:
                    same += 1
                else:
                    moved += 1
        print("- {}: 0.5° の送信 {} 回のうち, 読んだ角度が 0.2° 以上動いたのは {} 回".format(run, moved + same, moved))


if __name__ == "__main__":
    main(sys.argv[1])
