publish eve_orehold_watcher.py

This commit is contained in:
brockdarnold 2026-06-14 15:52:39 +00:00
parent e390c416b5
commit 6ba9fbc272

View file

@ -82,28 +82,56 @@ def save_region(cp, left, top, width, height):
cp.write(f) cp.write(f)
RATE_PATH = os.path.join(HERE, ".mining_rate")
def write_rate(m3_per_min, cur, cap):
"""Publish the live ore-hold fill rate so the rock watcher can estimate how long
until the asteroid you're on is depleted. Written every OCR tick."""
try:
with open(RATE_PATH, "w") as f:
json.dump({"rate_m3min": round(m3_per_min, 1), "cur": cur, "cap": cap,
"ts": int(time.time())}, f)
except Exception:
pass
# --------------------------------------------------------------------------- # # --------------------------------------------------------------------------- #
# Delivery # Delivery
# --------------------------------------------------------------------------- # # --------------------------------------------------------------------------- #
_BOT_STATE = {"t": 0, "muted": False} _BOT_STATE = {"t": 0, "muted": False, "mining": False}
def bot_muted(cp): DEFAULT_STATE_URL = ("https://git.armoredarmadillo.com/brockdarnold/eve-watcher/"
"""Coordinate with the Discord bot: poll the shared alert-state it publishes, so a "raw/branch/main/alert_state.json")
`!mute` in Discord also silences these local watchers. Cached 30s."""
url = cp.get("coordination", "bot_state_url", fallback="").strip() \
if cp.has_section("coordination") else "" def _bot_state(cp):
if not url: """Poll the shared alert-state the Discord bot publishes (mute/quiet/mining),
return False cached 30s, so a Discord `!mute` / `!mining` also drives the local watchers.
Defaults to the public alert_state.json (no config needed)."""
url = (cp.get("coordination", "bot_state_url", fallback="").strip()
if cp.has_section("coordination") else "") or DEFAULT_STATE_URL
if time.time() - _BOT_STATE["t"] < 30: if time.time() - _BOT_STATE["t"] < 30:
return _BOT_STATE["muted"] return _BOT_STATE
try: try:
d = json.loads(urllib.request.urlopen(url, timeout=5).read()) req = urllib.request.Request(url, headers={"User-Agent": "eve-watcher"})
d = json.loads(urllib.request.urlopen(req, timeout=5).read())
_BOT_STATE["muted"] = bool(d.get("muted")) _BOT_STATE["muted"] = bool(d.get("muted"))
_BOT_STATE["mining"] = bool(d.get("mining"))
_BOT_STATE["t"] = time.time() _BOT_STATE["t"] = time.time()
except Exception: except Exception:
pass pass
return _BOT_STATE["muted"] return _BOT_STATE
def bot_muted(cp):
return _bot_state(cp)["muted"]
def bot_mining(cp):
"""True when a mining session is active (started via `!mining on` in Discord)."""
return _bot_state(cp)["mining"]
def notify(cp, title, message, priority="high", tags="rock,bell"): def notify(cp, title, message, priority="high", tags="rock,bell"):
@ -287,6 +315,7 @@ def run_ocr(cp):
last_grow = time.time() last_grow = time.time()
last_stall_alert = 0.0 last_stall_alert = 0.0
misses = 0 misses = 0
samples = [] # recent (t, cur) for the live fill-rate estimate
while True: while True:
try: try:
img = grab_region(region) img = grab_region(region)
@ -297,6 +326,14 @@ def run_ocr(cp):
cur, cap = parsed cur, cap = parsed
pct = 100.0 * cur / cap pct = 100.0 * cur / cap
print(f"[ocr] {cur}/{cap} m3 ({pct:.1f}%) armed={armed}") print(f"[ocr] {cur}/{cap} m3 ({pct:.1f}%) armed={armed}")
# --- live fill rate (m3/min) over a ~90s window -> .mining_rate ---
now = time.time()
samples.append((now, cur))
samples = [(t, c) for (t, c) in samples if now - t <= 90 and c <= cur]
if len(samples) >= 2 and (samples[-1][0] - samples[0][0]) >= 20:
dc = samples[-1][1] - samples[0][1]
dt = samples[-1][0] - samples[0][0]
write_rate(dc / dt * 60 if dc > 0 else 0.0, cur, cap)
if pct < reset_pct: if pct < reset_pct:
armed = True armed = True
# --- still mining? (hold should be growing) --- # --- still mining? (hold should be growing) ---