Ejemplo n.º 1
0
    def _sos_is_appear_at_chapter(self, chapter):
        """
        Args:
            chapter (int): 3 to 10.

        Returns:
            bool:

        Pages:
            in: page_campaign
            out: page_campaign, may in different chapter.
        """
        self.ensure_campaign_ui(name=f'{chapter}-4', mode='normal')

        confirm_timer = Timer(1.5, count=3).start()
        while 1:
            self.device.screenshot()
            try:
                self.campaign_get_entrance('X-5')
                logger.info(f'Found SOS stage in chapter {chapter}')
                return True
            except CampaignNameError:
                if confirm_timer.reached():
                    logger.info(f'No SOS stage in chapter {chapter}')
                    return False
                else:
                    continue
Ejemplo n.º 2
0
    def _guild_operations_ensure(self, skip_first_screenshot=True):
        """
        Ensure guild operation is loaded
        After entering guild operation, background loaded first, then dispatch/boss
        """
        confirm_timer = Timer(1.5, count=3).start()
        while 1:
            if skip_first_screenshot:
                skip_first_screenshot = False
            else:
                self.device.screenshot()

            if self.appear(GUILD_OPERATIONS_JOIN, interval=3):
                confirm_timer.reset()
                if self.image_color_count(GUILD_OPERATIONS_MONTHLY_COUNT,
                                          color=(255, 93, 90),
                                          threshold=221,
                                          count=20):
                    self.device.click(GUILD_OPERATIONS_CLICK_SAFE_AREA)
                else:
                    self.device.click(GUILD_OPERATIONS_JOIN)
                continue

            # End
            if self.appear(GUILD_BOSS_ENTER) or self.appear(
                    GUILD_OPERATIONS_ACTIVE_CHECK, offset=(20, 20)):
                if not self.info_bar_count() and confirm_timer.reached():
                    break
Ejemplo n.º 3
0
    def wait_until_camera_stable(self, skip_first_screenshot=True):
        """
        Wait until homo_loca stabled.
        DETECTION_BACKEND must be 'homography'.
        """
        logger.hr('Wait until camera stable')
        record = None
        confirm_timer = Timer(0.6, count=2).start()
        while 1:
            if skip_first_screenshot:
                skip_first_screenshot = False
            else:
                self.device.screenshot()

            self.update_os()
            current = self.view.backend.homo_loca
            logger.attr('homo_loca', current)
            if record is None or (current is not None and np.linalg.norm(
                    np.subtract(current, record)) < 3):
                if confirm_timer.reached():
                    break
            else:
                confirm_timer.reset()

            record = current

        logger.info('Camera stabled')
Ejemplo n.º 4
0
    def set(self, status, main, skip_first_screenshot=True):
        """
        Args:
            status (str):
            main (ModuleBase):
            skip_first_screenshot (bool):

        Returns:
            bool:
        """
        changed = False
        warning_show_timer = Timer(5, count=10).start()
        while 1:
            if skip_first_screenshot:
                skip_first_screenshot = False
            else:
                main.device.screenshot()

            current = self.get(main=main)
            logger.attr(self.name, current)
            if current == status:
                return changed

            if current == 'unknown':
                if warning_show_timer.reached():
                    logger.warning(f'Unknown {self.name} switch')
                    warning_show_timer.reset()
                continue

            for data in self.status_list:
                if data['status'] == current:
                    main.device.click(data['click_button'])
                    main.device.sleep(data['sleep'])
                    changed = True
Ejemplo n.º 5
0
    def story_skip(self):
        if self.story_popup_timout.started() and not self.story_popup_timout.reached():
            if self.handle_popup_confirm('STORY_SKIP'):
                self.story_popup_timout = Timer(10)
                self.interval_reset(STORY_SKIP)
                self.interval_reset(STORY_LETTERS_ONLY)
                return True
        if self.appear(STORY_LETTER_BLACK) and self.appear_then_click(STORY_LETTERS_ONLY, offset=True, interval=2):
            self.story_popup_timout.reset()
            return True
        if self._story_option_timer.reached() and self.appear(STORY_SKIP, offset=True, interval=0):
            options = self._story_option_buttons()
            if len(options):
                self.device.click(options[0])
                self._story_option_timer.reset()
                self.story_popup_timout.reset()
                self.interval_reset(STORY_SKIP)
                self.interval_reset(STORY_LETTERS_ONLY)
                return True
        if self.appear_then_click(STORY_SKIP, offset=True, interval=2):
            self.story_popup_timout.reset()
            return True
        if self.appear_then_click(GAME_TIPS, offset=(20, 20), interval=2):
            self.story_popup_timout.reset()
            return True

        return False
