예제 #1
0
    def __init__(self, image, button):
        """
        Args:
            image (PIL.Image.Image):
            button (Button):
        """
        image = image.crop(button.area)
        self.button = button

        self.genre = 0
        color = get_color(image, (65, 35, 72, 42))
        for key, value in self.color_genre.items():
            if color_similar(color1=color, color2=value, threshold=30):
                self.genre = key

        self.tier = 0
        color = get_color(image, (83, 61, 92, 70))
        for key, value in self.color_tier.items():
            if color_similar(color1=color, color2=value, threshold=30):
                self.tier = key

        color = color_similarity_2d(image.crop((15, 0, 97, 13)), color=(148, 251, 99))
        self.exp = bool(np.sum(color > 221) > 50)

        self.valid = bool(self.genre and self.tier)
    def enemy_searching_appear(self):
        if not self.is_in_map():
            return False

        return red_overlay_transparency(
            MAP_ENEMY_SEARCHING.color, get_color(self.device.image, MAP_ENEMY_SEARCHING.area)
        ) > self.MAP_ENEMY_SEARCHING_OVERLAY_TRANSPARENCY_THRESHOLD
예제 #3
0
    def commission_parse(self):
        # Name
        # This is different from CN, EN has longer names
        area = area_offset((176, 23, 420, 51), self.area[0:2])
        button = Button(area=area, color=(), button=area, name='COMMISSION')
        ocr = Ocr(button, lang='cnocr', back=(74, 97, 148), use_binary=False)
        self.button = button
        self.name = ocr.ocr(self.image)
        self.genre = self.commission_name_parse(self.name)

        # Duration time
        area = area_offset((290, 74, 390, 92), self.area[0:2])
        button = Button(area=area, color=(), button=area, name='DURATION')
        ocr = Ocr(button, lang='stage', back=(57, 85, 132))
        self.duration = self.parse_time(ocr.ocr(self.image))

        # Expire time
        area = area_offset((-49, 68, -45, 84), self.area[0:2])
        button = Button(area=area,
                        color=(189, 65, 66),
                        button=area,
                        name='IS_URGENT')
        if button.appear_on(self.image):
            area = area_offset((-49, 73, 45, 91), self.area[0:2])
            button = Button(area=area, color=(), button=area, name='EXPIRE')
            ocr = Ocr(button, lang='stage', back=(189, 65, 66))
            self.expire = self.parse_time(ocr.ocr(self.image))
        else:
            self.expire = None

        # Status
        area = area_offset((179, 71, 187, 93), self.area[0:2])
        dic = {0: 'finished', 1: 'running', 2: 'pending'}
        self.status = dic[int(np.argmax(get_color(self.image, area)))]
예제 #4
0
 def check_screen_black(self):
     if self._screen_black_checked:
         return True
     # Check screen color
     # May get a pure black screenshot on some emulators.
     color = get_color(self.image, area=(0, 0, 1280, 720))
     if sum(color) < 1:
         if self.config.Emulator_ScreenshotMethod == 'uiautomator2':
             logger.warning(
                 f'Received pure black screenshots from emulator, color: {color}'
             )
             logger.warning('Uninstall minicap and retry')
             self.uninstall_minicap()
             self._screen_black_checked = False
             return False
         else:
             logger.critical(
                 f'Received pure black screenshots from emulator, color: {color}'
             )
             logger.critical(
                 f'Screenshot method `{self.config.Emulator_ScreenshotMethod}` '
                 f'may not work on emulator `{self.serial}`')
             logger.critical('Please use other screenshot methods')
             raise RequestHumanTakeover
     else:
         self._screen_black_checked = True
         return True
예제 #5
0
    def check_screen(self):
        """
        Screen size must be 1280x720.
        Take a screenshot before call.
        """
        # Check screen size
        width, height = self.image.size
        logger.attr('Screen_size', f'{width}x{height}')
        if not (width == 1280 and height == 720):
            logger.critical(f'Resolution not supported: {width}x{height}')
            logger.critical('Please set emulator resolution to 1280x720')
            raise RequestHumanTakeover

        # Check screen color
        # May get a pure black screenshot on some emulators.
        color = get_color(self.image, area=(0, 0, 1280, 720))
        if sum(color) < 1:
            logger.critical(
                f'Received pure black screenshots from emulator, color: {color}'
            )
            logger.critical(
                f'Screenshot method `{self.config.Emulator_ScreenshotMethod}` '
                f'may not work on emulator `{self.serial}`')
            logger.critical('Please use other screenshot methods')
            raise RequestHumanTakeover
