From ba5b853cb9dfe63a037c89c429f6a6f21c27deef Mon Sep 17 00:00:00 2001 From: LmeSzinc <37934724+LmeSzinc@users.noreply.github.com> Date: Mon, 9 Dec 2024 16:09:34 +0800 Subject: [PATCH] Refactor: Standardize the use of match_template_color() --- module/base/base.py | 32 ++++++++++++++++++++++++++++ module/base/button.py | 20 +++++++++++------ module/commission/commission.py | 3 +-- module/dorm/buy_furniture.py | 3 +-- module/freebies/battle_pass.py | 3 +-- module/handler/login.py | 2 +- module/handler/strategy.py | 3 +-- module/map/map_operation.py | 6 ++---- module/meowfficer/base.py | 3 +-- module/meowfficer/buy.py | 3 +-- module/meowfficer/collect.py | 3 +-- module/meta_reward/meta_reward.py | 6 ++---- module/os/fleet.py | 3 ++- module/os_ash/meta.py | 6 ++---- module/os_handler/action_point.py | 3 +-- module/os_handler/enemy_searching.py | 2 +- module/os_handler/map_event.py | 15 +++++-------- module/os_handler/mission.py | 9 +++----- module/os_handler/strategic.py | 3 +-- module/retire/retirement.py | 11 ++++------ module/reward/reward.py | 3 +-- module/storage/ui.py | 3 +-- 22 files changed, 79 insertions(+), 66 deletions(-) diff --git a/module/base/base.py b/module/base/base.py index 85563306a..4646baee5 100644 --- a/module/base/base.py +++ b/module/base/base.py @@ -176,6 +176,38 @@ class ModuleBase: return appear + def match_template_color(self, button, offset=(20, 20), interval=0, similarity=0.85, threshold=30): + """ + Args: + button (Button): + offset (bool, int): + interval (int, float): interval between two active events. + similarity (int, float): 0 to 1. + threshold (int, float): 0 to 255 if not use offset, smaller means more similar + + Returns: + bool: + """ + button = self.ensure_button(button) + self.device.stuck_record_add(button) + + if interval: + if button.name in self.interval_timer: + if self.interval_timer[button.name].limit != interval: + self.interval_timer[button.name] = Timer(interval) + else: + self.interval_timer[button.name] = Timer(interval) + if not self.interval_timer[button.name].reached(): + return False + + appear = button.match_template_color( + self.device.image, offset=offset, similarity=similarity, threshold=threshold) + + if appear and interval: + self.interval_timer[button.name].reset() + + return appear + def appear_then_click(self, button, screenshot=False, genre='items', offset=0, interval=0, similarity=0.85, threshold=30): button = self.ensure_button(button) diff --git a/module/base/button.py b/module/base/button.py index 0344dc266..6c550b4de 100644 --- a/module/base/button.py +++ b/module/base/button.py @@ -321,18 +321,26 @@ class Button(Resource): self._button_offset = area_offset(self._button, offset[:2] + np.array(point)) return sim > similarity - def match_appear_on(self, image, threshold=30): + def match_template_color(self, image, offset=(20, 20), similarity=0.85, threshold=30): """ + Template match first, color match then + Args: image: Screenshot. - threshold: Default to 10. + offset (int, tuple): Detection area offset. + similarity (float): 0-1. + threshold (int): Default to 30. Returns: - bool: + bool. """ - diff = np.subtract(self.button, self._button)[:2] - area = area_offset(self.area, offset=diff) - return color_similar(color1=get_color(image, area), color2=self.color, threshold=threshold) + if self.match(image, offset=offset, similarity=similarity): + diff = np.subtract(self.button, self._button)[:2] + area = area_offset(self.area, offset=diff) + color = get_color(image, area) + return color_similar(color1=color, color2=self.color, threshold=threshold) + else: + return False def crop(self, area, image=None, name=None): """ diff --git a/module/commission/commission.py b/module/commission/commission.py index edaf58505..727b51779 100644 --- a/module/commission/commission.py +++ b/module/commission/commission.py @@ -363,8 +363,7 @@ class RewardCommission(UI, InfoHandler): raise GameStuckError('Triggered commission list flashing bug') # Click - if (self.appear(COMMISSION_START, offset=(5, 20), interval=7) - and COMMISSION_START.match_appear_on(self.device.image)): + if self.match_template_color(COMMISSION_START, offset=(5, 20), interval=7): self.device.click(COMMISSION_START) self.interval_reset(COMMISSION_ADVICE) comm_timer.reset() diff --git a/module/dorm/buy_furniture.py b/module/dorm/buy_furniture.py index 4d2061d38..2f9e62579 100644 --- a/module/dorm/buy_furniture.py +++ b/module/dorm/buy_furniture.py @@ -183,8 +183,7 @@ class BuyFurniture(UI): False if Failed buy """ self.enter_first_furniture_details_page() - if self.appear(DORM_FURNITURE_COUNTDOWN, offset=(20, 20)) \ - and DORM_FURNITURE_COUNTDOWN.match_appear_on(self.device.image): + if self.match_template_color(DORM_FURNITURE_COUNTDOWN, offset=(20, 20)): logger.info("There is a time-limited furniture available for buy") if self.buy_furniture_once(self.config.BuyFurniture_BuyOption): diff --git a/module/freebies/battle_pass.py b/module/freebies/battle_pass.py index a5d977e56..75dadff99 100644 --- a/module/freebies/battle_pass.py +++ b/module/freebies/battle_pass.py @@ -73,8 +73,7 @@ class BattlePass(Combat, UI): if self.appear_then_click(REWARD_RECEIVE, offset=(20, 20), interval=3): confirm_timer.reset() continue - if self.appear(REWARD_RECEIVE_SP, offset=(20, 20), interval=3) \ - and REWARD_RECEIVE_SP.match_appear_on(self.device.image, threshold=15): + if self.match_template_color(REWARD_RECEIVE_SP, offset=(20, 20), interval=3, threshold=15): self.device.click(REWARD_RECEIVE_SP) confirm_timer.reset() continue diff --git a/module/handler/login.py b/module/handler/login.py index bb4b0ed1c..bce990522 100644 --- a/module/handler/login.py +++ b/module/handler/login.py @@ -50,7 +50,7 @@ class LoginHandler(UI): confirm_timer.reset() # Login - if self.appear(LOGIN_CHECK, offset=(30, 30), interval=5) and LOGIN_CHECK.match_appear_on(self.device.image): + if self.match_template_color(LOGIN_CHECK, offset=(30, 30), interval=5): self.device.click(LOGIN_CHECK) if not login_success: logger.info('Login success') diff --git a/module/handler/strategy.py b/module/handler/strategy.py index 7b78fd1e3..b3ff703c5 100644 --- a/module/handler/strategy.py +++ b/module/handler/strategy.py @@ -217,8 +217,7 @@ class StrategyHandler(InfoHandler): in: STRATEGY_OPENED out: STRATEGY_OPENED """ - if (self.appear(MOB_MOVE_ENTER, offset=MOB_MOVE_OFFSET) - and MOB_MOVE_ENTER.match_appear_on(self.device.image)): + if self.match_template_color(MOB_MOVE_ENTER, offset=MOB_MOVE_OFFSET): return True else: return False diff --git a/module/map/map_operation.py b/module/map/map_operation.py index e7fff3314..4a9de599a 100644 --- a/module/map/map_operation.py +++ b/module/map/map_operation.py @@ -269,8 +269,7 @@ class MapOperation(MysteryHandler, FleetPreparation, Retirement, FastForwardHand return True if mode == 'normal': - if self.appear(MAP_MODE_SWITCH_NORMAL, offset=(20, 20)) \ - and MAP_MODE_SWITCH_NORMAL.match_appear_on(self.device.image): + if self.match_template_color(MAP_MODE_SWITCH_NORMAL, offset=(20, 20)): logger.attr('MAP_MODE_SWITCH', 'normal') return True elif self.appear(MAP_MODE_SWITCH_HARD, offset=(20, 20), interval=2): @@ -281,8 +280,7 @@ class MapOperation(MysteryHandler, FleetPreparation, Retirement, FastForwardHand else: return False elif mode == 'hard': - if self.appear(MAP_MODE_SWITCH_HARD, offset=(20, 20)) \ - and MAP_MODE_SWITCH_HARD.match_appear_on(self.device.image): + if self.match_template_color(MAP_MODE_SWITCH_HARD, offset=(20, 20)): logger.attr('MAP_MODE_SWITCH', 'hard') return True if self.appear(MAP_MODE_SWITCH_NORMAL, offset=(20, 20), interval=2): diff --git a/module/meowfficer/base.py b/module/meowfficer/base.py index 02f98159c..0c5fcdc1a 100644 --- a/module/meowfficer/base.py +++ b/module/meowfficer/base.py @@ -69,8 +69,7 @@ class MeowfficerBase(UI): self.device.screenshot() # End - if self.appear(MEOWFFICER_CHECK, offset=(20, 20)) \ - and MEOWFFICER_CHECK.match_appear_on(self.device.image): + if self.match_template_color(MEOWFFICER_CHECK, offset=(20, 20)): break else: if click_timer.reached(): diff --git a/module/meowfficer/buy.py b/module/meowfficer/buy.py index 213841480..c76abdba1 100644 --- a/module/meowfficer/buy.py +++ b/module/meowfficer/buy.py @@ -99,8 +99,7 @@ class MeowfficerBuy(MeowfficerBase): continue # End - if self.appear(MEOWFFICER_BUY_ENTER, offset=(20, 20)) \ - and MEOWFFICER_BUY_ENTER.match_appear_on(self.device.image): + if self.match_template_color(MEOWFFICER_BUY_ENTER, offset=(20, 20)): break def meow_buy(self) -> bool: diff --git a/module/meowfficer/collect.py b/module/meowfficer/collect.py index 673aa4a2c..1ff9e10f0 100644 --- a/module/meowfficer/collect.py +++ b/module/meowfficer/collect.py @@ -75,8 +75,7 @@ class MeowfficerCollect(MeowfficerBase): Returns: bool """ - if self.appear(MEOWFFICER_GET_CHECK, offset=(40, 40)) and MEOWFFICER_GET_CHECK.match_appear_on( - self.device.image): + if self.match_template_color(MEOWFFICER_GET_CHECK, offset=(40, 40)): return True if self.appear(MEOWFFICER_TRAIN_START, offset=(20, 20)): diff --git a/module/meta_reward/meta_reward.py b/module/meta_reward/meta_reward.py index b701e930b..66512e98b 100644 --- a/module/meta_reward/meta_reward.py +++ b/module/meta_reward/meta_reward.py @@ -64,8 +64,7 @@ class BeaconReward(Combat, UI): else: self.device.screenshot() - if self.appear(REWARD_RECEIVE, offset=(20, 20), interval=3) and REWARD_RECEIVE.match_appear_on( - self.device.image): + if self.match_template_color(REWARD_RECEIVE, offset=(20, 20), interval=3): self.device.click(REWARD_RECEIVE) confirm_timer.reset() continue @@ -166,8 +165,7 @@ class DossierReward(Combat, UI): else: self.device.screenshot() - if self.appear(DOSSIER_REWARD_RECEIVE, offset=(20, 20), interval=3) and DOSSIER_REWARD_RECEIVE.match_appear_on( - self.device.image): + if self.match_template_color(DOSSIER_REWARD_RECEIVE, offset=(20, 20), interval=3): self.device.click(DOSSIER_REWARD_RECEIVE) confirm_timer.reset() continue diff --git a/module/os/fleet.py b/module/os/fleet.py index aff0ecef0..77d63638a 100644 --- a/module/os/fleet.py +++ b/module/os/fleet.py @@ -369,7 +369,8 @@ class OSFleet(OSCamera, Combat, Fleet, OSAsh): # Arrive # Check colors, because screen goes black when something is unlocking. - if self.is_in_map() and IN_MAP.match_appear_on(self.device.image): + # A direct use of IN_MAP, basically `self.is_in_map() and IN_MAP.match_template_color()` + if self.match_template_color(IN_MAP, offset=(200, 5)): self.update_os() current = self.view.backend.homo_loca logger.attr('homo_loca', current) diff --git a/module/os_ash/meta.py b/module/os_ash/meta.py index b1312d4da..3920b86a6 100644 --- a/module/os_ash/meta.py +++ b/module/os_ash/meta.py @@ -231,12 +231,10 @@ class OpsiAshBeacon(Meta): else: self.device.screenshot() - if self.appear(META_INNER_PAGE_DAMAGE, offset=(20, 20)) \ - and META_INNER_PAGE_DAMAGE.match_appear_on(self.device.image): + if self.match_template_color(META_INNER_PAGE_DAMAGE, offset=(20, 20)): logger.info('Already in meta damage page') break - if self.appear(META_INNER_PAGE_NOT_DAMAGE, offset=(20, 20)) \ - and META_INNER_PAGE_NOT_DAMAGE.match_appear_on(self.device.image): + if self.match_template_color(META_INNER_PAGE_NOT_DAMAGE, offset=(20, 20)): logger.info('In meta details page, should switch to damage page') self.appear_then_click(META_INNER_PAGE_NOT_DAMAGE, offset=(20, 20), interval=2) continue diff --git a/module/os_handler/action_point.py b/module/os_handler/action_point.py index 17084dd65..0bc485188 100644 --- a/module/os_handler/action_point.py +++ b/module/os_handler/action_point.py @@ -106,8 +106,7 @@ class ActionPointHandler(UI, MapEventHandler): return self.appear(ACTION_POINT_USE, offset=(20, 20)) def is_current_ap_visible(self): - return self.appear(CURRENT_AP_CHECK, offset=(40, 5)) \ - and CURRENT_AP_CHECK.match_appear_on(self.device.image, threshold=15) + return self.match_template_color(CURRENT_AP_CHECK, offset=(40, 5), threshold=15) def action_point_use(self, skip_first_screenshot=True): prev = self._action_point_current diff --git a/module/os_handler/enemy_searching.py b/module/os_handler/enemy_searching.py index 383e61a31..2394a0cd1 100644 --- a/module/os_handler/enemy_searching.py +++ b/module/os_handler/enemy_searching.py @@ -10,7 +10,7 @@ class EnemySearchingHandler(EnemySearchingHandler_): def is_in_map(self): if IN_MAP.match_luma(self.device.image, offset=(200, 5)): return True - if self.appear(MAP_GOTO_GLOBE_FOG, offset=(5, 5)) and MAP_GOTO_GLOBE_FOG.match_appear_on(self.device.image): + if self.match_template_color(MAP_GOTO_GLOBE_FOG, offset=(5, 5)): return True return False diff --git a/module/os_handler/map_event.py b/module/os_handler/map_event.py index 653ed46a9..ee3244460 100644 --- a/module/os_handler/map_event.py +++ b/module/os_handler/map_event.py @@ -244,14 +244,12 @@ class MapEventHandler(EnemySearchingHandler): Returns: bool: If clicked. """ - if self.appear(AUTO_SEARCH_OS_MAP_OPTION_OFF, offset=(5, 120)) \ - and AUTO_SEARCH_OS_MAP_OPTION_OFF.match_appear_on(self.device.image): + if self.match_template_color(AUTO_SEARCH_OS_MAP_OPTION_OFF, offset=(5, 120)): if self.info_bar_count() >= 2: self.device.screenshot_interval_set() self.os_auto_search_quit(drop=drop) raise CampaignEnd - if self.appear(AUTO_SEARCH_OS_MAP_OPTION_OFF_DISABLED, offset=(5, 120)) \ - and AUTO_SEARCH_OS_MAP_OPTION_OFF_DISABLED.match_appear_on(self.device.image): + if self.match_template_color(AUTO_SEARCH_OS_MAP_OPTION_OFF_DISABLED, offset=(5, 120)): if self.info_bar_count() >= 2: self.device.screenshot_interval_set() self.os_auto_search_quit(drop=drop) @@ -268,20 +266,17 @@ class MapEventHandler(EnemySearchingHandler): if enable is None: pass elif enable: - if self.appear(AUTO_SEARCH_OS_MAP_OPTION_OFF, offset=(5, 120), interval=3) \ - and AUTO_SEARCH_OS_MAP_OPTION_OFF.match_appear_on(self.device.image): + if self.match_template_color(AUTO_SEARCH_OS_MAP_OPTION_OFF, offset=(5, 120), interval=3): self.device.click(AUTO_SEARCH_OS_MAP_OPTION_OFF) self.interval_reset(AUTO_SEARCH_OS_MAP_OPTION_OFF_DISABLED) return True # Game client bugged sometimes, AUTO_SEARCH_OS_MAP_OPTION_OFF grayed out but still functional - if self.appear(AUTO_SEARCH_OS_MAP_OPTION_OFF_DISABLED, offset=(5, 120), interval=3) \ - and AUTO_SEARCH_OS_MAP_OPTION_OFF_DISABLED.match_appear_on(self.device.image): + if self.match_template_color(AUTO_SEARCH_OS_MAP_OPTION_OFF_DISABLED, offset=(5, 120), interval=3): self.device.click(AUTO_SEARCH_OS_MAP_OPTION_OFF_DISABLED) self.interval_reset(AUTO_SEARCH_OS_MAP_OPTION_OFF) return True else: - if self.appear(AUTO_SEARCH_OS_MAP_OPTION_ON, offset=(5, 120), interval=3) \ - and AUTO_SEARCH_OS_MAP_OPTION_ON.match_appear_on(self.device.image): + if self.match_template_color(AUTO_SEARCH_OS_MAP_OPTION_ON, offset=(5, 120), interval=3): self.device.click(AUTO_SEARCH_OS_MAP_OPTION_ON) return True diff --git a/module/os_handler/mission.py b/module/os_handler/mission.py index 51a0697f3..081ac2de4 100644 --- a/module/os_handler/mission.py +++ b/module/os_handler/mission.py @@ -81,15 +81,13 @@ class MissionHandler(GlobeOperation, ZoneManager): # End if self.is_in_os_mission() \ and not self.appear(MISSION_FINISH, offset=(20, 20)) \ - and not (self.appear(MISSION_CHECKOUT, offset=(20, 20)) - and MISSION_CHECKOUT.match_appear_on(self.device.image)): + and not self.match_template_color(MISSION_CHECKOUT, offset=(20, 20)): # No mission found, wait to confirm. Missions might not be loaded so fast. if confirm_timer.reached(): logger.info('No OS mission found.') break elif self.is_in_os_mission() \ - and (self.appear(MISSION_CHECKOUT, offset=(20, 20)) - and MISSION_CHECKOUT.match_appear_on(self.device.image)): + and self.match_template_color(MISSION_CHECKOUT, offset=(20, 20)): # Found one mission. logger.info('Found at least one OS missions.') break @@ -119,8 +117,7 @@ class MissionHandler(GlobeOperation, ZoneManager): logger.info('Monthly BOSS mission found, checking missions bellow it') checkout_offset = (-20, 100, 20, 150) - if not (self.appear(MISSION_CHECKOUT, offset=checkout_offset) - and MISSION_CHECKOUT.match_appear_on(self.device.image)): + if not self.match_template_color(MISSION_CHECKOUT, offset=checkout_offset): # If not having enough items to claim a mission, # there will still be MISSION_CHECKOUT, but button is transparent. # So here needs to use both template matching and color detection. diff --git a/module/os_handler/strategic.py b/module/os_handler/strategic.py index a808f3fdf..07eb97aa1 100644 --- a/module/os_handler/strategic.py +++ b/module/os_handler/strategic.py @@ -25,8 +25,7 @@ class StrategicSearchHandler(MapEventHandler): continue if self.appear(AUTO_SEARCH_REWARD, offset=(50, 50)): continue - if self.appear(STRATEGIC_SEARCH_MAP_OPTION_OFF, offset=(20, 20), interval=2) \ - and STRATEGIC_SEARCH_MAP_OPTION_OFF.match_appear_on(self.device.image): + if self.match_template_color(STRATEGIC_SEARCH_MAP_OPTION_OFF, offset=(20, 20), interval=2): self.device.click(STRATEGIC_SEARCH_MAP_OPTION_OFF) continue diff --git a/module/retire/retirement.py b/module/retire/retirement.py index 1059c3bce..622cc735c 100644 --- a/module/retire/retirement.py +++ b/module/retire/retirement.py @@ -110,12 +110,9 @@ class Retirement(Enhancement, QuickRetireSettingHandler): timeout.reset() # Click - if self.appear(SHIP_CONFIRM, offset=(30, 30), interval=2): - if SHIP_CONFIRM.match_appear_on(self.device.image): - self.device.click(SHIP_CONFIRM) - continue - else: - self.interval_clear(SHIP_CONFIRM) + if self.match_template_color(SHIP_CONFIRM, offset=(30, 30), interval=2): + self.device.click(SHIP_CONFIRM) + continue if self.appear(SHIP_CONFIRM_2, offset=(30, 30), interval=2): if self.retire_keep_common_cv and not self._have_kept_cv: self.keep_one_common_cv() @@ -259,7 +256,7 @@ class Retirement(Enhancement, QuickRetireSettingHandler): if selected == 0: break self.device.screenshot() - if not (self.appear(SHIP_CONFIRM, offset=(30, 30)) and SHIP_CONFIRM.match_appear_on(self.device.image)): + if not self.match_template_color(SHIP_CONFIRM, offset=(30, 30)): logger.warning('No ship selected, retrying') continue diff --git a/module/reward/reward.py b/module/reward/reward.py index 21f660778..4d790ba4b 100644 --- a/module/reward/reward.py +++ b/module/reward/reward.py @@ -103,8 +103,7 @@ class Reward(UI): for button in [MISSION_MULTI, MISSION_SINGLE]: if not click_timer.reached(): continue - if self.appear(button, offset=(20, 200), interval=interval) \ - and button.match_appear_on(self.device.image): + if self.match_template_color(button, offset=(20, 200), interval=interval): self.device.click(button) exit_timer.reset() click_timer.reset() diff --git a/module/storage/ui.py b/module/storage/ui.py index 06e53df1f..9ba518954 100644 --- a/module/storage/ui.py +++ b/module/storage/ui.py @@ -40,8 +40,7 @@ class StorageUI(UI): Returns: bool, if in MATERIAL_CHECK, appear and match_appear_on """ - return self.appear(MATERIAL_CHECK, offset=(20, 20), interval=interval) \ - and MATERIAL_CHECK.match_appear_on(self.device.image) + return self.match_template_color(MATERIAL_CHECK, offset=(20, 20), interval=interval) def _storage_enter_material(self, skip_first_screenshot=True): """