diff --git a/assets/share/battle_pass/OCR_REMAINING_TIME.png b/assets/share/battle_pass/OCR_REMAINING_TIME.png new file mode 100644 index 000000000..30d967ec2 Binary files /dev/null and b/assets/share/battle_pass/OCR_REMAINING_TIME.png differ diff --git a/module/config/config.py b/module/config/config.py index 6e2520c81..aaeea7101 100644 --- a/module/config/config.py +++ b/module/config/config.py @@ -264,6 +264,7 @@ class AzurLaneConfig(ConfigUpdater, ManualConfig, GeneratedConfig, ConfigWatcher if isinstance(next_run, datetime) and next_run > limit: deep_set(self.data, keys=f"{task}.Scheduler.NextRun", value=now) + limit_next_run(['BattlePass'], limit=now + timedelta(days=31, seconds=-1)) limit_next_run(self.args.keys(), limit=now + timedelta(hours=24, seconds=-1)) def override(self, **kwargs): diff --git a/module/ocr/ocr.py b/module/ocr/ocr.py index d8e669bdd..fd5711db8 100644 --- a/module/ocr/ocr.py +++ b/module/ocr/ocr.py @@ -283,14 +283,14 @@ class Duration(Ocr): @cached_property def timedelta_regex(self): regex_str = { - 'ch': r'\D*((?P\d{1,2})小时)?((?P\d{1,2})分钟)?((?P\d{1,2})秒})?', - 'en': r'\D*((?P\d{1,2})h\s*)?((?P\d{1,2})m\s*)?((?P\d{1,2})s)?' + 'ch': r'\D*((?P\d{1,2})天)?((?P\d{1,2})小时)?((?P\d{1,2})分钟)?((?P\d{1,2})秒})?', + 'en': r'\D*((?P\d{1,2})d\s*)?((?P\d{1,2})h\s*)?((?P\d{1,2})m\s*)?((?P\d{1,2})s)?' }[self.lang] return re.compile(regex_str) def format_result(self, result: str) -> timedelta: """ - Do OCR on a duration, such as `2h 13m 30s`, `2h`, `13m 30s`, `9s` + Do OCR on a duration, such as `18d 2h 13m 30s`, `2h`, `13m 30s`, `9s` Returns: timedelta: @@ -298,10 +298,11 @@ class Duration(Ocr): matched = self.timedelta_regex.match(result) if matched is None: return timedelta() + days = self._sanitize_number(matched.group('days')) hours = self._sanitize_number(matched.group('hours')) minutes = self._sanitize_number(matched.group('minutes')) seconds = self._sanitize_number(matched.group('seconds')) - return timedelta(hours=hours, minutes=minutes, seconds=seconds) + return timedelta(days=days, hours=hours, minutes=minutes, seconds=seconds) @staticmethod def _sanitize_number(number) -> int: diff --git a/tasks/battle_pass/assets/assets_battle_pass.py b/tasks/battle_pass/assets/assets_battle_pass.py index 2ac516e5e..df6c7aecb 100644 --- a/tasks/battle_pass/assets/assets_battle_pass.py +++ b/tasks/battle_pass/assets/assets_battle_pass.py @@ -63,6 +63,16 @@ OCR_LEVEL = ButtonWrapper( button=(183, 93, 240, 134), ), ) +OCR_REMAINING_TIME = ButtonWrapper( + name='OCR_REMAINING_TIME', + share=Button( + file='./assets/share/battle_pass/OCR_REMAINING_TIME.png', + area=(289, 89, 630, 132), + search=(269, 69, 650, 152), + color=(66, 63, 57), + button=(289, 89, 630, 132), + ), +) REWARDS_CHECK = ButtonWrapper( name='REWARDS_CHECK', share=Button( diff --git a/tasks/battle_pass/battle_pass.py b/tasks/battle_pass/battle_pass.py index 4bfdc4152..b12a5efb8 100644 --- a/tasks/battle_pass/battle_pass.py +++ b/tasks/battle_pass/battle_pass.py @@ -3,7 +3,7 @@ import numpy as np from module.base.timer import Timer from module.base.utils import get_color from module.logger.logger import logger -from module.ocr.ocr import Digit +from module.ocr.ocr import Digit, Duration from module.ui.switch import Switch from tasks.base.assets.assets_base_page import BATTLE_PASS_CHECK from tasks.base.assets.assets_base_popup import GET_REWARD @@ -26,6 +26,8 @@ SWITCH_BATTLE_PASS_TAB.add_state( class BattlePassUI(UI): + MAX_LEVEL = 50 + def _battle_pass_wait_rewards_loaded(self, skip_first_screenshot=True): timeout = Timer(2, count=4).start() while 1: @@ -150,6 +152,9 @@ class BattlePassUI(UI): digit = Digit(OCR_LEVEL) return digit.ocr_single_line(self.device.image) + def _get_remaining_time(self): + return Duration(OCR_REMAINING_TIME).ocr_single_line(self.device.image) + def claim_battle_pass_rewards(self): """ Examples: @@ -159,16 +164,19 @@ class BattlePassUI(UI): """ self.ui_ensure(page_battle_pass) previous_level = self._get_battle_pass_level() + if previous_level == self.MAX_LEVEL: + return previous_level claimed_exp = self._claim_exp() - if claimed_exp and previous_level != 50 and self._get_battle_pass_level() > previous_level: + current_level = self._get_battle_pass_level() + if claimed_exp and current_level > previous_level: logger.info("Upgraded, go to claim rewards") self._claim_rewards() - return True + return current_level def run(self): - for _ in range(5): - claimed = self.claim_battle_pass_rewards() - if claimed: - break - - self.config.task_delay(server_update=True) + current_level = self.claim_battle_pass_rewards() + if current_level == self.MAX_LEVEL: + remaining_time = self._get_remaining_time() + self.config.task_delay(minute=remaining_time.total_seconds() / 60) + else: + self.config.task_delay(server_update=True)