# -*- coding: utf-8 -*-
"""Spike: pick screenshot moments from FIT volatility instead of a fixed
interval. Validation = do the picked windows line up with the moments we
already KNOW mattered in this ride (43s attack, 101s surge, 126s big effort,
148s max speed, 210s finish)?"""
import json
import sys
from pathlib import Path

sys.stdout.reconfigure(encoding="utf-8")

win = json.loads(Path(r"C:\ai\AUTOMOVIE\app\projects\20260802_183358\window.json")
                 .read_text(encoding="utf-8"))
by_t = {}
for r in win:
    t = int(round(r["vt"]))
    if 0 <= t:
        by_t[t] = r
T = max(by_t)


def series(key):
    out, last = [], 0.0
    for t in range(T + 1):
        v = (by_t.get(t) or {}).get(key)
        if v is not None:
            last = v
        out.append(last)
    return out


pwr, hr, cad, spd = series("pwr"), series("hr"), series("cad"), series("spd_kmh")


def volatility(sig, half=4):
    """local range (max-min) in a ±half-second window, normalised 0..1."""
    out = []
    for t in range(len(sig)):
        w = sig[max(0, t - half):t + half + 1]
        out.append(max(w) - min(w))
    m = max(out) or 1
    return [v / m for v in out]


v_pwr = volatility(pwr)
v_hr = volatility(hr, half=8)      # HR moves slower
v_cad = volatility(cad)
v_spd = volatility(spd)

score = [0.45 * a + 0.15 * b + 0.2 * c + 0.2 * d
         for a, b, c, d in zip(v_pwr, v_hr, v_cad, v_spd)]

# pick bursts: greedy top-score, suppress ±10s around each pick
picked = []
order = sorted(range(len(score)), key=lambda t: -score[t])
BURST = 6            # 每個重點時段連拍秒數
MAX_BURSTS = 12
for t in order:
    if len(picked) >= MAX_BURSTS:
        break
    if all(abs(t - p) > 10 for p in picked):
        picked.append(t)
picked.sort()

KNOWN = {43: "572W攻擊", 50: "543W接上", 70: "490W跟上", 101: "452W試探",
         126: "571W大爆發", 148: "極速57.6", 210: "終點衝刺"}

print(f"影片 {T}s，挑出 {len(picked)} 個連拍時段（每段 {BURST} 張）"
      f"= {len(picked)*BURST} 張")
print(f"對比固定 1 秒間隔的 {T} 張：省 {(1-len(picked)*BURST/T)*100:.0f}%\n")
print(f"{'連拍時段':<14}{'分數':<7}{'該刻功率':<9}對應已知劇情點")
for t in picked:
    a, b = max(0, t - BURST // 2), min(T, t + BURST // 2)
    near = [f"{v}({k}s)" for k, v in KNOWN.items() if abs(k - t) <= 6]
    print(f"t={a:>3}~{b:<7} {score[t]:.2f}   {pwr[t]:>5.0f}W   "
          f"{'✓ ' + ', '.join(near) if near else '（數據波動點）'}")

hit = sum(1 for k in KNOWN if any(abs(k - t) <= 6 for t in picked))
print(f"\n已知 {len(KNOWN)} 個劇情點命中 {hit} 個")