Ejemplo n.º 6
0
    def handle_in_map_with_enemy_searching(self):
        if not self.is_in_map():
            return False

        timeout = Timer(self.MAP_ENEMY_SEARCHING_TIMEOUT_SECOND)
        appeared = False
        while 1:
            if self.is_in_map():
                timeout.start()
            else:
                timeout.reset()

            if self.handle_in_stage():
                return True
            if self.handle_story_skip():
                self.ensure_no_story()
                timeout.limit = 10
                timeout.reset()

            # End
            if self.enemy_searching_appear():
                appeared = True
            else:
                if appeared:
                    self.handle_enemy_flashing()
                    self.device.sleep(0.3)
                    logger.info('Enemy searching appeared.')
                    break
                self.enemy_searching_color_initial()
            if timeout.reached():
                logger.info('Enemy searching timeout.')
                break

            self.device.screenshot()
        return True
Ejemplo n.º 7
0
    def story_skip(self):
        if self.story_popup_timout.started(
        ) and not self.story_popup_timout.reached():
            if self.handle_popup_confirm('STORY_SKIP'):
                self.story_popup_timout = Timer(10)
                self.interval_reset(STORY_SKIP)
                self.interval_reset(STORY_LETTERS_ONLY)
                return True
        if self.appear_then_click(STORY_SKIP, offset=True, interval=2):
            self.story_popup_timout.reset()
            return True
        if self.appear(STORY_LETTER_BLACK) and self.appear_then_click(
                STORY_LETTERS_ONLY, offset=True, interval=2):
            self.story_popup_timout.reset()
            return True
        if self.appear_then_click(STORY_CHOOSE, offset=True, interval=2):
            self.story_popup_timout.reset()
            return True
        if self.appear_then_click(STORY_CHOOSE_2, offset=True, interval=2):
            self.story_popup_timout.reset()
            return True
        if self.appear_then_click(GAME_TIPS, offset=(20, 20), interval=2):
            self.story_popup_timout.reset()
            return True

        return False
Ejemplo n.º 8
0
    def _ash_enter_from_map(self, skip_first_screenshot=True):
        """
        Pages:
            in: is_in_map
            out: is_in_ash
        """
        in_map_timeout = Timer(2, count=3)
        while 1:
            if skip_first_screenshot:
                skip_first_screenshot = False
            else:
                self.device.screenshot()

            if in_map_timeout.reached() and self.is_in_map():
                self.device.click(ASH_COLLECT_STATUS)
                in_map_timeout.reset()
                continue
            if self.appear_then_click(ASH_ENTER_CONFIRM,
                                      offset=(20, 20),
                                      interval=2):
                continue
            if self.appear_then_click(BEACON_ENTER,
                                      offset=(20, 20),
                                      interval=2):
                continue
            if self._handle_ash_beacon_reward():
                continue

            # End:
            if self.appear(ASH_START, offset=(30, 30)):
                break
Ejemplo n.º 9
0
    def globe_focus_to(self, zone):
        """
        Args:
            zone (str, int, Zone): Name in CN/EN/JP/TW, zone id, or Zone instance.

        Pages:
            in: IN_GLOBE
            out: IN_GLOBE, zone selected, ZONE_ENTRANCE
        """
        zone = self.name_to_zone(zone)
        logger.info(f'Globe focus_to: {zone.zone_id}')

        interval = Timer(2, count=2)
        while 1:
            if self.handle_zone_pinned():
                self.globe_update()
                continue

            self.globe_in_sight(zone)
            if interval.reached_and_reset():
                self.device.click(self.zone_to_button(zone))
                self.device.sleep(0.3)

            self.globe_update()

            if self.is_zone_pinned():
                if self.get_globe_pinned_zone() == zone:
                    logger.attr('Globe_pinned', zone)
                    break
