import numpy as np from module.base.base import ModuleBase from module.base.timer import Timer from module.base.utils import area_size from module.logger import logger from module.ocr.ocr import DigitCounter from tasks.base.ui import UI from tasks.shop.assets.assets_shop import * ITEM_POSITIONS = { 1: (650, 200), 2: (805, 200), 3: (960, 200), 4: (1110, 200), 5: (650, 460), 6: (805, 460), 7: (960, 460), 8: (1110, 460), 9: (650, 200), 10: (805, 200), 11: (960, 200), 12: (1110, 200), 13: (650, 460), 14: (805, 460), 15: (960, 460), 16: (1110, 460), 17: (650, 460), 18: (805, 460), 19: (960, 460), 20: (1110, 460), } class ShopUI(UI): def __init__(self, config, device): super().__init__(config, device) self.click_coords = self.device.click_methods.get(self.config.Emulator_ControlMethod, self.device.click_adb) self.swipe_vector_range = (0.85, 0.9) self.swipe_flags = {8: False, 16: False} self.list = ITEM_LIST def swipe_page(self, direction: str, main: ModuleBase, vector_range=None, reverse=False): """ Args: direction: up, down main: vector_range (tuple[float, float]): reverse (bool): """ if vector_range is None: vector_range = self.swipe_vector_range vector = np.random.uniform(*vector_range) width, height = area_size(self.list.button) if direction == 'up': vector = (0, vector * height) elif direction == 'down': vector = (0, -vector * height) else: logger.warning(f'Unknown swipe direction: {direction}') return if reverse: vector = (-vector[0], -vector[1]) main.device.swipe_vector(vector, self.list.button) def select_then_check(self, dest_enter: ButtonWrapper, dest_check: ButtonWrapper): timer = Timer(5, 10).start() while 1: self.device.screenshot() self.appear_then_click(dest_enter, interval=1) if self.appear(dest_check): return True if timer.reached(): return False def select_shop(self, shop_switch): """ Set skip switch to on Returns: True if switch is set, False if switch not found """ if not shop_switch.appear(main=self): logger.info(f'{shop_switch.name} not found') return False shop_switch.set('on', main=self) return True def select_items(self, item_list): """ Select items in the item list checking if swipe is required each time. However, swipes are inaccurate and clicks too fast. """ timer = Timer(1).start() for item in item_list: if self.should_swipe(item): self.swipe_page('down', self) self.wait_until_stable( self.list.button, timer=Timer(3, 0), timeout=Timer(1.5, 5) ) while not timer.reached_and_reset(): pass self.click_coords(*ITEM_POSITIONS[item]) def should_swipe(self, item): """ Return True based on two checkpoints: one at 8 and the other at 16. Only once for each checkpoint. """ if (9 <= item <= 16) and not self.swipe_flags[8]: self.swipe_flags[8] = True return True elif item >= 17 and not self.swipe_flags[16]: self.swipe_flags[16] = True return True return False def reset_swipe_flags(self): self.swipe_flags[8], self.swipe_flags[16] = False, False def make_purchase(self): if self.match_color(PURCHASE) and self.select_then_check(PURCHASE, CONFIRM_PURCHASE) and self.appear_then_click( CONFIRM_PURCHASE): return True logger.warning("No items were selected. Unable to purchase.") return False def refresh_shop(self, need_count): """ Refresh the shop """ refresh_count = self.get_refresh_count() if refresh_count: purchased_count = 4 - refresh_count if need_count > purchased_count and self.appear_then_click(CONFIRM_REFRESH): logger.info("Refreshed the shop") return True return False def get_refresh_count(self): if not self.select_then_check(REFRESH, CONFIRM_REFRESH): logger.warning('OCR failed due to invalid page') return False count, _, total = DigitCounter(OCR_REFRESH).ocr_single_line(self.device.image) if total == 0: logger.warning('Invalid count') return False return count