예제 #1
0
    def predict_enemy_scale(self):
        """
        icon on the upperleft which shows enemy scale: Large Middle Small.

        Returns:
            int: 1: Small, 2: Middle, 3: Large.
        """
        # if not self.is_enemy:
        #     return 0

        image = self.get_relative_image((-0.415 - 0.7, -0.62 - 0.7, -0.415, -0.62))
        image = np.stack(
            [
                color_similarity_2d(image, (255, 130, 132)),
                color_similarity_2d(image, (255, 239, 148)),
                color_similarity_2d(image, (255, 235, 156))
            ], axis=2
        )
        image = Image.fromarray(image).resize(self.ENEMY_SCALE_IMAGE_SIZE)

        if TEMPLATE_ENEMY_L.match(image):
            scale = 3
        elif TEMPLATE_ENEMY_M.match(image):
            scale = 2
        elif TEMPLATE_ENEMY_S.match(image):
            scale = 1
        else:
            scale = 0

        return scale
예제 #2
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 predict_enemy_genre(self):
        image = self.relative_crop((-0.55, -0.2, 0.45, 0.2), shape=(50, 20))
        image = color_similarity_2d(image, color=(255, 150, 24))
        if TEMPLATE_ENEMY_BOSS.match(image, similarity=0.75):
            return 'Siren_Siren'

        return super().predict_enemy_genre()
예제 #4
0
    def _equip_sidebar_click(self, index):
        """
        Args:
            index (int):
                5 for retrofit.
                4 for enhancement.
                3 for limit break.
                2 for gem / equipment.
                1 for detail.

        Returns:
            bool: if changed.
        """
        if index <= 0 or index > 5:
            logger.warning(
                f'Sidebar index cannot be clicked, {index}, limit to 1 through 5 only'
            )
            return False

        current = 0
        total = 0

        for idx, button in enumerate(DETAIL_SIDEBAR.buttons()):
            image = np.array(self.device.image.crop(button.area))
            if np.sum(image[:, :, 0] > 235) > 100:
                current = idx + 1
                total = idx + 1
                continue
            if np.sum(color_similarity_2d(image, color=(140, 162,
                                                        181)) > 221) > 100:
                total = idx + 1
            else:
                break
        if not current:
            logger.warning('No ship details sidebar active.')
        if total == 3:
            current = 4 - current
        elif total == 4:
            current = 5 - current
        elif total == 5:
            current = 6 - current
        else:
            logger.warning('Ship details sidebar total count error.')

        logger.attr('Detail_sidebar', f'{current}/{total}')
        if current == index:
            return False

        diff = total - index
        if total == 3 and index == 3:
            logger.warning('Ship is PRY, equipment research not supported')
        elif diff >= 0:
            self.device.click(DETAIL_SIDEBAR[0, diff])
        else:
            logger.warning(
                f'Target index {index} cannot be clicked for this ship')
        return True
예제 #5
0
 def predict_fleet(self):
     # white ammo icon
     # return self._relative_image_color_count(
     #     area=(-1, -2, -0.5, -1.5), color=(255, 255, 255), color_threshold=252) > 300
     # count = self._relative_image_color_hue_count(area=(-1, -2, -0.5, -1.5), h=(0, 360), s=(0, 5), v=(95, 100))
     # return count > 300
     image = self.get_relative_image((-1, -2, -0.5, -1.5), output_shape=self.ENEMY_SCALE_IMAGE_SIZE)
     image = color_similarity_2d(image, (255, 255, 255))
     return TEMPLATE_FLEET_AMMO.match(image)
예제 #6
0
 def _relative_image_color_count(self,
                                 area,
                                 color,
                                 output_shape=(50, 50),
                                 color_threshold=221):
     image = self.get_relative_image(area, output_shape=output_shape)
     image = color_similarity_2d(image, color=color)
     count = np.sum(image > color_threshold)
     return count