예제 #6
0
    def commission_parse(self):
        # Name
        area = area_offset((176, 23, 420, 53), self.area[0:2])
        button = Button(area=area, color=(), button=area, name='COMMISSION')
        ocr = Ocr(button, lang='cnocr', threshold=256)
        self.button = button
        self.name = ocr.ocr(self.image)
        self.genre = self.commission_name_parse(self.name)

        # Duration time
        area = area_offset((290, 68, 390, 95), self.area[0:2])
        button = Button(area=area, color=(), button=area, name='DURATION')
        ocr = Ocr(button, alphabet='0123456789:')
        self.duration = self.parse_time(ocr.ocr(self.image))

        # Expire time
        area = area_offset((-49, 68, -45, 84), self.area[0:2])
        button = Button(area=area,
                        color=(189, 65, 66),
                        button=area,
                        name='IS_URGENT')
        if button.appear_on(self.image):
            area = area_offset((-49, 67, 45, 94), self.area[0:2])
            button = Button(area=area, color=(), button=area, name='EXPIRE')
            ocr = Ocr(button, alphabet='0123456789:')
            self.expire = self.parse_time(ocr.ocr(self.image))
        else:
            self.expire = None

        # Status
        area = area_offset((179, 71, 187, 93), self.area[0:2])
        dic = {0: 'finished', 1: 'running', 2: 'pending'}
        self.status = dic[int(np.argmax(get_color(self.image, area)))]
예제 #7
0
    def check_screen(self):
        """
        Screen size must be 1280x720.
        Take a screenshot before call.
        """
        # Check screen size
        width, height = self.image.size
        if height > width:
            width, height = height, width
        logger.attr('Screen_size', f'{width}x{height}')
        if width == 1280 and height == 720:
            return True
        else:
            logger.warning(f'Not supported screen size: {width}x{height}')
            logger.warning('Alas requires 1280x720')
            logger.hr('Script end')
            exit(1)

        # Check screen color
        # May get a pure black screenshot on some emulators.
        color = get_color(self.image, area=(0, 0, 1280, 720))
        if sum(color) < 1:
            logger.warning('Received a pure black screenshot')
            logger.warning(f'Color: {color}')
            exit(1)
예제 #8
0
 def _extract(image, file):
     size = image_size(image)
     if size != (1280, 720):
         logger.warning(f'{file} has wrong resolution: {size}')
     bbox = get_bbox(image)
     mean = get_color(image=image, area=bbox)
     mean = tuple(np.rint(mean).astype(int))
     return bbox, mean
예제 #9
0
 def is_active(self):
     color = get_color(image=self.device.image, area=DAILY_ACTIVE.area)
     color = np.array(color).astype(float)
     color = (np.max(color) + np.min(color)) / 2
     active = color > 30
     if active:
         logger.attr(f'Daily_{self.daily_current}', 'active')
     else:
         logger.attr(f'Daily_{self.daily_current}', 'inactive')
     return active
 def campaign_predict_mode(self):
     """
     Returns:
         str: 'normal' or 'hard'
     """
     color = get_color(self.device.image, MODE_CHANGE.area)
     if np.max(color) - np.min(color) < 50:
         logger.warning(f'Unexpected color: {color}')
     index = np.argmax(color)  # R, G, B
     if index == 0:
         return 'normal'  # Red button. (214, 117, 115)
     elif index == 2:
         return 'hard'  # Blue button. (115, 146, 214)
     else:
         logger.warning(f'Unexpected color: {color}')
예제 #11
0
    def _get_archives_entrance(self, name):
        """
        Create entrance button to target archive campaign
        using a template acquired by event folder name

        Args:
            name(str): event folder name
        """
        template = dic_archives_template[name]

        sim, point = template.match_result(self.device.image)
        if sim < 0.85:
            return None

        button = area_offset(area=(-12, -12, 44, 32), offset=point)
        color = get_color(self.device.image, button)
        entrance = Button(area=button, color=color, button=button, name=name)
        return entrance
예제 #12
0
    def _research_has_finished_at(self, button):
        """
        Args:
            button (Button):

        Returns:
            bool: True if a research finished
        """
        color = get_color(self.device.image, button.area)
        if np.max(color) - np.min(color) < 40:
            logger.warning(f'Unexpected color: {color}')
        index = np.argmax(color)  # R, G, B
        if index == 1:
            return True  # Green
        elif index == 2:
            return False  # Blue
        else:
            logger.warning(f'Unexpected color: {color}')
            return False
예제 #13
0
    def _tactical_animation_running(self):
        """
        Returns:
            bool: If showing skill points increasing animation.
        """
        color_height = np.mean(self.device.image.crop((922, 0, 1036, 720)).convert('L'), axis=1)
        parameters = {'height': 200}
        peaks, _ = signal.find_peaks(color_height, **parameters)
        peaks = [y for y in peaks if y > 67 + 243]

        if not len(peaks):
            logger.warning('No student card found.')
        for y in peaks:
            student_area = (447, y - 243, 1244, y)
            area = area_offset((677, 172, 761, 183), student_area[0:2])
            # Normal: 160, In skill-increasing animation: 109
            if np.mean(get_color(self.device.image, area)) < 135:
                return True

        return False