Ejemplo n.º 10
0
    def gacha_load_ensure(self, skip_first_screenshot=True):
        """
        Switching between sidebar clicks for some
        takes a bit of processing before fully loading
        like guild logistics

        Args:
            skip_first_screenshot (bool):

        Returns:
            bool: Whether expected assets loaded completely
        """
        ensure_timeout = Timer(3, count=6).start()
        while 1:
            if skip_first_screenshot:
                skip_first_screenshot = False
            else:
                self.device.screenshot()

            # End
            results = [self.appear(button) for button in GACHA_LOAD_ENSURE_BUTTONS]
            if any(results):
                return True

            # Exception
            if ensure_timeout.reached():
                logger.warning('Wait for loaded assets is incomplete, ensure not guaranteed')
                return False
Ejemplo n.º 11
0
    def _handle_app_login(self):
        """
        Pages:
            in: Any page
            out: page_main
        """
        logger.hr('App login')

        confirm_timer = Timer(1.5, count=4).start()
        login_success = False
        while 1:
            self.device.screenshot()

            if self.handle_get_items(save_get_items=False):
                continue
            if self.handle_get_ship():
                continue
            if self.appear_then_click(LOGIN_ANNOUNCE,
                                      offset=(30, 30),
                                      interval=5):
                continue
            if self.appear(EVENT_LIST_CHECK, offset=(30, 30), interval=5):
                self.device.click(BACK_ARROW)
                continue
            if self.appear_then_click(MAINTENANCE_ANNOUNCE,
                                      offset=(30, 30),
                                      interval=5):
                continue
            if self.appear_then_click(LOGIN_GAME_UPDATE,
                                      offset=(30, 30),
                                      interval=5):
                continue
            if self.appear_then_click(LOGIN_RETURN_SIGN,
                                      offset=(30, 30),
                                      interval=5):
                continue
            if server.server == 'cn':
                if self.appear_then_click(LOGIN_CONFIRM, interval=5):
                    continue
            if self.handle_popup_confirm('LOGIN'):
                continue
            if self.handle_urgent_commission(save_get_items=False):
                continue
            if self.appear_then_click(GOTO_MAIN, offset=(30, 30), interval=5):
                continue

            if self.appear_then_click(LOGIN_CHECK, interval=5):
                if not login_success:
                    logger.info('Login success')
                    login_success = True
            if self.appear(MAIN_CHECK):
                if confirm_timer.reached():
                    logger.info('Login to main confirm')
                    break
            else:
                confirm_timer.reset()

        self.config.start_time = datetime.now()
        return True
Ejemplo n.º 12
0
    def research_project_start(self, project, skip_first_screenshot=True):
        """
        Args:
            project (ResearchProject):
            skip_first_screenshot:

        Returns:
            bool: If start success.
        """
        logger.info(f'Research project: {project}')
        if project in self.projects:
            index = self.projects.index(project)
        else:
            logger.warning(
                f'The project to start: {project} is not in known projects')
            return False
        logger.info(f'Research project: {index}')
        available = False
        click_timer = Timer(10)
        while 1:
            if skip_first_screenshot:
                skip_first_screenshot = False
            else:
                self.device.screenshot()

            max_rgb = np.max(rgb2gray(self.image_crop(RESEARCH_UNAVAILABLE)))

            # Don't use interval here, RESEARCH_CHECK already appeared 5 seconds ago
            if click_timer.reached() and self.appear(RESEARCH_CHECK,
                                                     offset=(20, 20)):
                i = (index - self._research_project_offset) % 5
                logger.info(
                    f'Project offset: {self._research_project_offset}, project {index} is at {i}'
                )
                self.device.click(RESEARCH_ENTRANCE[i])
                self._research_project_offset = (index - 2) % 5
                self.ensure_research_stable()
                click_timer.reset()
                continue
            if max_rgb > 235 and self.appear_then_click(
                    RESEARCH_START, offset=(5, 20), interval=10):
                available = True
                continue
            if self.handle_popup_confirm('RESEARCH_START'):
                continue

            # End
            if self.appear(RESEARCH_STOP, offset=(20, 20)):
                # RESEARCH_STOP is a semi-transparent button, color will vary depending on the background.
                self.research_detail_quit()
                # self.ensure_no_info_bar(timeout=3)  # Research started
                self.research_project_started = project
                return True
            if not available and max_rgb <= 235 and self.appear(
                    RESEARCH_UNAVAILABLE, offset=(5, 20)):
                logger.info('Not enough resources to start this project')
                self.research_detail_quit()
                self.research_project_started = None
                return False
