Spaces:
Sleeping
Sleeping
| from __future__ import annotations | |
| """ | |
| Canonical UI geometry contract for the live Bluestacks pipeline. | |
| Everything here is expressed in *normalized coordinates inside the game viewport* | |
| (after black bars/padding are removed): | |
| x_n in [0,1], y_n in [0,1] | |
| This keeps the extractor/executor stable across resolutions and window borders. | |
| """ | |
| from dataclasses import dataclass | |
| from typing import Literal | |
| Zone = Literal["back_left", "back_right", "mid_left", "mid_right", "bridge_left", "bridge_right"] | |
| class RectN: | |
| x1: float | |
| y1: float | |
| x2: float | |
| y2: float | |
| class PointN: | |
| x: float | |
| y: float | |
| # --- ROIs (starting calibration; refine per-device if needed) --- | |
| ROI_TIME_LEFT = RectN(0.74, 0.00, 1.00, 0.10) | |
| ROI_MY_ELIXIR = RectN(0.23, 0.86, 0.40, 0.97) | |
| ROI_NEXT_CARD = RectN(0.02, 0.80, 0.22, 0.99) | |
| ROI_HAND_BAR = RectN(0.22, 0.76, 1.00, 1.00) | |
| def hand_slot_roi(slot: int) -> RectN: | |
| slot = max(0, min(3, int(slot))) | |
| w = (ROI_HAND_BAR.x2 - ROI_HAND_BAR.x1) / 4.0 | |
| x1 = ROI_HAND_BAR.x1 + slot * w | |
| return RectN(x1, ROI_HAND_BAR.y1, x1 + w, ROI_HAND_BAR.y2) | |
| def hand_slot_center(slot: int) -> PointN: | |
| r = hand_slot_roi(slot) | |
| return PointN((r.x1 + r.x2) / 2.0, 0.88) | |
| # --- Placement zone click points (normalized) --- | |
| ZONE_POINTS: dict[Zone, PointN] = { | |
| "back_left": PointN(0.30, 0.63), | |
| "back_right": PointN(0.70, 0.63), | |
| "mid_left": PointN(0.30, 0.52), | |
| "mid_right": PointN(0.70, 0.52), | |
| "bridge_left": PointN(0.30, 0.42), | |
| "bridge_right": PointN(0.70, 0.42), | |
| } | |