"""首页任务奖励领取流程。""" import time from .engine import WorkflowError class TaskRunner: def __init__(self, desktop, matcher, flow, region_provider, log=print, timeout=12): self.desktop = desktop self.matcher = matcher self.flow = flow self.region_provider = region_provider self.log = log self.timeout = timeout def observe(self): screenshot = self.desktop.screenshot() region = self.region_provider(screenshot) return screenshot, region, self.matcher.frame(screenshot, region) def wait(self, *names): deadline = time.monotonic() + self.timeout previous, stable = None, 0 while time.monotonic() < deadline: screenshot, region, frame = self.observe() found = next((name for name in names if self.matcher.matches(frame, self.flow['states'][name])), None) stable = stable + 1 if found and found == previous else 1 if found else 0 previous = found if stable >= 2: return found, screenshot, region, frame time.sleep(0.25) raise WorkflowError('未识别到预期页面 ' + '/'.join(names) + ',已停止。') def click(self, point, screenshot, region, hold=0.2): if self.region_provider(screenshot) != region: raise WorkflowError('识别后游戏窗口移动,已停止,请重新运行。') self.desktop.click(point, region, screenshot.size, hold=hold) def click_action(self, action, observation): _, screenshot, region, _ = observation self.click(self.flow['clicks'][action], screenshot, region) self.log('已执行:' + action) def claim_location(self, frame): spec = self.flow['claim_button'] score, location = self.matcher.locate(frame, spec) if score < spec.get('threshold', 0.86): return None x, y, width, height = location return ((x + width / 2) / 562, (y + height / 2) / 1002) def panel_dot(self, frame, panel): spec = self.flow['tab_dots'][panel] return self.matcher.score(frame, spec) >= spec.get('threshold', 0.86) def claim_panel(self, panel): count = 0 while count < self.flow['max_claims_per_panel']: name, screenshot, region, frame = self.wait(panel) location = self.claim_location(frame) if location is None: return count self.click(location, screenshot, region, hold=0.8) count += 1 self.log('已执行:%s 第 %s 个领取按钮。' % (panel, count)) reward = self.wait('reward') self.click_action('dismiss_reward', reward) raise WorkflowError('单个面板领取次数超过安全上限,已停止。') def close_and_home(self): panel = self.wait('daily', 'weekly') self.click_action('close', panel) self.wait('home') self.log('已确认返回首页。') def run(self, dry_run=False): home = self.wait('home') if dry_run: self.log('首页识别通过。计划:检测任务红点 → 日常/周常领取 → 关闭任务 → 返回首页。未点击。') return 'preview' _, screenshot, region, frame = home if not self.matcher.matches(frame, self.flow['task_dot']): self.log('任务按钮没有红点,本次不进入任务面板。') return 'no_task_dot' self.click_action('open_tasks', home) panel = self.wait('daily', 'weekly') current = panel[0] claimed = self.claim_panel(current) self.log('%s 面板领取 %s 个奖励。' % (current, claimed)) other = 'weekly' if current == 'daily' else 'daily' _, screenshot, region, frame = self.wait(current) if self.panel_dot(frame, other): self.click_action('open_' + other, (current, screenshot, region, frame)) claimed += self.claim_panel(other) self.log('%s 面板领取完成。' % other) else: self.log('%s 标签没有红点,不切换。' % other) self.close_and_home() return 'claimed' if claimed else 'no_claim_button'