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
|
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"):
|
if not cp.has_section("rock"):
|
||||||
cp.add_section("rock")
|
cp.add_section("rock")
|
||||||
cp["rock"]["region"] = f"{l},{t},{wd},{ht}"
|
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:
|
with open(w.CONFIG_PATH, "w") as f:
|
||||||
cp.write(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):
|
def detect_survey_region(cp):
|
||||||
"""Find the Survey Scanner Results window by locating >=2 'ore name + number' rows."""
|
"""Find the Survey Scanner Results window by locating >=2 'ore name + number' rows."""
|
||||||
import mss
|
import mss
|
||||||
|
|
@ -163,11 +216,28 @@ class Tracker:
|
||||||
|
|
||||||
|
|
||||||
def get_region(cp):
|
def get_region(cp):
|
||||||
region_s = cp.get("rock", "region", fallback="").strip() if cp.has_section("rock") else ""
|
"""Return (region, mode). mode = 'survey' (scanner rows) or 'selected' (Selected Item)."""
|
||||||
if region_s:
|
if cp.has_section("rock"):
|
||||||
return [int(x) for x in region_s.split(",")]
|
rs = cp.get("rock", "region", fallback="").strip()
|
||||||
print("[rock] no saved region — auto-detecting the Survey Scanner Results window...")
|
if rs:
|
||||||
return detect_survey_region(cp)
|
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():
|
def main():
|
||||||
|
|
@ -191,13 +261,12 @@ def main():
|
||||||
tcmd = cp.get("ocr", "tesseract_cmd", fallback="").strip()
|
tcmd = cp.get("ocr", "tesseract_cmd", fallback="").strip()
|
||||||
if tcmd:
|
if tcmd:
|
||||||
pytesseract.pytesseract.tesseract_cmd = tcmd
|
pytesseract.pytesseract.tesseract_cmd = tcmd
|
||||||
region = get_region(cp)
|
region, mode = get_region(cp)
|
||||||
if not region:
|
if not region:
|
||||||
print("Couldn't find the survey window. Open it (with rocks scanned) and retry, "
|
print("Couldn't find a Survey Scanner window or a Selected-Item 'Quantity N "
|
||||||
"or run --snip.")
|
"Units'. Select a rock (or open the survey results) and retry.")
|
||||||
return
|
return
|
||||||
text = pytesseract.image_to_string(w.grab_region(region))
|
print(f"mode={mode} rows:", read_rows(cp, region, mode))
|
||||||
print("rows:", parse_survey(text))
|
|
||||||
return
|
return
|
||||||
|
|
||||||
import pytesseract
|
import pytesseract
|
||||||
|
|
@ -209,22 +278,22 @@ def main():
|
||||||
tracker = Tracker()
|
tracker = Tracker()
|
||||||
last_alert = {}
|
last_alert = {}
|
||||||
last_status = 0.0
|
last_status = 0.0
|
||||||
region = None
|
region = mode = None
|
||||||
while True:
|
while True:
|
||||||
if not w.bot_mining(cp): # only during a mining session
|
if not w.bot_mining(cp): # only during a mining session
|
||||||
tracker.h.clear()
|
tracker.h.clear()
|
||||||
time.sleep(15)
|
time.sleep(15)
|
||||||
continue
|
continue
|
||||||
if region is None:
|
if region is None:
|
||||||
region = get_region(cp)
|
region, mode = get_region(cp)
|
||||||
if region is None:
|
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))
|
time.sleep(max(poll, 15))
|
||||||
continue
|
continue
|
||||||
w.heartbeat(cp, "rock")
|
w.heartbeat(cp, "rock")
|
||||||
try:
|
try:
|
||||||
text = pytesseract.image_to_string(w.grab_region(region))
|
rows = read_rows(cp, region, mode)
|
||||||
rows = parse_survey(text)
|
|
||||||
if not rows:
|
if not rows:
|
||||||
region = None # lost it; re-detect next loop
|
region = None # lost it; re-detect next loop
|
||||||
time.sleep(poll)
|
time.sleep(poll)
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue