From 82b9ef36054df69c647d81187298a78eaee50f6f Mon Sep 17 00:00:00 2001 From: brockdarnold Date: Mon, 15 Jun 2026 05:21:08 +0000 Subject: [PATCH] publish eve_rock_watcher.py --- eve_rock_watcher.py | 42 +++++++++++++++++++++++++++++------------- 1 file changed, 29 insertions(+), 13 deletions(-) diff --git a/eve_rock_watcher.py b/eve_rock_watcher.py index 5596824..75da0d4 100644 --- a/eve_rock_watcher.py +++ b/eve_rock_watcher.py @@ -352,13 +352,16 @@ def main(): pytesseract.pytesseract.tesseract_cmd = tcmd poll = max(poll, 8) # full-window OCR is heavy; don't spin + MAX_DROP_PS = 4000 / 60.0 # units/sec ceiling — a faster "drop" than this is a misread print(f"[rock] started; switch<{switch_secs}s, poll {poll}s (waits for !mining on)") - hist = deque() # (t, units) for the currently-selected rock + hist = deque() # accepted (t, units), cleaned of OCR outliers + pending = None # a jumped value awaiting a confirming second read last_status = 0.0 last_alert = 0.0 + last_ore = "rock" while True: if not w.bot_mining(cp): # only during a mining session - hist.clear() + hist.clear(); pending = None time.sleep(15) continue try: @@ -367,26 +370,39 @@ def main(): if units is None: # no rock selected / popup not shown time.sleep(poll) continue - # quantity jumped UP -> you locked a fresh rock; restart the measurement - if hist and units > hist[-1][1] + 50: - hist.clear() - hist.append((now, units)) + if ore and ore != "rock": + last_ore = ore + # ---- reject OCR misreads (a stray digit makes 34,569 read as ~234,000) ---- + if not hist: + hist.append((now, units)); pending = None + else: + lt, lu = hist[-1] + dt = max(1.0, now - lt) + if (lu - units) <= MAX_DROP_PS * dt + 400 and units <= lu + 40: + hist.append((now, units)); pending = None # normal depletion / flat + elif pending is not None and abs(units - pending) <= max(400, units * 0.03): + hist.clear(); hist.append((now, units)); pending = None # new rock, confirmed + else: + pending = units # outlier or jump — wait for confirmation + time.sleep(poll); continue while hist and now - hist[0][0] > 180: # keep a ~3 min window hist.popleft() - # true depletion rate from the number falling — captures ALL miners on the rock + # ---- depletion rate from the cleaned series (captures ALL miners on the rock) ---- rate = 0.0 # units/sec - if len(hist) >= 2 and (hist[-1][0] - hist[0][0]) >= 20: + if len(hist) >= 3 and (hist[-1][0] - hist[0][0]) >= 30: du, dt = hist[0][1] - hist[-1][1], hist[-1][0] - hist[0][0] - rate = du / dt if du > 0 else 0.0 + r = du / dt if du > 0 else 0.0 + if 0 < r <= MAX_DROP_PS: # ignore impossible rates + rate = r tleft = units / rate if rate > 0 else None # live readout (edit-in-place, no spam) if post_rock and not w.bot_muted(cp) and now - last_status >= status_secs: if tleft: empty_at = int(now + tleft) - line = (f"🪨 {ore.title()} {units:,} u · ~{_fmt_dur(tleft)} left " + line = (f"🪨 {last_ore.title()} {units:,} u · ~{_fmt_dur(tleft)} left " f"(empties ) · {rate*60:,.0f} u/min") else: - line = f"🪨 {ore.title()} {units:,} u · measuring rate…" + line = f"🪨 {last_ore.title()} {units:,} u · measuring rate…" w._discord_live(cp, "rock", f"⛏️ {socket.gethostname()} current rock", line) last_status = now # switch-rocks alert when it's genuinely about to empty @@ -394,10 +410,10 @@ def main(): last_alert = now empty_at = int(now + tleft) w.notify(cp, "Switch rocks", - f"{ore.title()} rock empties in ~{_fmt_dur(tleft)} " + f"{last_ore.title()} rock empties in ~{_fmt_dur(tleft)} " f"() — {units:,} u left. Lock a new rock.", priority="high", tags="pick,gem") - print(f"[rock] ALERT {ore} {units} u, ~{_fmt_dur(tleft)} left") + print(f"[rock] ALERT {last_ore} {units} u, ~{_fmt_dur(tleft)} left") except Exception as e: print(f"[rock] error: {e}") time.sleep(poll)