예제 #7
0
    def predict_static_red_border(self):
        # image = self.image.transform(self.ENEMY_PERSPECTIVE_IMAGE_SIZE, Image.PERSPECTIVE, self._perspective)

        image = color_similarity_2d(
            self.image_transform.crop((0, self.RED_BORDER_IGNORE_TOP, *self.ENEMY_PERSPECTIVE_IMAGE_SIZE)),
            color=(255, 36, 82))

        # Image.fromarray(np.array(image).astype('uint8'), mode='RGB').save(f'{self}.png')

        count = np.sum(image > 221)
        return count > 40
    def predict_boss(self):
        # Small boss icon
        if self.relative_hsv_count(area=(0.03, -0.15, 0.63, 0.15),
                                   h=(358 - 3, 358 + 3),
                                   shape=(50, 20)) > 100:
            image = self.relative_crop((0.03, -0.15, 0.63, 0.15),
                                       shape=(50, 20))
            image = color_similarity_2d(image, color=(255, 77, 82))
            if TEMPLATE_ENEMY_BOSS.match(image, similarity=0.7):
                return True

        return False
예제 #9
0
    def match_color(self, main):
        """
        Args:
            main (ModuleBase):

        Returns:
            np.ndarray: Shape (n,), dtype bool.
        """
        image = main.image_crop(self.area)
        image = color_similarity_2d(image, color=self.color)
        mask = np.max(image, axis=1 if self.is_vertical else 0) > self.color_threshold
        self.length = np.sum(mask)
        return mask
예제 #10
0
    def handle_map_cat_attack(self):
        """
        Click to skip the animation when cat attacks.
        """
        if not self.map_cat_attack_timer.reached():
            return False
        if np.sum(color_similarity_2d(self.image_area(MAP_CAT_ATTACK), (255, 231, 123)) > 221) > 100:
            logger.info('Skip map cat attack')
            self.device.click(MAP_CAT_ATTACK)
            self.map_cat_attack_timer.reset()
            return True

        return False
예제 #11
0
    def handle_map_cat_attack(self):
        """
        Click to skip the animation when cat attacks.

        Overridden as button position matches with
        MAP_EXIT for OpSi
        """
        if not self.map_cat_attack_timer.reached():
            return False
        if np.sum(color_similarity_2d(self.image_crop(MAP_CAT_ATTACK), (255, 231, 123)) > 221) > 100:
            logger.info('Skip map cat attack')
            self.device.click(CLICK_SAFE_AREA)
            self.map_cat_attack_timer.reset()
            return True

        return False
예제 #12
0
 def guild_lobby_get_report(self):
     """
     Returns:
         Button: Button to enter guild report.
     """
     # Find red color in the area of GUILD_REPORT_AVAILABLE
     image = color_similarity_2d(self.image_crop(GUILD_REPORT_AVAILABLE), color=(255, 8, 8))
     points = np.array(np.where(image > 221)).T[:, ::-1]
     if len(points):
         # The center of red dot
         points = Points(points).group(threshold=40) + GUILD_REPORT_AVAILABLE.area[:2]
         # Shift to the center of report icon
         area = area_offset((-51, -45, -13, 0), offset=points[0])
         return Button(area=area, color=(255, 255, 255), button=area, name='GUILD_REPORT')
     else:
         return None
예제 #13
0
    def get_map_is_hard_mode(self):
        """
        Detect how many light orange lines are there.
        Having lines means current map has stat limits and user has satisfied at least one of them,
        so this is a hard map.

        Returns:
            bool:
        """
        area = (208, 130, 226, 551)
        image = color_similarity_2d(self.image_area(area), color=(249, 199, 0))
        height = np.max(image, axis=1)
        parameters = {'height': 180, 'distance': 5}
        peaks, _ = signal.find_peaks(height, **parameters)
        lines = len(peaks)
        logger.attr('Light_orange_line', lines)
        return lines > 0