Ejemplo n.º 13
0
    def shop_buy_select_execute(self, item):
        """
        Args:
            item (Item):

        Returns:
            bool:
        """
        # Search for appropriate select grid button for item
        select = self.shop_get_select(item)

        # Get displayed stock limit; varies between shops
        # If read 0, then warn and exit as cannot safely buy
        _, _, limit = OCR_SHOP_SELECT_STOCK.ocr(self.device.image)
        if not limit:
            logger.critical(f'{item.name}\'s stock count cannot be '
                            'extracted. Advised to re-cut the asset '
                            'OCR_SHOP_SELECT_STOCK')
            raise ScriptError

        # Click in intervals until plus/minus are onscreen
        click_timer = Timer(3, count=6)
        select_offset = (500, 400)
        while 1:
            if click_timer.reached():
                self.device.click(select)
                click_timer.reset()

            # Scan for plus/minus locations; searching within
            # offset will update the click position automatically
            self.device.screenshot()
            if self.appear(SELECT_MINUS, offset=select_offset) and self.appear(SELECT_PLUS, offset=select_offset):
                break
            else:
                continue

        # Total number to purchase altogether
        total = int(self._currency // item.price)
        diff = limit - total
        if diff > 0:
            limit = total

        # Alias OCR_SHOP_SELECT_STOCK to adapt with
        # ui_ensure_index; prevent overbuying when
        # out of stock; item.price may still evaluate
        # incorrectly
        def shop_buy_select_ensure_index(image):
            current, remain, _ = OCR_SHOP_SELECT_STOCK.ocr(image)
            if not current:
                group_case = item.group.title() if len(item.group) > 2 else item.group.upper()
                logger.info(f'{group_case}(s) out of stock; exit to prevent overbuying')
                return limit
            return remain

        self.ui_ensure_index(limit, letter=shop_buy_select_ensure_index, prev_button=SELECT_MINUS,
                             next_button=SELECT_PLUS,
                             skip_first_screenshot=True)
        self.device.click(SHOP_BUY_CONFIRM_SELECT)
        return True
Ejemplo n.º 14
0
    def os_auto_search_daemon(self, drop=None, skip_first_screenshot=True):
        """
        Raises:
            CampaignEnd: If auto search ended
            RequestHumanTakeover: If there's no auto search option.

        Pages:
            in: AUTO_SEARCH_OS_MAP_OPTION_OFF
            out: AUTO_SEARCH_OS_MAP_OPTION_OFF and info_bar_count() >= 2, if no more objects to clear on this map.
                 AUTO_SEARCH_REWARD if get auto search reward.
        """
        logger.hr('OS auto search', level=2)
        self._auto_search_battle_count = 0
        unlock_checked = True
        unlock_check_timer = Timer(5, count=10).start()
        self.ash_popup_canceled = False

        success = True
        died_timer = Timer(1.5, count=3)
        while 1:
            if skip_first_screenshot:
                skip_first_screenshot = False
            else:
                self.device.screenshot()

            if not unlock_checked and unlock_check_timer.reached():
                logger.critical('Unable to use auto search in current zone')
                logger.critical('Please finish the story mode of OpSi to unlock auto search '
                                'before using any OpSi functions')
                raise RequestHumanTakeover
            if self.is_in_map():
                self.device.stuck_record_clear()
                if not success:
                    if died_timer.reached():
                        logger.warning('Fleet died confirm')
                        break
                else:
                    died_timer.reset()
            else:
                died_timer.reset()
            if self.handle_os_auto_search_map_option(drop=drop, enable=success):
                unlock_checked = True
                continue
            if self.handle_retirement():
                # Retire will interrupt auto search, need a retry
                self.ash_popup_canceled = True
                continue
            if self.combat_appear():
                self._auto_search_battle_count += 1
                logger.attr('battle_count', self._auto_search_battle_count)
                result = self.auto_search_combat(drop=drop)
                if not result:
                    success = False
                    logger.warning('Fleet died, stop auto search')
                    continue
            if self.handle_map_event():
                # Auto search can not handle siren searching device.
                continue
Ejemplo n.º 15
0
    def multi_click(self, button, n, interval=(0.1, 0.2)):
        click_timer = Timer(0.1)
        for _ in range(n):
            remain = ensure_time(interval) - click_timer.current()
            if remain > 0:
                self.sleep(remain)

            click_timer.reset()
            self.click(button)
Ejemplo n.º 16
0
    def ensure_no_info_bar(self, timeout=0.6):
        timeout = Timer(timeout)
        timeout.start()
        while 1:
            self.device.screenshot()
            self.handle_info_bar()

            if timeout.reached():
                break
Ejemplo n.º 17
0
    def appear(self, button, offset=0, interval=0, threshold=None):
        """
        Args:
            button (Button, Template, HierarchyButton, str):
            offset (bool, int):
            interval (int, float): interval between two active events.
            threshold (int, float): 0 to 1 if use offset, bigger means more similar,
                0 to 255 if not use offset, smaller means more similar

        Returns:
            bool:

        Examples:
            Image detection:
            ```
            self.device.screenshot()
            self.appear(Button(area=(...), color=(...), button=(...))
            self.appear(Template(file='...')
            ```

            Hierarchy detection (detect elements with xpath):
            ```
            self.device.dump_hierarchy()
            self.appear('//*[@resource-id="..."]')
            ```
        """
        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

        if isinstance(button, HierarchyButton):
            appear = bool(button)
        elif offset:
            if isinstance(offset, bool):
                offset = self.config.BUTTON_OFFSET
            appear = button.match(self.device.image,
                                  offset=offset,
                                  threshold=self.config.BUTTON_MATCH_SIMILARITY
                                  if threshold is None else threshold)
        else:
            appear = button.appear_on(
                self.device.image,
                threshold=self.config.COLOR_SIMILAR_THRESHOLD
                if threshold is None else threshold)

        if appear and interval:
            self.interval_timer[button.name].reset()

        return appear
Ejemplo n.º 18
0
    def os_mission_overview_accept(self):
        """
        Accept all missions in mission overview.

        Returns:
            bool: True if all missions accepted or no mission found.
                  False if unable to accept more missions.

        Pages:
            in: is_in_map
            out: is_in_map
        """
        logger.hr('OS mission overview accept', level=1)
        # is_in_map
        self.os_map_goto_globe(unpin=False)
        # is_in_globe
        self.ui_click(MISSION_OVERVIEW_ENTER,
                      check_button=MISSION_OVERVIEW_CHECK,
                      offset=(200, 20),
                      retry_wait=3,
                      skip_first_screenshot=True)

        # MISSION_OVERVIEW_CHECK
        confirm_timer = Timer(1, count=3).start()
        skip_first_screenshot = True
        success = True
        while 1:
            if skip_first_screenshot:
                skip_first_screenshot = False
            else:
                self.device.screenshot()

            if self.appear_then_click(MISSION_OVERVIEW_ACCEPT,
                                      offset=(20, 20),
                                      interval=0.2):
                confirm_timer.reset()
                continue
            else:
                # End
                if confirm_timer.reached():
                    success = True
                    break

            if self.info_bar_count():
                logger.info(
                    'Unable to accept missions, because reached the maximum number of missions'
                )
                success = False
                break

        # is_in_globe
        self.ui_back(appear_button=MISSION_OVERVIEW_CHECK,
                     check_button=self.is_in_globe,
                     skip_first_screenshot=True)
        # is_in_map
        self.os_globe_goto_map()
        return success
Ejemplo n.º 19
0
    def _enhance_choose_simple(self, skip_first_screenshot=True):
        """
        Info:
            Simplified version of the legacy _enhance_choose
            Performs enhancements solely based on appearance
            of info bars

        Pages:
            in: page_ship_enhance, without info_bar
            out: EQUIP_CONFIRM
        """
        end_activate_timer = Timer(2, count=2)
        attempt_count = 0
        next_count = 0
        while 1:
            if skip_first_screenshot:
                skip_first_screenshot = False
            else:
                self.device.screenshot()

            if self.appear(EQUIP_CONFIRM, offset=(30, 30)):
                return True

            if not end_activate_timer.reached_and_reset():
                continue

            ensured = self.equip_sidebar_ensure(index=4)
            if ensured:
                self.wait_until_appear(ENHANCE_RECOMMEND,
                                       offset=(5, 5),
                                       skip_first_screenshot=True)
            else:
                continue

            if self.info_bar_count():
                if attempt_count >= 1:
                    logger.info('Unable to enhance this ship, swipe to next')
                    swiped = self.equip_view_next(
                        check_button=ENHANCE_RECOMMEND)
                    self.ensure_no_info_bar()
                    if not swiped or next_count >= 3:
                        return False
                    else:
                        attempt_count = 0
                        logger.info(
                            f'Try next ship: {3 - next_count}/3 remaining until give up'
                        )
                        next_count += 1
                        continue
                attempt_count += 1

            if self.appear_then_click(ENHANCE_RECOMMEND,
                                      offset=(5, 5),
                                      interval=2):
                self.device.sleep(0.3)
                self.device.click(ENHANCE_CONFIRM)
Ejemplo n.º 20
0
    def commission_receive(self, skip_first_screenshot=True):
        """
        Args:
            skip_first_screenshot:

        Returns:
            bool: If rewarded.

        Pages:
            in: page_reward
            out: page_commission
        """
        logger.hr('Reward receive')

        reward = False
        click_timer = Timer(1)
        with self.stat.new(
                'commission',
                save=self.config.DropRecord_SaveCommission,
                upload=self.config.DropRecord_UploadCommission) as drop:
            while 1:
                if skip_first_screenshot:
                    skip_first_screenshot = False
                else:
                    self.device.screenshot()

                for button in [
                        EXP_INFO_S_REWARD, GET_ITEMS_1, GET_ITEMS_2,
                        GET_ITEMS_3, GET_SHIP
                ]:
                    if self.appear(button, interval=1):
                        self.ensure_no_info_bar(timeout=1)
                        drop.add(self.device.image)

                        REWARD_SAVE_CLICK.name = button.name
                        self.device.click(REWARD_SAVE_CLICK)
                        click_timer.reset()
                        reward = True
                        continue
                if click_timer.reached() and self.appear_then_click(
                        REWARD_1, interval=1):
                    click_timer.reset()
                    reward = True
                    continue
                if click_timer.reached() and self.appear_then_click(
                        REWARD_GOTO_COMMISSION, offset=(20, 20)):
                    click_timer.reset()
                    continue

                # End
                if self.appear(COMMISSION_CHECK, offset=(20, 20)):
                    # Leaving at page_commission
                    # Commission rewards may appear too slow, causing stuck in UI switching
                    break

        return reward
Ejemplo n.º 21
0
    def _data_key_collect_confirm(self, skip_first_screenshot=True):
        """
        Wait for results: get_items or cancel popup.

        Pages:
            in: page_archives
            out: page_archives
        """
        confirm_timer = Timer(1.5, count=3).start()
        while 1:
            if skip_first_screenshot:
                skip_first_screenshot = False
            else:
                self.device.screenshot()

            if self.appear_then_click(GET_ITEMS_1, genre='get_items',
                                      offset=5):
                confirm_timer.reset()
                continue
            if self.handle_popup_confirm('DATA_KEY_LIMIT'):
                # If it's in 29/30 means user is not doing war achieves frequently,
                # no need to bother losing one key, just make it full filled.
                confirm_timer.reset()
                continue

            # End
            if self.appear(WAR_ARCHIVES_CHECK, offset=(20, 20)):
                if confirm_timer.reached():
                    return True
            else:
                confirm_timer.reset()
Ejemplo n.º 22
0
    def _data_key_collect_confirm(self, skip_first_screenshot=True):
        """
        Wait for results: get_items or cancel popup.

        Pages:
            in: page_archives
            out: page_archives
        """
        confirm_timer = Timer(1.5, count=3).start()
        while 1:
            if skip_first_screenshot:
                skip_first_screenshot = False
            else:
                self.device.screenshot()

            if self.appear(GET_ITEMS_1, offset=5, interval=3):
                # Clicking any blank area in page_archives will exit to page_campaign.
                # Click WAR_ARCHIVES_EX to avoid this, if double clicking GET_ITEMS.
                self.device.click(WAR_ARCHIVES_EX_ON)
                confirm_timer.reset()
                continue
            if self.handle_popup_confirm('DATA_KEY_LIMIT'):
                # If it's in 29/30 means user is not doing war achieves frequently,
                # no need to bother losing one key, just make it full filled.
                confirm_timer.reset()
                continue

            # End
            if self.appear(WAR_ARCHIVES_CHECK, offset=(20, 20)):
                if confirm_timer.reached():
                    return True
            else:
                confirm_timer.reset()
Ejemplo n.º 23
0
    def ui_click(
            self,
            click_button,
            check_button,
            appear_button=None,
            additional=None,
            confirm_wait=1,
            offset=(30, 30),
            retry_wait=10,
            skip_first_screenshot=False,
    ):
        """
        Args:
            click_button (Button):
            check_button (Button, callable):
            appear_button (Button, callable):
            additional (callable):
            confirm_wait (int, float):
            offset (bool, int, tuple):
            retry_wait (int, float):
            skip_first_screenshot (bool):
        """
        logger.hr("UI click")
        if appear_button is None:
            appear_button = click_button

        click_timer = Timer(retry_wait, count=retry_wait // 0.5)
        confirm_wait = confirm_wait if additional is not None else 0
        confirm_timer = Timer(confirm_wait, count=confirm_wait // 0.5).start()
        while 1:
            if skip_first_screenshot:
                skip_first_screenshot = False
            else:
                self.device.screenshot()

            if (isinstance(check_button, Button) and self.appear(
                    check_button, offset=offset)) or (callable(check_button)
                                                      and check_button()):
                if confirm_timer.reached():
                    break
            else:
                confirm_timer.reset()

            if click_timer.reached():
                if (isinstance(appear_button, Button)
                        and self.appear(appear_button, offset=offset)) or (
                            callable(appear_button) and appear_button()):
                    self.device.click(click_button)
                    click_timer.reset()
                    continue

            if additional is not None:
                if additional():
                    continue
Ejemplo n.º 24
0
    def port_mission_accept(self):
        """
        Accept all missions in port.

        Deprecated since 2022.01.13, missions are shown only in overview, no longer to be shown at ports.

        Returns:
            bool: True if all missions accepted or no mission found.
                  False if unable to accept more missions.

        Pages:
            in: PORT_CHECK
            out: PORT_CHECK
        """
        if not self.appear(PORT_MISSION_RED_DOT):
            logger.info('No available missions in this port')
            return True

        self.ui_click(PORT_GOTO_MISSION,
                      appear_button=PORT_CHECK,
                      check_button=PORT_MISSION_CHECK,
                      skip_first_screenshot=True)

        confirm_timer = Timer(1.5, count=3).start()
        skip_first_screenshot = True
        success = True
        while 1:
            if skip_first_screenshot:
                skip_first_screenshot = False
            else:
                self.device.screenshot()

            if self.appear_then_click(PORT_MISSION_ACCEPT,
                                      offset=(20, 20),
                                      interval=0.2):
                confirm_timer.reset()
                continue
            else:
                # End
                if confirm_timer.reached():
                    success = True
                    break

            if self.info_bar_count():
                logger.info(
                    'Unable to accept missions, because reached the maximum number of missions'
                )
                success = False
                break

        self.ui_back(appear_button=PORT_MISSION_CHECK,
                     check_button=PORT_CHECK,
                     skip_first_screenshot=True)
        return success
Ejemplo n.º 25
0
    def ui_click(self,
                 click_button,
                 check_button,
                 appear_button=None,
                 additional_button=None,
                 offset=(20, 20),
                 retry_wait=10,
                 additional_button_interval=3,
                 skip_first_screenshot=False):
        """
        Args:
            click_button (Button):
            check_button (Button, callable):
            appear_button (Button):
            additional_button (Button, list[Button], callable):
            additional_button_interval (int, float):
            offset (bool, int, tuple):
            retry_wait (int, float):
            skip_first_screenshot (bool):
        """
        logger.hr('UI click')
        if appear_button is None:
            appear_button = click_button
        if not isinstance(additional_button, list):
            additional_button = [additional_button]
        click_timer = Timer(retry_wait, count=retry_wait // 0.5)
        while 1:
            if skip_first_screenshot:
                skip_first_screenshot = False
            else:
                self.device.screenshot()

            if isinstance(check_button, Button) and self.appear(check_button,
                                                                offset=offset):
                break
            if callable(check_button) and check_button():
                break

            for button in additional_button:
                if button is None:
                    continue
                if isinstance(button, Button):
                    self.appear_then_click(button,
                                           offset=offset,
                                           interval=additional_button_interval)
                    continue
                if callable(button) and button():
                    continue

            if click_timer.reached() and self.appear(appear_button,
                                                     offset=offset):
                self.device.click(click_button)
                click_timer.reset()
                continue
Ejemplo n.º 26
0
    def _active_edit(self):
        timer = Timer(1)
        while 1:
            self.device.screenshot()

            if timer.reached() and self.appear_then_click(EQUIP_EDIT_INACTIVE):
                timer.reset()

            # End
            if self.appear(EQUIP_EDIT_ACTIVE):
                self.device.sleep((0.2, 0.3))
                break
Ejemplo n.º 27
0
    def _set_2x_book_status(self, status, check_button, box_button, skip_first_screenshot=True):
        """
        Set appropriate 2x book setting
        with corresponding status and buttons
        Built with retry mechanism that limits to 3
        attempts that span 3 second intervals each

        Args:
            status (string):
                on or off
            check_button (Button):
                button to check before attempting to click
            box_button (Button):
                button to click and image color count against
            skip_first_screenshot (bool):
                namesake

        Returns:
            bool:
                True if detected having set correctly
                False can occur for 2 reasons either
                assets insufficient to detect properly
                or 2x book setting is absent

        """
        confirm_timer = Timer(1).start()
        clicked_threshold = 0
        while 1:
            if skip_first_screenshot:
                skip_first_screenshot = False
            else:
                self.device.screenshot()

            if clicked_threshold > 3:
                break

            if self.appear(check_button, offset=self._auto_search_menu_offset, interval=3):
                box_button.load_offset(check_button)
                enabled = self.image_color_count(box_button.button, color=(156, 255, 82), threshold=221, count=20)
                if (status == 'on' and enabled) or (status == 'off' and not enabled):
                    return True
                if (status == 'on' and not enabled) or (status == 'off' and enabled):
                    self.device.click(box_button)

                clicked_threshold += 1

            if not clicked_threshold and confirm_timer.reached():
                logger.info('Map do not have 2x book setting')
                return False

        logger.warning(f'Wait time has expired; Cannot set 2x book setting')
        return False
Ejemplo n.º 28
0
    def ensure_no_zone_pinned(self, skip_first_screenshot=True):
        confirm_timer = Timer(1, count=2).start()
        while 1:
            if skip_first_screenshot:
                skip_first_screenshot = False
            else:
                self.device.screenshot()

            if self.handle_zone_pinned():
                confirm_timer.reset()
            else:
                if confirm_timer.reached():
                    break
Ejemplo n.º 29
0
    def _equip_enter(self, enter):
        enter_timer = Timer(5)

        while 1:
            if enter_timer.reached():
                self.device.long_click(enter, duration=(1.5, 1.7))
                enter_timer.reset()

            self.device.screenshot()

            # End
            if self.appear(EQUIPMENT_OPEN):
                break
Ejemplo n.º 30
0
    def hermit_enable_accessibility(self):
        """
        Turn on accessibility service for Hermit.

        Raises:
            RequestHumanTakeover: If failed and user should do it manually.
        """
        logger.hr('Enable accessibility service')
        interval = Timer(0.3)
        timeout = Timer(10, count=10).start()
        while 1:
            h = self.dump_hierarchy_adb()
            interval.wait()
            interval.reset()

            def appear(xpath):
                return bool(HierarchyButton(h, xpath))

            def appear_then_click(xpath):
                b = HierarchyButton(h, xpath)
                if b:
                    point = random_rectangle_point(b.button)
                    logger.info(f'Click {point2str(*point)} @ {b}')
                    self.click_adb(*point)
                    return True
                else:
                    return False

            if appear_then_click(
                    '//*[@text="Hermit" and @resource-id="android:id/title"]'):
                continue
            if appear_then_click(
                    '//*[@class="android.widget.Switch" and @checked="false"]'
            ):
                continue
            if appear_then_click('//*[@resource-id="android:id/button1"]'):
                # Just plain click here
                # Can't use uiautomator once hermit has access to accessibility service,
                # or uiautomator will get the access.
                break
            if appear(
                    '//*[@class="android.widget.Switch" and @checked="true"]'):
                raise HermitError(
                    'Accessibility service already enable but get error')

            # End
            if timeout.reached():
                logger.critical(
                    'Unable to turn on accessibility service for Hermit')
                logger.critical(
                    '\n\n'
                    'Please do this manually:\n'
                    '1. Find "Hermit" in accessibility setting and click it\n'
                    '2. Turn it ON and click OK\n'
                    '3. Switch back to AzurLane\n')
                raise RequestHumanTakeover