publish eve_rock_watcher.py
This commit is contained in:
parent
b3843f5de4
commit
5beca84cde
1 changed files with 85 additions and 16 deletions
|
|
@ -66,14 +66,67 @@ def parse_survey(text):
|
|||
return rows
|
||||
|
||||
|
||||
def save_rock_region(cp, l, t, wd, ht):
|
||||
# Selected-Item panel (no survey scanner needed): "Quantity 5,593 Units"
|
||||
QTY_RE = re.compile(r"quantit\w*\s*([\d.,]{2,})\s*units?", re.I)
|
||||
|
||||
|
||||
def parse_selected(text):
|
||||
"""The selected asteroid's remaining units from its info panel, or None."""
|
||||
m = QTY_RE.search(text.replace("\n", " "))
|
||||
if not m:
|
||||
return None
|
||||
digits = re.sub(r"\D", "", m.group(1)) # tolerate OCR , vs . in the number
|
||||
return int(digits) if digits else None
|
||||
|
||||
|
||||
def save_rock_region(cp, l, t, wd, ht, mode="survey"):
|
||||
if not cp.has_section("rock"):
|
||||
cp.add_section("rock")
|
||||
cp["rock"]["region"] = f"{l},{t},{wd},{ht}"
|
||||
cp["rock"]["mode"] = mode # 'survey' rows or 'selected' item
|
||||
with open(w.CONFIG_PATH, "w") as f:
|
||||
cp.write(f)
|
||||
|
||||
|
||||
def detect_selected_region(cp):
|
||||
"""Find the Selected Item panel by locating its 'Quantity N Units' line."""
|
||||
import mss
|
||||
import pytesseract
|
||||
from PIL import Image
|
||||
tcmd = cp.get("ocr", "tesseract_cmd", fallback="").strip()
|
||||
if tcmd:
|
||||
pytesseract.pytesseract.tesseract_cmd = tcmd
|
||||
try:
|
||||
with mss.mss() as sct:
|
||||
mon = sct.monitors[0]
|
||||
raw = sct.grab(mon)
|
||||
img = Image.frombytes("RGB", raw.size, raw.bgra, "raw", "BGRX")
|
||||
data = pytesseract.image_to_data(img, output_type=pytesseract.Output.DICT)
|
||||
except Exception as e:
|
||||
print(f"[rock] detect error: {e}")
|
||||
return None
|
||||
lines = {}
|
||||
for i in range(len(data["text"])):
|
||||
if not data["text"][i].strip():
|
||||
continue
|
||||
k = (data["block_num"][i], data["par_num"][i], data["line_num"][i])
|
||||
lines.setdefault(k, []).append(i)
|
||||
for idxs in lines.values():
|
||||
joined = " ".join(data["text"][i] for i in idxs)
|
||||
if QTY_RE.search(joined):
|
||||
xs = [data["left"][i] for i in idxs]
|
||||
ys = [data["top"][i] for i in idxs]
|
||||
rs = [data["left"][i] + data["width"][i] for i in idxs]
|
||||
bs = [data["top"][i] + data["height"][i] for i in idxs]
|
||||
pad = 10
|
||||
region = [mon["left"] + min(xs) - pad, mon["top"] + min(ys) - pad,
|
||||
(max(rs) - min(xs)) + 2 * pad, (max(bs) - min(ys)) + 2 * pad]
|
||||
save_rock_region(cp, *region, mode="selected")
|
||||
print(f"[rock] auto-detected Selected-Item quantity -> {region}")
|
||||
return region
|
||||
return None
|
||||
|
||||
|
||||
def detect_survey_region(cp):
|
||||
"""Find the Survey Scanner Results window by locating >=2 'ore name + number' rows."""
|
||||
import mss
|
||||
|
|
@ -163,11 +216,28 @@ class Tracker:
|
|||
|
||||
|
||||
def get_region(cp):
|
||||
region_s = cp.get("rock", "region", fallback="").strip() if cp.has_section("rock") else ""
|
||||
if region_s:
|
||||
return [int(x) for x in region_s.split(",")]
|
||||
print("[rock] no saved region — auto-detecting the Survey Scanner Results window...")
|
||||
return detect_survey_region(cp)
|
||||
"""Return (region, mode). mode = 'survey' (scanner rows) or 'selected' (Selected Item)."""
|
||||
if cp.has_section("rock"):
|
||||
rs = cp.get("rock", "region", fallback="").strip()
|
||||
if rs:
|
||||
return [int(x) for x in rs.split(",")], cp.get("rock", "mode", fallback="survey")
|
||||
print("[rock] no saved region — looking for a Survey Scanner window, else Selected Item...")
|
||||
r = detect_survey_region(cp)
|
||||
if r:
|
||||
return r, "survey"
|
||||
r = detect_selected_region(cp)
|
||||
if r:
|
||||
return r, "selected"
|
||||
return None, None
|
||||
|
||||
|
||||
def read_rows(cp, region, mode):
|
||||
import pytesseract
|
||||
text = pytesseract.image_to_string(w.grab_region(region))
|
||||
if mode == "selected":
|
||||
q = parse_selected(text)
|
||||
return [("rock", q)] if q else []
|
||||
return parse_survey(text)
|
||||
|
||||
|
||||
def main():
|
||||
|
|
@ -191,13 +261,12 @@ def main():
|
|||
tcmd = cp.get("ocr", "tesseract_cmd", fallback="").strip()
|
||||
if tcmd:
|
||||
pytesseract.pytesseract.tesseract_cmd = tcmd
|
||||
region = get_region(cp)
|
||||
region, mode = get_region(cp)
|
||||
if not region:
|
||||
print("Couldn't find the survey window. Open it (with rocks scanned) and retry, "
|
||||
"or run --snip.")
|
||||
print("Couldn't find a Survey Scanner window or a Selected-Item 'Quantity N "
|
||||
"Units'. Select a rock (or open the survey results) and retry.")
|
||||
return
|
||||
text = pytesseract.image_to_string(w.grab_region(region))
|
||||
print("rows:", parse_survey(text))
|
||||
print(f"mode={mode} rows:", read_rows(cp, region, mode))
|
||||
return
|
||||
|
||||
import pytesseract
|
||||
|
|
@ -209,22 +278,22 @@ def main():
|
|||
tracker = Tracker()
|
||||
last_alert = {}
|
||||
last_status = 0.0
|
||||
region = None
|
||||
region = mode = None
|
||||
while True:
|
||||
if not w.bot_mining(cp): # only during a mining session
|
||||
tracker.h.clear()
|
||||
time.sleep(15)
|
||||
continue
|
||||
if region is None:
|
||||
region = get_region(cp)
|
||||
region, mode = get_region(cp)
|
||||
if region is None:
|
||||
print("[rock] survey window not visible — open it (rocks scanned). Retrying...")
|
||||
print("[rock] no survey window / selected rock visible — select a rock. "
|
||||
"Retrying...")
|
||||
time.sleep(max(poll, 15))
|
||||
continue
|
||||
w.heartbeat(cp, "rock")
|
||||
try:
|
||||
text = pytesseract.image_to_string(w.grab_region(region))
|
||||
rows = parse_survey(text)
|
||||
rows = read_rows(cp, region, mode)
|
||||
if not rows:
|
||||
region = None # lost it; re-detect next loop
|
||||
time.sleep(poll)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue