Spaces:
Sleeping
Sleeping
| # -*- coding: utf-8 -*- | |
| """BG30 Bước 1.1 — bảng đối chiếu quy ước φ trên 5 điểm dữ liệu thật. | |
| Câu hỏi (BRIEF 30): Δφ model↔analytic chụm ~140–149° trên clip thật có phải | |
| lỗi quy ước/mirror không? So φ model với 4 phép biến đổi của φ analytic: | |
| {φ, −φ mod 360, φ+180, 180−φ} | |
| (−φ = lật trục x; 180−φ = lật trục y; φ+180 = xoay 180° — xoay 180° là | |
| nhập nhằng VÔ HẠI duy nhất của quy ước chấm góc, homography.py:48-49). | |
| 5 điểm dữ liệu — KHÔNG đo mới, chỉ đọc số đã công bố: | |
| - 2 job BG28 (model c3): đọc từ JSON đã lưu ở | |
| ``poolcoach-docs\\results\\2026-08-12_shotnet_p2\\cu1?_app_bg28.json`` | |
| (chỉ ĐỌC — file thuộc repo docs, không sửa). | |
| - 3 job smoke BG29b (model c4b): Redis hết TTL, số chép NGUYÊN VĂN từ | |
| HANDOFF 13/08/2026 10:25 (bảng "Số 2 cột") — đúng nguồn BRIEF chỉ định. | |
| Chạy (venv app, không cần GPU/torch): | |
| python scripts/broadcast/diag_phi_conventions.py | |
| Artifact: ``D:\\Khoa luan\\bb9_diag30_phi_conventions.csv`` (mới, không đè | |
| gì) — mỗi dòng một (điểm × phép biến đổi), kèm commit hash lúc chạy. | |
| Caveat đọc kết quả (ghi sẵn để khỏi đọc quá tay): φ analytic của cả 5 điểm | |
| chỉ trải 258.0–261.6° (3.6°) — bảng này thực chất chỉ thử các phép biến đổi | |
| tại MỘT hướng đánh, nên "phép nào khớp nhất" không tự nó phân biệt được | |
| mirror với một offset cố định ~±140°; phải đọc KÈM audit code (Bước 1.2). | |
| """ | |
| from __future__ import annotations | |
| import csv | |
| import json | |
| import subprocess | |
| import sys | |
| from pathlib import Path | |
| ROOT = Path(__file__).resolve().parents[2] | |
| WORKSPACE = ROOT.parent | |
| BG28_DIR = WORKSPACE / "poolcoach-docs" / "results" / "2026-08-12_shotnet_p2" | |
| OUT_CSV = WORKSPACE / "bb9_diag30_phi_conventions.csv" | |
| # 3 job smoke BG29b — nguyên văn HANDOFF 13/08/2026 10:25 (model c4b, | |
| # commit lúc smoke a65787a); Redis TTL đã hết nên đây là nguồn duy nhất. | |
| BG29B_POINTS = [ | |
| {"diem": "cu11_lan1_bg29b", "model": "c4b", "phi_model": 109.3, | |
| "phi_analytic": 258.3}, | |
| {"diem": "cu11_lan2_bg29b", "model": "c4b", "phi_model": 110.7, | |
| "phi_analytic": 258.0}, | |
| {"diem": "cu12_bg29b", "model": "c4b", "phi_model": 121.4, | |
| "phi_analytic": 261.6}, | |
| ] | |
| TRANSFORMS = [ | |
| ("phi", lambda p: p % 360.0), | |
| ("neg_phi", lambda p: (-p) % 360.0), | |
| ("phi_plus_180", lambda p: (p + 180.0) % 360.0), | |
| ("180_minus_phi", lambda p: (180.0 - p) % 360.0), | |
| ] | |
| def circ_diff_signed(a: float, b: float) -> float: | |
| """a − b về (−180, 180] — dấu để thấy phần dư lệch về phía nào.""" | |
| return ((a - b + 180.0) % 360.0) - 180.0 | |
| def load_bg28_points() -> list[dict]: | |
| pts = [] | |
| for cu in (11, 12): | |
| p = BG28_DIR / f"cu{cu}_app_bg28.json" | |
| r = json.loads(p.read_text(encoding="utf-8"))["result"] | |
| pts.append({"diem": f"cu{cu}_bg28", | |
| "model": "c3", | |
| "phi_model": float(r["shotnet"]["phi_deg"]), | |
| "phi_analytic": float(r["metrics"]["phi_deg"])}) | |
| return pts | |
| def git_head() -> str: | |
| try: | |
| return subprocess.run(["git", "-C", str(ROOT), "rev-parse", | |
| "--short", "HEAD"], capture_output=True, | |
| text=True, check=True).stdout.strip() | |
| except Exception: | |
| return "unknown" | |
| def main() -> int: | |
| points = load_bg28_points() + BG29B_POINTS | |
| commit = git_head() | |
| rows = [] | |
| for pt in points: | |
| for name, fn in TRANSFORMS: | |
| tv = fn(pt["phi_analytic"]) | |
| resid = circ_diff_signed(pt["phi_model"], tv) | |
| rows.append({"diem": pt["diem"], "model": pt["model"], | |
| "phi_model": pt["phi_model"], | |
| "phi_analytic": pt["phi_analytic"], | |
| "phep": name, | |
| "phi_analytic_bien_doi": round(tv, 1), | |
| "du_deg": round(resid, 1), | |
| "abs_du_deg": round(abs(resid), 1), | |
| "commit_luc_chay": commit}) | |
| if OUT_CSV.exists(): | |
| print(f"BO QUA ghi CSV: {OUT_CSV} da ton tai (luat khong de " | |
| f"artifact cu) -- xoa tay neu muon sinh lai.") | |
| else: | |
| with OUT_CSV.open("w", newline="", encoding="utf-8") as f: | |
| wr = csv.DictWriter(f, fieldnames=list(rows[0].keys())) | |
| wr.writeheader() | |
| wr.writerows(rows) | |
| print(f"da ghi {OUT_CSV} ({len(rows)} dong, commit {commit})") | |
| # ----- bảng tóm tắt ra console (ASCII — bẫy cp1252) | |
| print(f"\n{'diem':<18}{'model':<7}{'phi_mod':>8}{'phi_ana':>8}" | |
| + "".join(f"{n:>15}" for n, _ in TRANSFORMS)) | |
| for pt in points: | |
| cells = "" | |
| for name, fn in TRANSFORMS: | |
| resid = circ_diff_signed(pt["phi_model"], fn(pt["phi_analytic"])) | |
| cells += f"{resid:>+15.1f}" | |
| print(f"{pt['diem']:<18}{pt['model']:<7}{pt['phi_model']:>8.1f}" | |
| f"{pt['phi_analytic']:>8.1f}{cells}") | |
| print("\nmedian |du| theo phep (5 diem / rieng c4b):") | |
| for name, fn in TRANSFORMS: | |
| alls = sorted(abs(circ_diff_signed(pt["phi_model"], | |
| fn(pt["phi_analytic"]))) | |
| for pt in points) | |
| c4b = sorted(abs(circ_diff_signed(pt["phi_model"], | |
| fn(pt["phi_analytic"]))) | |
| for pt in points if pt["model"] == "c4b") | |
| print(f" {name:<15} all={alls[len(alls) // 2]:>6.1f} " | |
| f"c4b={c4b[len(c4b) // 2]:>6.1f}") | |
| print("\nCAVEAT: phi analytic 5 diem chi trai 258.0-261.6 (3.6 deg) — " | |
| "bang chi thu duoc MOT huong danh; doc kem audit code Buoc 1.2.") | |
| return 0 | |
| if __name__ == "__main__": | |
| sys.exit(main()) | |