예제 #14
0
    def _get_archives_entrance(self, name):
        """
        Create entrance button to target archive campaign
        using a template acquired by event folder name

        TODO: Each server have different selectable campaign
              Need something similar to commission to scroll
              or turn page. CN/JP have more than 4 atm.

        Args:
            name(str): event folder name
        """
        template = dic_archives_template[name]

        sim, point = template.match_result(self.device.image)
        if sim < 0.85:
            raise CampaignNameError

        button = area_offset(area=(-12, -12, 44, 32), offset=point)
        color = get_color(self.device.image, button)
        entrance = Button(area=button, color=color, button=button, name=name)
        return entrance
예제 #15
0
    def _retirement_choose(self, amount=10, target_rarity=('N', )):
        """
        Args:
            amount (int): Amount of cards retire. 0 to 10.
            target_rarity (tuple(str)): Card rarity. N, R, SR, SSR.

        Returns:
            int: Amount of cards have retired.
        """
        cards = []
        rarity = []
        for x, y, button in CARD_RARITY_GRIDS.generate():
            card_color = get_color(image=self.device.image, area=button.area)
            f = False
            for r, rarity_color in CARD_RARITY_COLORS.items():

                if color_similar(card_color, rarity_color, threshold=15):
                    cards.append([x, y])
                    rarity.append(r)
                    f = True

            if not f:
                logger.warning(
                    f'Unknown rarity color. Grid: ({x}, {y}). Color: {card_color}'
                )

        logger.info(' '.join([r.rjust(3) for r in rarity[:7]]))
        logger.info(' '.join([r.rjust(3) for r in rarity[7:]]))

        selected = 0
        for card, r in zip(cards, rarity):
            if r in target_rarity:
                self.device.click(CARD_GRIDS[card])
                self.device.sleep((0.1, 0.15))
                selected += 1
            if selected >= amount:
                break
        return selected
예제 #16
0
 def check_screen_black(self):
     if self._screen_black_checked:
         return True
     # Check screen color
     # May get a pure black screenshot on some emulators.
     color = get_color(self.image, area=(0, 0, 1280, 720))
     if sum(color) < 1:
         if self.config.Emulator_Serial == 'wsa-0':
             for _ in range(2):
                 display = self.get_display_id()
                 if display == 0:
                     return True
             logger.info(f'Game running on display {display}')
             logger.warning(
                 'Game not running on display 0, will be restarted')
             self.app_stop_uiautomator2(self.config.Emulator_PackageName)
             return False
         elif self.config.Emulator_ScreenshotMethod == 'uiautomator2':
             logger.warning(
                 f'Received pure black screenshots from emulator, color: {color}'
             )
             logger.warning('Uninstall minicap and retry')
             self.uninstall_minicap()
             self._screen_black_checked = False
             return False
         else:
             logger.critical(
                 f'Received pure black screenshots from emulator, color: {color}'
             )
             logger.critical(
                 f'Screenshot method `{self.config.Emulator_ScreenshotMethod}` '
                 f'may not work on emulator `{self.serial}`')
             logger.critical('Please use other screenshot methods')
             raise RequestHumanTakeover
     else:
         self._screen_black_checked = True
         return True
예제 #17
0
    def battle_pass_red_dot_appear(self):
        """
        Returns:
            bool: If appear.

        Page:
            in: page_reward
        """
        if self.appear(REWARD_GOTO_BATTLE_PASS, offset=(10, 150)):
            # Load button offset from REWARD_GOTO_BATTLE_PASS,
            # because entrance may not be the top one.
            BATTLE_PASS_RED_DOT.load_offset(REWARD_GOTO_BATTLE_PASS)
            # Not using self.appear() here, because it's transparent,
            # color may be different depending on background.
            r, _, _ = get_color(self.device.image, BATTLE_PASS_RED_DOT.area)
            if r > BATTLE_PASS_RED_DOT.color[0] - 40:
                logger.info('Found battle pass red dot')
                return True
            else:
                logger.info('No battle pass red dot')
                return False
        else:
            logger.warning('No battle pass entrance')
            return False
예제 #18
0
 def extract(file):
     image = load_image(file)
     bbox = get_bbox(image)
     mean = get_color(image=image, area=bbox)
     mean = tuple(np.rint(mean).astype(int))
     return bbox, mean
예제 #19
0
 def _ambush_appear(self):
     return red_overlay_transparency(MAP_AMBUSH.color, get_color(self.device.image, MAP_AMBUSH.area)) > \
            self.MAP_AMBUSH_OVERLAY_TRANSPARENCY_THRESHOLD
예제 #20
0
 def _air_raid_appear(self):
     return red_overlay_transparency(MAP_AIR_RAID.color, get_color(self.device.image, MAP_AIR_RAID.area)) > \
            self.MAP_AIR_RAID_OVERLAY_TRANSPARENCY_THRESHOLD