tools: focus_persistence.py used the reader that was two items out
Now uses the shared measured reader, which refuses to name a row outside the calibration rather than guessing. Replaying this run's stored frames through it gives NEW GAME / TUTORIAL / TUTORIAL, which is what the corrected record says. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Wuu56cE8vJGTBtn1ppsk8v
This commit is contained in:
@@ -39,16 +39,23 @@ NEED, CEIL, HOLD = 500, 2500, 12 # title plate pulse band
|
||||
MENU_LO, MENU_HI, MENU_HOLD = 250, 420, 6 # glyph-327 menu detector
|
||||
PAD = os.path.join(os.path.dirname(os.path.abspath(__file__)), "pad.py")
|
||||
|
||||
# menu_focus.py's geometry, byte for byte: the focus RING sits in the gutter
|
||||
# left of the label and nothing else is bright there.
|
||||
NAMES = ["NEW GAME", "LOAD GAME", "TUTORIAL", "OPTIONS", "EXTRAS"]
|
||||
YS = [166, 241, 315, 390, 465]
|
||||
# 🔴 This used menu_focus.py's DESIGN-SPACE rows [166,241,315,390,465] against
|
||||
# x11grab frames, which carry Xenia's window chrome and a surface scaled 1.060 --
|
||||
# and reported item names TWO POSITIONS OUT for a whole session. The control
|
||||
# ("2 DOWNs move 2 items") could not catch it, because a constant offset
|
||||
# preserves relative motion exactly. See data/menu-focus-reader-offset.txt.
|
||||
# Now measured, via the shared reader, which REFUSES to name an out-of-range row.
|
||||
import os as _os
|
||||
sys.path.insert(0, _os.path.dirname(_os.path.abspath(__file__)))
|
||||
from ring_row import ring_row as _ring_row, main_menu_item as _mmi, NAMES
|
||||
|
||||
|
||||
def focus(a):
|
||||
g = np.asarray(Image.fromarray(a.astype(np.uint8)).convert("L"), dtype=float)
|
||||
v = [g[y - 20:y + 20, 500:542].max() for y in YS]
|
||||
return int(np.argmax(v)), v
|
||||
y = _ring_row(Image.fromarray(a.astype(np.uint8)))
|
||||
i = _mmi(y)
|
||||
if i is None:
|
||||
return None, [y]
|
||||
return i, [y]
|
||||
|
||||
|
||||
def deliveries(vk):
|
||||
@@ -139,6 +146,8 @@ while True:
|
||||
p, a = fresh(p)
|
||||
Image.fromarray(a.astype(np.uint8)).save(f"{OUT}/1-F1.png")
|
||||
F1, v = focus(a)
|
||||
if F1 is None:
|
||||
print(f"🔴 no main-menu ring row in the F1 frame (y={v[0]}) — stopping", flush=True); break
|
||||
print(f"[{el:7.1f}s] MENU (glyph {c}) F1 = {NAMES[F1]} ring "
|
||||
+ " ".join(f"{x:5.0f}" for x in v), flush=True)
|
||||
# 🔴 Run 1 pressed DOWN twice through pad.py with NO delivery
|
||||
@@ -153,6 +162,8 @@ while True:
|
||||
p, a = fresh(p)
|
||||
Image.fromarray(a.astype(np.uint8)).save(f"{OUT}/2-F2.png")
|
||||
F2, v = focus(a)
|
||||
if F2 is None:
|
||||
print(f"🔴 no main-menu ring row in the F2 frame (y={v[0]}) — stopping", flush=True); break
|
||||
print(f"[{el:7.1f}s] after 2x DOWN F2 = {NAMES[F2]} ring "
|
||||
+ " ".join(f"{x:5.0f}" for x in v), flush=True)
|
||||
want = (F1 + 2) % len(NAMES)
|
||||
@@ -181,6 +192,8 @@ while True:
|
||||
p, a = fresh(p)
|
||||
Image.fromarray(a.astype(np.uint8)).save(f"{OUT}/4-F3.png")
|
||||
F3, v = focus(a)
|
||||
if F3 is None:
|
||||
print(f"🔴 no main-menu ring row in the F3 frame (y={v[0]}) — stopping", flush=True); break
|
||||
print(f"[{el:7.1f}s] MENU AGAIN F3 = {NAMES[F3]} ring "
|
||||
+ " ".join(f"{x:5.0f}" for x in v), flush=True)
|
||||
print(f"\nF1={NAMES[F1]} F2={NAMES[F2]} F3={NAMES[F3]}")
|
||||
|
||||
Reference in New Issue
Block a user