예제 #14
0
    def _equip_sidebar_click(self, index):
        """
        Args:
            index (int):
                5 for retrofit.
                4 for enhancement.
                3 for limit break.
                2 for gem / equipment.
                1 for detail.

        Returns:
            bool: if changed.
        """
        current = 0
        total = 0

        for idx, button in enumerate(DETAIL_SIDEBAR.buttons()):
            image = np.array(self.device.image.crop(button.area))
            if np.sum(image[:, :, 0] > 235) > 100:
                current = idx + 1
                total = idx + 1
                continue
            if np.sum(color_similarity_2d(image, color=(140, 162,
                                                        181)) > 221) > 100:
                total = idx + 1
            else:
                break
        if not current:
            logger.warning('No ship details sidebar active.')
        if total == 4:
            current = 5 - current
        elif total == 5:
            current = 6 - current
        else:
            logger.warning('Ship details sidebar total count error.')

        logger.attr('Detail_sidebar', f'{current}/{total}')
        if current == index:
            return False

        self.device.click(DETAIL_SIDEBAR[0, total - index])
        return True
예제 #15
0
    def handle_user_agreement(self, xp, hierarchy):
        """
        For CN only.
        CN client is bugged. User Agreement and Privacy Policy may popup again even you have agreed with it.
        This method scrolls to the bottom and click AGREE.

        Returns:
            bool: If handled.
        """

        if server.server == 'cn':
            area_wait_results = self.get_for_any_ele([
                XPS('//*[@text="sdk协议"]', xp, hierarchy),
                XPS('//*[@content-desc="sdk协议"]', xp, hierarchy)
            ])
            if area_wait_results is False:
                return False
            agree_wait_results = self.get_for_any_ele([
                XPS('//*[@text="同意"]', xp, hierarchy),
                XPS('//*[@content-desc="同意"]', xp, hierarchy)
            ])
            start_padding_results = self.get_for_any_ele([
                XPS('//*[@text="隐私政策"]', xp, hierarchy),
                XPS('//*[@content-desc="隐私政策"]', xp, hierarchy),
                XPS('//*[@text="用户协议"]', xp, hierarchy),
                XPS('//*[@content-desc="用户协议"]', xp, hierarchy)
            ])
            start_margin_results = self.get_for_any_ele([
                XPS('//*[@text="请滑动阅读协议内容"]', xp, hierarchy),
                XPS('//*[@content-desc="请滑动阅读协议内容"]', xp, hierarchy)
            ])

            test_image_original = self.device.image
            image_handle_crop = crop(
                test_image_original,
                (start_padding_results[2], 0, start_margin_results[2], 720))
            # Image.fromarray(image_handle_crop).show()
            sims = color_similarity_2d(image_handle_crop,
                                       color=(182, 189, 202))
            points = np.sum(sims >= 255)
            if points == 0:
                return False
            sims_height = np.mean(sims, axis=1)
            # pyplot.plot(sims_height, color='r')
            # pyplot.show()
            peaks, __ = find_peaks(sims_height, height=225)
            if len(peaks) == 2:
                peaks = (peaks[0] + peaks[1]) / 2
            start_pos = [
                (start_padding_results[2] + start_margin_results[2]) / 2,
                float(peaks)
            ]
            end_pos = [
                (start_padding_results[2] + start_margin_results[2]) / 2,
                area_wait_results[3]
            ]
            logger.info("user agreement position find result: " +
                        ', '.join('%.2f' % _ for _ in start_pos))
            logger.info("user agreement area expect:          " +
                        'x:963-973, y:259-279')

            self.device.drag(start_pos,
                             end_pos,
                             segments=2,
                             shake=(0, 25),
                             point_random=(0, 0, 0, 0),
                             shake_random=(0, -5, 0, 5))
            AGREE = Button(area=agree_wait_results,
                           color=(),
                           button=agree_wait_results,
                           name='AGREE')
            self.device.click(AGREE)
            return True