def ash_collect_status(self): """ Returns: int: 0 to 100. """ if self._ash_fully_collected: return 0 if self.image_color_count(ASH_COLLECT_STATUS, color=(235, 235, 235), threshold=221, count=20): logger.info('Ash beacon status: light') ocr_collect = DigitCounter(ASH_COLLECT_STATUS, letter=(235, 235, 235), threshold=160, name='OCR_ASH_COLLECT_STATUS') ocr_daily = DailyDigitCounter(ASH_DAILY_STATUS, letter=(235, 235, 235), threshold=160, name='OCR_ASH_DAILY_STATUS') elif self.image_color_count(ASH_COLLECT_STATUS, color=(140, 142, 140), threshold=221, count=20): logger.info('Ash beacon status: gray') ocr_collect = DigitCounter(ASH_COLLECT_STATUS, letter=(140, 142, 140), threshold=160, name='OCR_ASH_COLLECT_STATUS') ocr_daily = DailyDigitCounter(ASH_DAILY_STATUS, letter=(140, 142, 140), threshold=160, name='OCR_ASH_DAILY_STATUS') else: # If OS daily mission received or finished, the popup will cover beacon status. logger.info('Ash beacon status is covered, will check next time') return 0 status, _, _ = ocr_collect.ocr(self.device.image) daily, _, _ = ocr_daily.ocr(self.device.image) if daily >= 200: logger.info('Ash beacon fully collected today') self._ash_fully_collected = True if status < 0: status = 0 return status
def raid_ocr(raid, mode): """ Args: raid (str): Raid name, such as raid_20200624, raid_20210708. mode (str): easy, normal, hard Returns: DigitCounter: """ raid = raid_name_shorten(raid) key = f'{raid}_OCR_REMAIN_{mode.upper()}' try: button = globals()[key] # Old raids use RaidCounter to compatible with old OCR model and its assets # New raids use DigitCounter if raid == 'ESSEX': return RaidCounter(button, letter=(57, 52, 255), threshold=128) elif raid == 'SURUGA': return RaidCounter(button, letter=(49, 48, 49), threshold=128) elif raid == 'BRISTOL': return RaidCounter(button, letter=(214, 231, 219), threshold=128) elif raid == 'IRIS': # Font is not in model 'azur_lane', so use general ocr model if server.server == 'en': # Bold in EN return RaidCounter(button, letter=(148, 138, 123), threshold=80, lang='cnocr') if server.server == 'jp': return RaidCounter(button, letter=(148, 138, 123), threshold=128, lang='cnocr') else: return DigitCounter(button, letter=(148, 138, 123), threshold=128, lang='cnocr') except KeyError: raise ScriptError(f'Raid entrance asset not exists: {key}')
from datetime import datetime from module.base.button import ButtonGrid from module.base.timer import Timer from module.base.utils import * from module.exception import GameBugError from module.guild.assets import * from module.guild.base import GuildBase from module.logger import logger from module.ocr.ocr import DigitCounter from module.template.assets import TEMPLATE_OPERATIONS_RED_DOT GUILD_OPERATIONS_PROGRESS = DigitCounter(OCR_GUILD_OPERATIONS_PROGRESS, letter=(255, 247, 247), threshold=64) class GuildOperations(GuildBase): def _guild_operations_ensure(self, skip_first_screenshot=True): """ Ensure guild operation is loaded After entering guild operation, background loaded first, then dispatch/boss """ logger.attr('Guild master/official', self.config.GuildOperation_SelectNewOperation) confirm_timer = Timer(1.5, count=3).start() click_count = 0 while 1: if skip_first_screenshot: skip_first_screenshot = False else:
from module.base.mask import Mask from module.base.timer import Timer from module.base.utils import * from module.dorm.assets import * from module.logger import logger from module.ocr.ocr import Digit, DigitCounter from module.template.assets import TEMPLATE_DORM_COIN, TEMPLATE_DORM_LOVE from module.ui.assets import DORM_CHECK from module.ui.page import page_dorm, page_dormmenu from module.ui.ui import UI MASK_DORM = Mask(file='./assets/mask/MASK_DORM.png') DORM_CAMERA_SWIPE = (300, 250) DORM_CAMERA_RANDOM = (-20, -20, 20, 20) OCR_FILL = DigitCounter(OCR_DORM_FILL, letter=(255, 247, 247), threshold=128, name='OCR_DORM_FILL') class Food: def __init__(self, feed, amount): self.feed = feed self.amount = amount def __str__(self): return f'Food_{self.feed}' def __eq__(self, other): return str(self) == str(other)
from module.combat.assets import GET_ITEMS_1 from module.data_key.assets import * from module.logger import logger from module.ocr.ocr import DigitCounter from module.ui.assets import WAR_ARCHIVES_CHECK, CAMPAIGN_MENU_GOTO_WAR_ARCHIVES from module.ui.ui import UI, page_archives DATA_KEY = DigitCounter(OCR_DATA_KEY, letter=(255, 247, 247), threshold=64) class RewardDataKey(UI): def _data_key_collect(self, skip_first_screenshot=True): """ Pages: in: page_archives out: page_archives, DATA_KEY_COLLECTED """ logger.hr('Data Key Collect') while 1: if skip_first_screenshot: skip_first_screenshot = False else: self.device.screenshot() if self.appear_then_click(DATA_KEY_COLLECT, offset=(20, 20), interval=3): continue if self.appear(GET_ITEMS_1, offset=20, interval=3): self.device.click(DATA_KEY_COLLECT) continue
from campaign.campaign_war_archives.campaign_base import CampaignBase from module.campaign.run import CampaignRun from module.logger import logger from module.ocr.ocr import DigitCounter from module.war_archives.assets import OCR_DATA_KEY_CAMPAIGN, WAR_ARCHIVES_CAMPAIGN_CHECK DATA_KEY_CAMPAIGN = DigitCounter(OCR_DATA_KEY_CAMPAIGN, letter=(255, 247, 247), threshold=64) class CampaignWarArchives(CampaignRun, CampaignBase): def triggered_stop_condition(self, oil_check=True): # Must be in archives campaign to OCR check if self.appear(WAR_ARCHIVES_CAMPAIGN_CHECK, offset=(20, 20)): # Check for 0 data keys left to use current, remain, total = DATA_KEY_CAMPAIGN.ocr(self.device.image) logger.info(f'Inventory: {current} / {total}, Remain: {current}') if remain == total: logger.hr('Triggered out of data keys') return True # Else, check other stop conditions return super().triggered_stop_condition(oil_check) def run(self, name=None, folder='campaign_main', total=0): backup = self.config.cover(USE_DATA_KEY=True) super().run(name, folder, total) backup.recover()
from module.base.button import ButtonGrid from module.base.utils import * from module.logger import logger from module.ocr.ocr import Digit, DigitCounter from module.os_handler.assets import * from module.statistics.item import ItemGrid from module.ui.assets import OS_CHECK from module.ui.ui import UI OCR_ACTION_POINT_REMAIN = Digit(ACTION_POINT_REMAIN, letter=(255, 219, 66), name='OCR_ACTION_POINT_REMAIN') # Letters in ACTION_POINT_BUY_REMAIN are not the numeric fonts usually used in azur lane. OCR_ACTION_POINT_BUY_REMAIN = DigitCounter(ACTION_POINT_BUY_REMAIN, letter=(148, 247, 99), lang='cnocr', name='OCR_ACTION_POINT_BUY_REMAIN') ACTION_POINT_GRID = ButtonGrid(origin=(323, 274), delta=(173, 0), button_shape=(115, 115), grid_shape=(4, 1), name='ACTION_POINT_GRID') ACTION_POINT_ITEMS = ItemGrid(ACTION_POINT_GRID, templates={}, amount_area=(43, 89, 113, 113)) ACTION_POINTS_COST = { 1: 5, 2: 10, 3: 15, 4: 20, 5: 30,
from module.combat.assets import GET_ITEMS_1 from module.logger import logger from module.ocr.ocr import Digit, DigitCounter from module.reward.assets import * from module.ui.ui import UI, page_meowfficer, MEOWFFICER_GOTO_DORM BUY_MAX = 15 BUY_PRIZE = 1500 MEOWFFICER = DigitCounter(OCR_MEOWFFICER, letter=(140, 113, 99), threshold=64) MEOWFFICER_CHOOSE = Digit(OCR_MEOWFFICER_CHOOSE, letter=(140, 113, 99), threshold=64) MEOWFFICER_COINS = Digit(OCR_MEOWFFICER_COINS, letter=(99, 69, 41), threshold=64) class RewardMeowfficer(UI): def meow_choose(self, count): """ Pages: in: page_meowfficer out: MEOWFFICER_BUY Args: count (int): 0 to 15. Returns: bool: If success. """ remain, _, _ = MEOWFFICER.ocr(self.device.image) logger.attr('Meowfficer_remain', remain) # Check buy status if remain <= BUY_MAX - count:
from module.base.button import ButtonGrid from module.base.timer import Timer from module.handler.assets import INFO_BAR_1 from module.logger import logger from module.meowfficer.assets import * from module.meowfficer.collect import MeowfficerCollect from module.meowfficer.enhance import MeowfficerEnhance from module.ocr.ocr import Digit, DigitCounter MEOWFFICER_CAPACITY = DigitCounter(OCR_MEOWFFICER_CAPACITY, letter=(131, 121, 123), threshold=64) MEOWFFICER_QUEUE = DigitCounter(OCR_MEOWFFICER_QUEUE, letter=(131, 121, 123), threshold=64) MEOWFFICER_BOX_GRID = ButtonGrid(origin=(460, 210), delta=(160, 0), button_shape=(30, 30), grid_shape=(3, 1), name='MEOWFFICER_BOX_GRID') MEOWFFICER_BOX_COUNT_GRID = ButtonGrid(origin=(776, 21), delta=(133, 0), button_shape=(65, 27), grid_shape=(3, 1), name='MEOWFFICER_BOX_COUNT_GRID') MEOWFFICER_BOX_COUNT = Digit(MEOWFFICER_BOX_COUNT_GRID.buttons, letter=(16, 12, 0), threshold=64, name='MEOWFFICER_BOX_COUNT')
from module.base.timer import Timer from module.combat.assets import GET_ITEMS_1 from module.config.utils import get_server_next_update from module.handler.assets import INFO_BAR_1 from module.logger import logger from module.meowfficer.assets import * from module.ocr.ocr import Digit, DigitCounter from module.ui.assets import MEOWFFICER_GOTO_DORM, MEOWFFICER_INFO from module.ui.ui import UI, page_meowfficer BUY_MAX = 15 BUY_PRIZE = 1500 MEOWFFICER = DigitCounter(OCR_MEOWFFICER, letter=(140, 113, 99), threshold=64) MEOWFFICER_CHOOSE = Digit(OCR_MEOWFFICER_CHOOSE, letter=(140, 113, 99), threshold=64) MEOWFFICER_COINS = Digit(OCR_MEOWFFICER_COINS, letter=(99, 69, 41), threshold=64) MEOWFFICER_CAPACITY = DigitCounter(OCR_MEOWFFICER_CAPACITY, letter=(131, 121, 123), threshold=64) class RewardMeowfficer(UI): def meow_choose(self, count): """ Pages: in: page_meowfficer out: MEOWFFICER_BUY
from module.base.timer import Timer from module.base.utils import color_bar_percentage from module.combat.combat import Combat, BATTLE_PREPARATION, GET_ITEMS_1 from module.logger import logger from module.ocr.ocr import Digit, DigitCounter from module.os_ash.assets import * from module.os_handler.assets import IN_MAP from module.ui.page import page_os from module.ui.switch import Switch from module.ui.ui import UI OCR_BEACON_REMAIN = DigitCounter(BEACON_REMAIN, threshold=256, name='OCR_ASH_REMAIN') OCR_BEACON_TIER = Digit(BEACON_TIER, name='OCR_ASH_TIER') OCR_ASH_COLLECT_STATUS = DigitCounter(ASH_COLLECT_STATUS, letter=(235, 235, 235), threshold=160, name='OCR_ASH_COLLECT_STATUS') SWITCH_BEACON = Switch(name='Beacon', offset=(20, 20)) SWITCH_BEACON.add_status('mine', BEACON_LIST) SWITCH_BEACON.add_status('list', BEACON_MY) RECORD_OPTION = ('DailyRecord', 'ash') RECORD_SINCE = (0, ) class AshCombat(Combat): def handle_battle_status(self, save_get_items=False): """
from module.campaign.campaign_event import CampaignEvent from module.event.assets import * from module.exception import CampaignEnd from module.logger import logger from module.map.map_operation import MapOperation from module.ocr.ocr import DigitCounter OCR_REMAIN = DigitCounter(ESCORT_REMAIN, letter=(148, 255, 99), threshold=64) class MaritimeEscort(MapOperation, CampaignEvent): def is_in_escort(self): return self.appear(ESCORT_CHECK, offset=(20, 20)) def handle_in_stage(self): if self.is_in_escort(): if self.in_stage_timer.reached(): return True else: return False else: self.in_stage_timer.reset() return False def run_escort(self): """ Just enter and retreat, get about 70% of maximum rewards. Pages: in: ESCORT_CHECK out: ESCORT_CHECK
CARD_GRIDS = ButtonGrid(origin=(93, 76), delta=(164 + 2 / 3, 227), button_shape=(138, 204), grid_shape=(7, 2), name='CARD') CARD_RARITY_GRIDS = CARD_GRIDS.crop(area=(0, 0, 138, 5), name='RARITY') CARD_LEVEL_GRIDS = CARD_GRIDS.crop(area=(77, 5, 138, 27), name='LEVEL') CARD_EMOTION_GRIDS = CARD_GRIDS.crop(area=(23, 29, 48, 52), name='EMOTION') CARD_BOTTOM_GRIDS = CARD_GRIDS.move(vector=(0, 94), name='CARD') CARD_BOTTOM_LEVEL_GRIDS = CARD_LEVEL_GRIDS.move(vector=(0, 94), name='LEVEL') CARD_BOTTOM_EMOTION_GRIDS = CARD_EMOTION_GRIDS.move(vector=(0, 94), name='EMOTION') DOCK_SCROLL = Scroll(DOCK_SCROLL, color=(247, 211, 66), name='DOCK_SCROLL') OCR_DOCK_SELECTED = DigitCounter(DOCK_SELECTED, threshold=64, name='OCR_DOCK_SELECTED') class Dock(Equipment): def handle_dock_cards_loading(self): # Poor implementation. self.device.sleep((1, 1.5)) self.device.screenshot() def dock_favourite_set(self, enable=False): if DOCK_FAVOURITE.set('on' if enable else 'off', main=self): self.handle_dock_cards_loading() def _dock_quit_check_func(self): return not self.appear(DOCK_CHECK, offset=(20, 20))
from module.ocr.ocr import DigitCounter from module.ui.assets import MEOWFFICER_GOTO_DORM from module.ui.page import page_meowfficer MEOWFFICER_SELECT_GRID = ButtonGrid(origin=(770, 245), delta=(130, 147), button_shape=(70, 20), grid_shape=(4, 3), name='MEOWFFICER_SELECT_GRID') MEOWFFICER_FEED_GRID = ButtonGrid(origin=(818, 212), delta=(130, 147), button_shape=(30, 30), grid_shape=(4, 3), name='MEOWFFICER_FEED_GRID') MEOWFFICER_FEED = DigitCounter(OCR_MEOWFFICER_FEED, letter=(131, 121, 123), threshold=64) class MeowfficerEnhance(MeowfficerBase): def _meow_select(self, skip_first_screenshot=True): """ Select the target meowfficer in the MEOWFFICER_SELECT_GRID (4x3) Ensure through dotted yellow/white circle appearance after click Args: skip_first_screenshot (bool): """ # Calculate (x, y) coordinate within
from random import choice from module.base.timer import Timer from module.combat.assets import GET_ITEMS_1 from module.exception import ScriptError from module.logger import logger from module.ocr.ocr import DigitCounter from module.retire.assets import * from module.retire.dock import CARD_GRIDS, Dock VALID_SHIP_TYPES = ['dd', 'ss', 'cl', 'ca', 'bb', 'cv', 'repair', 'others'] OCR_DOCK_AMOUNT = DigitCounter(DOCK_AMOUNT, letter=(255, 255, 255), threshold=192) class Enhancement(Dock): @property def _retire_amount(self): if self.config.Retirement_RetireAmount == 'retire_all': return 2000 if self.config.Retirement_RetireAmount == 'retire_10': return 10 return 2000 def _enhance_enter(self, favourite=False, ship_type=None): """ Pages: in: page_dock out: page_ship_enhance
from module.os_handler.map_event import MapEventHandler from module.ui.assets import BACK_ARROW from module.ui.page import page_os from module.ui.switch import Switch from module.ui.ui import UI class DailyDigitCounter(DigitCounter): def pre_process(self, image): image = super().pre_process(image) image = image_left_strip(image, threshold=120, length=35) return image OCR_BEACON_REMAIN = DigitCounter(BEACON_REMAIN, threshold=256, name='OCR_ASH_REMAIN') OCR_BEACON_TIER = Digit(BEACON_TIER, name='OCR_ASH_TIER') SWITCH_BEACON = Switch(name='Beacon', offset=(20, 20)) SWITCH_BEACON.add_status('mine', BEACON_LIST) SWITCH_BEACON.add_status('list', BEACON_MY) class AshBeaconFinished(Exception): pass class AshCombat(Combat): def handle_battle_status(self, drop=None): """