From 1ec5d66be28c75e635f8395dea40b6d2693168b5 Mon Sep 17 00:00:00 2001 From: noname94 Date: Tue, 20 Oct 2020 16:28:04 +0900 Subject: [PATCH 1/3] Opt: level detection minor optimizations --- module/combat/level.py | 25 +++++++++++-------------- 1 file changed, 11 insertions(+), 14 deletions(-) diff --git a/module/combat/level.py b/module/combat/level.py index 24714e6b0..974a5e91a 100644 --- a/module/combat/level.py +++ b/module/combat/level.py @@ -2,7 +2,7 @@ from module.base.base import ModuleBase from module.base.button import * from module.base.decorator import Config from module.logger import logger -from module.ocr.ocr import Ocr +from module.ocr.ocr import Digit LV_GRID_MAIN = ButtonGrid(origin=(58, 118), delta=(0, 100), button_shape=(46, 19), grid_shape=(1, 3)) LV_GRID_VANGUARD = ButtonGrid(origin=(58, 420), delta=(0, 100), button_shape=(46, 19), grid_shape=(1, 3)) @@ -72,13 +72,7 @@ class Level(ModuleBase): return False -class LevelOcr(Ocr): - # Ocr's default argument 'threshold=128' makes some digits too thin to be recognized. - # Use 'threshold=191' instead. - def __init__(self, buttons, lang='azur_lane', letter=COLOR_WHITE, threshold=191, alphabet='0123456789', - name='LevelOcr'): - super().__init__(buttons, lang=lang, letter=letter, threshold=threshold, alphabet=alphabet, name=name) - +class LevelOcr(Digit): def pre_process(self, image): # Check the max value of red channel to find out whether the image is masked. # It would be no larger than COLOR_MASKED[0]=107 iff masked. @@ -90,7 +84,15 @@ class LevelOcr(Ocr): scalar = np.mean(COLOR_WHITE) / np.mean(COLOR_MASKED) image = cv2.addWeighted(image, scalar, image, 0, 0) - image = super().pre_process(image) + # Deal with the blue background of chars before converting to greyscale. + # The background is semi-transparent. It turns (0, 0, 0) to (33, 65, 115), and (255, 255, 255) + # to (107, 138, 189). We use the middle point (70, 102, 152). + bg = (70, 102, 152) + # BT.601 + luma_trans = (0.299, 0.587, 0.114) + luma_bg = np.dot(bg, luma_trans) + image = cv2.subtract(image, (*bg, 0)).dot(luma_trans).round().astype(np.uint8) + image = cv2.subtract(255, cv2.multiply(image, 255 / (255 - luma_bg))) # Find 'L' to strip 'LV.'. # Ruturn an empty image if 'L' is not found. letter_l = np.nonzero(image[2:15, :].max(axis=0) < 127)[0] @@ -98,8 +100,3 @@ class LevelOcr(Ocr): return image[:, letter_l[0] + 17:] else: return np.array([[255]], dtype=np.uint8) - - def after_process(self, result): - result = super().after_process(result) - - return int(result) if result else -1 From 90d1b09bceca448c2db960852c691f14f2108158 Mon Sep 17 00:00:00 2001 From: noname94 Date: Tue, 20 Oct 2020 16:58:21 +0900 Subject: [PATCH 2/3] Fix: pre_process of LevelOcr may return NoneType --- module/combat/level.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/module/combat/level.py b/module/combat/level.py index 974a5e91a..f12a71320 100644 --- a/module/combat/level.py +++ b/module/combat/level.py @@ -97,6 +97,7 @@ class LevelOcr(Digit): # Ruturn an empty image if 'L' is not found. letter_l = np.nonzero(image[2:15, :].max(axis=0) < 127)[0] if len(letter_l): - return image[:, letter_l[0] + 17:] - else: - return np.array([[255]], dtype=np.uint8) + first_digit = letter_l[0] + 17 + if first_digit + 3 < LV_GRID_MAIN.button_shape[0]: + return image[:, first_digit:] + return np.array([[255]], dtype=np.uint8) From 0ad206c69b415ab19555fed8cf50447e75336955 Mon Sep 17 00:00:00 2001 From: LmeSzinc <37934724+LmeSzinc@users.noreply.github.com> Date: Wed, 21 Oct 2020 20:00:52 +0800 Subject: [PATCH 3/3] Fix: Avoid clicking MEOWFFICER_BUY multiple times --- module/reward/meowfficer.py | 37 +++++++++++++++++++++++-------------- 1 file changed, 23 insertions(+), 14 deletions(-) diff --git a/module/reward/meowfficer.py b/module/reward/meowfficer.py index e8c311ea9..3f20938c1 100644 --- a/module/reward/meowfficer.py +++ b/module/reward/meowfficer.py @@ -1,3 +1,4 @@ +from module.base.timer import Timer from module.combat.assets import GET_ITEMS_1 from module.logger import logger from module.ocr.ocr import Digit, DigitCounter @@ -48,33 +49,34 @@ class RewardMeowfficer(UI): next_button=MEOWFFICER_BUY_NEXT, skip_first_screenshot=True) return True - def meow_confirm(self, skip_first_screenshot=True): + def meow_confirm(self): """ Pages: in: MEOWFFICER_BUY out: page_meowfficer """ - executed = False - while 1: - if skip_first_screenshot: - skip_first_screenshot = False - else: - self.device.screenshot() + # Here uses a simple click, to avoid clicking MEOWFFICER_BUY multiple times. + # Retry logic is in meow_buy() + self.device.click(MEOWFFICER_BUY) + + confirm_timer = Timer(1, count=2).start() + while 1: + self.device.screenshot() - if self.appear_then_click(MEOWFFICER_BUY, interval=5): - continue if self.appear_then_click(MEOWFFICER_BUY_CONFIRM, interval=5): continue if self.appear_then_click(MEOWFFICER_BUY_SKIP, interval=5): continue if self.appear(GET_ITEMS_1): self.device.click(MEOWFFICER_BUY_SKIP) - executed = True continue # End - if executed and self.appear(MEOWFFICER_BUY): - break + if self.appear(MEOWFFICER_BUY): + if confirm_timer.reached(): + break + else: + confirm_timer.reset() self.ui_click(MEOWFFICER_GOTO_DORM, check_button=MEOWFFICER_BUY_ENTER, appear_button=MEOWFFICER_BUY, offset=None) @@ -85,9 +87,16 @@ class RewardMeowfficer(UI): out: page_main """ self.ui_ensure(page_meowfficer) - if self.meow_choose(count=self.config.BUY_MEOWFFICER): - self.meow_confirm() + for _ in range(3): + if self.meow_choose(count=self.config.BUY_MEOWFFICER): + self.meow_confirm() + else: + self.ui_goto_main() + return True + + logger.warning('Too many trial in meowfficer buy, stopped.') self.ui_goto_main() + return False def handle_meowfficer(self): """