Spaces:
Sleeping
Sleeping
File size: 7,308 Bytes
78738de | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 | """Verify kha thi cua thu vien drill (app/drills.json) β BRIEF 04/08/2026 buoc 1.
CURATION, KHONG PHAI EVAL (tien le 11b ban giao 9): so "cu dat goal" o day chi
de chung minh drill TAP DUOC β dung de lan vao so do engine trong research log.
Voi moi drill: quet dung grid ky thuat x luc cua engine (11 ky thuat x nac
2-10 = 99 o, `v2_specs`) tren phi ngam ghost-ball vao lo goal (goal.pot.pocket
= "any" thi quet moi lo kha thi tu `feasible_pockets_full`), sim tung cu bang
`simulate_shot_multi`, dem:
n_pot : cu pot SACH bi muc tieu (khong scratch, first_contact dung bi,
bi vao lo) β gate cung: moi drill phai co >= 1
n_pass : cu dat TRON goal = pot sach + cue dung trong cue_zone
(scoring.pass "pot && cue_zone") β drill 0 cu dat la drill
khong tap duoc: chinh zone/khoang cach roi quet lai
Gate G1: 100% drill layout hop le (validate_full khong nem) VA n_pot >= 1.
Bang so n_pass tung drill di vao HANDOFF.
Chay SERIAL co chu dich, khong pool: tong scan ~9 drill x 99-500 sim ~ 10-30s
sau warmup, trong khi moi worker process phai tra ~40s JIT Numba rieng β
pool o day cham hon serial. Khong hardcode so worker vi khong co worker nao
(POOLCOACH_WORKERS chi danh cho cho nao that su co pool).
python scripts/verify_drills.py [--drill stop_shot_short] [--drills-file ...]
"""
from __future__ import annotations
import argparse
import json
import sys
import time
from pathlib import Path
ROOT = Path(__file__).resolve().parents[1]
if str(ROOT / "src") not in sys.path:
sys.path.insert(0, str(ROOT / "src"))
DRILLS_FILE = ROOT / "app" / "drills.json"
def load_drills(path: Path) -> list[dict]:
data = json.loads(path.read_text(encoding="utf-8"))
return data["drills"]
def check_layout(env_h, balls, target):
"""Layout hop le = validate_full khong nem + bi muc tieu co mat.
Tra ve None neu ok, message loi neu khong."""
from poolcoach_rl.recommend import validate_full
if target not in balls:
return f"goal.pot.ball={target!r} khong co trong layout"
try:
validate_full(env_h, balls)
except ValueError as e:
return str(e)
return None
def scan_drill(env_h, drill):
"""Quet grid engine tren MOT drill. Tra dict so lieu cho bang bao cao."""
import numpy as np
from poolcoach_rl.recommend import feasible_pockets_full
from poolcoach_rl.recommend.zone_v2 import v2_specs
from poolcoach_rl.recommend import simulate_shot_multi
balls = {bid: np.array([p["x"], p["y"]], dtype=np.float64)
for bid, p in drill["layout"].items()}
target = drill["goal"]["pot"]["ball"]
want_pocket = drill["goal"]["pot"]["pocket"]
zone = drill["goal"]["cue_zone"]
zc = np.array([zone["cx"], zone["cy"]], dtype=np.float64)
err = check_layout(env_h, balls, target)
if err:
return {"id": drill["id"], "layout_err": err}
pockets = feasible_pockets_full(env_h, balls, target)
if want_pocket != "any":
pockets = [p for p in pockets if p[0] == int(want_pocket)]
specs = v2_specs()
n_sim = n_pot = n_pass = 0
example = None
t0 = time.time()
for idx, phi, _cut, _blocked in pockets:
for side, vert, v0 in specs:
m = simulate_shot_multi(env_h, balls, phi, v0, side, vert)
n_sim += 1
if m is None:
continue
pot_ok = (not m["scratch"]
and m["first_contact"] == target
and list(m["potted"]) == [target])
if not pot_ok:
continue
n_pot += 1
cue_final = m["balls_final"].get("cue")
if cue_final is None:
continue
d_zone = float(np.linalg.norm(
np.asarray(cue_final, dtype=np.float64) - zc))
if d_zone <= zone["r"]:
n_pass += 1
if example is None:
example = (side, vert, v0, d_zone)
return {"id": drill["id"], "layout_err": None,
"n_pockets": len(pockets), "n_sim": n_sim,
"n_pot": n_pot, "n_pass": n_pass,
"example": example, "elapsed_s": time.time() - t0}
def main() -> int:
# Console Windows co the la cp1252 β title tieng Viet khong duoc lam chet script
if hasattr(sys.stdout, "reconfigure"):
sys.stdout.reconfigure(encoding="utf-8", errors="replace")
ap = argparse.ArgumentParser(description=__doc__.splitlines()[0])
ap.add_argument("--drill", help="chi quet 1 drill theo id (chinh sua nhanh)")
ap.add_argument("--drills-file", type=Path, default=DRILLS_FILE)
args = ap.parse_args()
drills = load_drills(args.drills_file)
if args.drill:
drills = [d for d in drills if d["id"] == args.drill]
if not drills:
print(f"khong co drill id={args.drill!r}")
return 2
print(f"[verify_drills] {len(drills)} drill tu {args.drills_file}")
print("[verify_drills] dung env + warmup JIT Numba (~40s lan dau)...",
flush=True)
t0 = time.time()
from poolcoach_rl.envs import PositionPlayEnv
from poolcoach_rl.recommend import warmup
env_h = PositionPlayEnv()
warmup(env_h)
print(f"[verify_drills] warmup xong sau {time.time() - t0:.1f}s", flush=True)
rows = []
for d in drills:
r = scan_drill(env_h, d)
rows.append(r)
if r["layout_err"]:
print(f" {r['id']:18s} LAYOUT LOI: {r['layout_err']}", flush=True)
else:
ex = r["example"]
ex_txt = (f"side {ex[0]:+.1f} vert {ex[1]:+.1f} v0 {ex[2]:.2f} "
f"(cach tam zone {ex[3]:.3f} m)" if ex else "-")
print(f" {r['id']:18s} pockets {r['n_pockets']} sim {r['n_sim']:4d}"
f" pot {r['n_pot']:3d} PASS {r['n_pass']:3d}"
f" vd: {ex_txt} [{r['elapsed_s']:.1f}s]", flush=True)
# ------------------------------------------------------------- gate G1
bad_layout = [r["id"] for r in rows if r["layout_err"]]
no_pot = [r["id"] for r in rows
if not r["layout_err"] and r["n_pot"] == 0]
no_pass = [r["id"] for r in rows
if not r["layout_err"] and r["n_pot"] > 0 and r["n_pass"] == 0]
print()
print("| drill | pockets | sim | pot sach | dat tron goal |")
print("|---|---|---|---|---|")
for r in rows:
if r["layout_err"]:
print(f"| {r['id']} | - | - | - | LAYOUT LOI |")
else:
print(f"| {r['id']} | {r['n_pockets']} | {r['n_sim']} "
f"| {r['n_pot']} | {r['n_pass']} |")
print()
if bad_layout:
print(f"GATE DO: layout loi: {', '.join(bad_layout)}")
return 1
if no_pot:
print(f"GATE DO: khong ton tai cu pot: {', '.join(no_pot)}")
return 1
if no_pass:
# khong phai gate cung cua G1, nhung drill 0 cu dat tron goal la drill
# khong tap duoc β BRIEF bat chinh zone/khoang cach roi quet lai
print(f"CANH BAO: pot duoc nhung 0 cu dat tron goal (phai chinh + quet "
f"lai): {', '.join(no_pass)}")
return 1
print("GATE G1 DAT: 100% layout hop le, moi drill co cu pot va co cu dat "
"tron goal.")
return 0
if __name__ == "__main__":
raise SystemExit(main())
|