Refactor: [ALAS] Page class

Path findings in page class
This commit is contained in:
LmeSzinc 2023-07-02 15:24:40 +08:00
parent 11d094c025
commit 2f771d8ca5
15 changed files with 94 additions and 117 deletions

View File

@ -12,7 +12,7 @@ from module.retire.assets import DOCK_CHECK, TEMPLATE_BOGUE, TEMPLATE_HERMES, TE
from module.retire.dock import Dock
from module.retire.scanner import ShipScanner
from module.ui.page import page_fleet
from module.ui.ui import BACK_ARROW
from module.ui.assets import BACK_ARROW
SIM_VALUE = 0.95

View File

@ -7,9 +7,8 @@ from module.daily.assets import *
from module.equipment.fleet_equipment import DailyEquipment
from module.logger import logger
from module.ocr.ocr import Digit
from module.ui.assets import DAILY_CHECK
from module.ui.ui import (BACK_ARROW, page_campaign_menu,
page_daily)
from module.ui.assets import BACK_ARROW, DAILY_CHECK
from module.ui.page import page_campaign_menu, page_daily
DAILY_MISSION_LIST = [DAILY_MISSION_1, DAILY_MISSION_2, DAILY_MISSION_3]
OCR_REMAIN = Digit(OCR_REMAIN, threshold=128, alphabet='01234')

View File

@ -3,7 +3,7 @@ from module.equipment.equipment import Equipment
from module.logger import logger
from module.ocr.ocr import Digit
from module.ui.assets import FLEET_CHECK
from module.ui.ui import page_fleet
from module.ui.page import page_fleet
OCR_FLEET_INDEX = Digit(OCR_FLEET_INDEX, letter=(90, 154, 255), threshold=128, alphabet='123456')

View File

@ -4,7 +4,7 @@ from module.exercise.assets import *
from module.exercise.combat import ExerciseCombat
from module.logger import logger
from module.ocr.ocr import Digit, Ocr, OcrYuv
from module.ui.ui import page_exercise
from module.ui.page import page_exercise
class DatedDuration(Ocr):

View File

@ -4,7 +4,9 @@ from module.logger import logger
from module.ocr.ocr import DigitCounter
from module.ui.assets import (CAMPAIGN_MENU_GOTO_WAR_ARCHIVES,
WAR_ARCHIVES_CHECK)
from module.ui.ui import UI, page_archives
from module.ui.page import page_archives
from module.ui.ui import UI
DATA_KEY = DigitCounter(OCR_DATA_KEY, letter=(255, 247, 247), threshold=64)

View File

@ -8,7 +8,7 @@ from module.combat.assets import *
from module.freebies.assets import *
from module.logger import logger
from module.statistics.item import ItemGrid
from module.ui.page import *
from module.ui.page import page_main
from module.ui.ui import UI
MAIL_BUTTON_GRID = ButtonGrid(

View File

@ -1,7 +1,7 @@
from module.guild.lobby import GuildLobby
from module.guild.logistics import GuildLogistics
from module.guild.operations import GuildOperations
from module.ui.ui import page_guild, page_main
from module.ui.page import page_guild, page_main
class RewardGuild(GuildLobby, GuildLogistics, GuildOperations):

View File

@ -1,7 +1,8 @@
import re
from module.base.mask import Mask
from module.ui.page import *
from module.ui.assets import PLAYER_CHECK
from module.ui.page import MAIN_CHECK
MASK_MAIN = Mask('./assets/mask/MASK_MAIN.png')
MASK_PLAYER = Mask('./assets/mask/MASK_PLAYER.png')

View File

@ -1,7 +1,7 @@
from module.meowfficer.buy import MeowfficerBuy
from module.meowfficer.fort import MeowfficerFort
from module.meowfficer.train import MeowfficerTrain
from module.ui.ui import page_meowfficer
from module.ui.page import page_meowfficer
class RewardMeowfficer(MeowfficerBuy, MeowfficerFort, MeowfficerTrain):

View File

@ -4,8 +4,9 @@ from module.combat.combat import Combat
from module.logger import logger
from module.meta_reward.assets import *
from module.template.assets import TEMPLATE_META_DOCK_RED_DOT
from module.ui.assets import BACK_ARROW
from module.ui.page import page_meta
from module.ui.ui import UI, BACK_ARROW
from module.ui.ui import UI
class MetaReward(Combat, UI):

View File

@ -12,7 +12,8 @@ from module.research.project import get_research_finished
from module.research.rqueue import ResearchQueue
from module.research.selector import RESEARCH_ENTRANCE, ResearchSelector
from module.storage.storage import StorageHandler
from module.ui.page import *
from module.ui.assets import RESEARCH_CHECK
from module.ui.page import page_research
OCR_DURATION = Duration(RESEARCH_LAB_DURATION_REMAIN, letter=(255, 255, 255), threshold=64,
name='RESEARCH_LAB_DURATION_REMAIN')

View File

@ -4,8 +4,9 @@ from module.base.timer import Timer
from module.combat.assets import *
from module.logger import logger
from module.reward.assets import *
from module.ui.assets import MISSION_CHECK
from module.ui.navbar import Navbar
from module.ui.page import *
from module.ui.page import page_main, page_mission, page_reward
from module.ui.ui import UI

View File

@ -18,7 +18,7 @@ from module.tactical.assets import *
from module.ui.assets import (BACK_ARROW, MAIN_GOTO_REWARD,
REWARD_GOTO_TACTICAL, REWARD_CHECK,
TACTICAL_CHECK)
from module.ui.ui import page_reward
from module.ui.page import page_reward
SKILL_GRIDS = ButtonGrid(origin=(315, 140), delta=(621, 132), button_shape=(621, 119), grid_shape=(1, 3), name='SKILL')
SKILL_LEVEL_GRIDS = SKILL_GRIDS.crop(area=(406, 98, 618, 116), name='EXP')

View File

@ -6,13 +6,56 @@ MAIN_CHECK = MAIN_GOTO_CAMPAIGN
class Page:
parent = None
# Key: str, page name like "page_main"
# Value: Page, page instance
all_pages = {}
@classmethod
def clear_connection(cls):
for page in cls.all_pages.values():
page.parent = None
@classmethod
def init_connection(cls, destination):
"""
Initialize an A* path finding among pages.
Args:
destination (Page):
"""
cls.clear_connection()
visited = [destination]
visited = set(visited)
while 1:
new = visited.copy()
for page in visited:
for link in cls.iter_pages():
if link in visited:
continue
if page in link.links:
link.parent = page
new.add(link)
if len(new) == len(visited):
break
visited = new
@classmethod
def iter_pages(cls):
return cls.all_pages.values()
@classmethod
def iter_check_buttons(cls):
for page in cls.all_pages.values():
yield page.check_button
def __init__(self, check_button):
self.check_button = check_button
self.links = {}
(filename, line_number, function_name, text) = traceback.extract_stack()[-2]
self.name = text[:text.find('=')].strip()
self.parent = None
Page.all_pages[self.name] = self
def __eq__(self, other):
return self.name == other.name

View File

@ -22,57 +22,10 @@ from module.raid.assets import RAID_FLEET_PREPARATION
from module.ui.assets import (BACK_ARROW, DORM_FEED_CANCEL, DORM_INFO, DORM_TROPHY_CONFIRM, EVENT_LIST_CHECK, GOTO_MAIN,
MAIN_GOTO_CAMPAIGN, MEOWFFICER_GOTO_DORMMENU, MEOWFFICER_INFO, META_CHECK, PLAYER_CHECK,
RAID_CHECK, SHIPYARD_CHECK, SHOP_GOTO_SUPPLY_PACK)
from module.ui.page import (Page, page_academy, page_archives,
page_battle_pass, page_build, page_campaign,
page_campaign_menu, page_commission, page_daily,
page_dorm, page_dormmenu, page_event,
page_event_list, page_exercise, page_fleet,
page_guild, page_main, page_meowfficer, page_meta,
page_mission, page_munitions, page_os, page_raid,
page_research, page_reshmenu, page_reward,
page_shipyard, page_shop, page_sp, page_storage,
page_supply_pack, page_tactical, page_unknown)
# from module.ui.page import *
from module.ui.page import (Page, page_campaign, page_event, page_main, page_sp)
class UI(InfoHandler):
# All pages defined.
ui_pages = [
page_unknown,
page_main,
page_fleet,
page_guild,
page_mission,
page_event_list,
page_campaign_menu,
page_campaign,
page_exercise,
page_daily,
page_event,
page_sp,
page_raid,
page_archives,
page_reward,
page_commission,
page_tactical,
page_battle_pass,
page_reshmenu,
page_research,
page_shipyard,
page_meta,
page_dormmenu,
page_dorm,
page_meowfficer,
page_academy,
page_shop,
page_storage,
page_munitions,
page_supply_pack,
page_build,
page_os,
]
ui_current: Page
def ui_page_appear(self, page):
@ -91,15 +44,15 @@ class UI(InfoHandler):
return False
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,
self,
click_button,
check_button,
appear_button=None,
additional=None,
confirm_wait=1,
offset=(30, 30),
retry_wait=10,
skip_first_screenshot=False,
):
"""
Args:
@ -133,7 +86,7 @@ class UI(InfoHandler):
if click_timer.reached():
if (isinstance(appear_button, Button) and self.appear(appear_button, offset=offset)) or (
callable(appear_button) and appear_button()
callable(appear_button) and appear_button()
):
self.device.click(click_button)
click_timer.reset()
@ -202,7 +155,7 @@ class UI(InfoHandler):
break
# Known pages
for page in self.ui_pages:
for page in Page.iter_pages():
if page.check_button is None:
continue
if self.ui_page_appear(page=page):
@ -226,41 +179,23 @@ class UI(InfoHandler):
logger.attr("EMULATOR__CONTROL_METHOD", self.config.Emulator_ControlMethod)
logger.attr("SERVER", self.config.SERVER)
logger.warning("Starting from current page is not supported")
logger.warning(f"Supported page: {[str(page) for page in self.ui_pages]}")
logger.warning(f"Supported page: {[str(page) for page in Page.iter_pages()]}")
logger.warning('Supported page: Any page with a "HOME" button on the upper-right')
logger.critical("Please switch to a supported page before starting Alas")
raise GamePageUnknownError
def ui_goto(self, destination, offset=(30, 30), confirm_wait=0, skip_first_screenshot=True):
def ui_goto(self, destination, offset=(30, 30), skip_first_screenshot=True):
"""
Args:
destination (Page):
offset:
confirm_wait:
skip_first_screenshot:
"""
# Reset connection
for page in self.ui_pages:
page.parent = None
# Create connection
visited = [destination]
visited = set(visited)
while 1:
new = visited.copy()
for page in visited:
for link in self.ui_pages:
if link in visited:
continue
if page in link.links:
link.parent = page
new.add(link)
if len(new) == len(visited):
break
visited = new
Page.init_connection(destination)
self.interval_clear(list(Page.iter_check_buttons()))
logger.hr(f"UI goto {destination}")
confirm_timer = Timer(confirm_wait, count=int(confirm_wait // 0.5)).start()
while 1:
GOTO_MAIN.clear_offset()
if skip_first_screenshot:
@ -270,15 +205,12 @@ class UI(InfoHandler):
# Destination page
if self.appear(destination.check_button, offset=offset):
if confirm_timer.reached():
logger.info(f'Page arrive: {destination}')
break
else:
confirm_timer.reset()
logger.info(f'Page arrive: {destination}')
break
# Other pages
clicked = False
for page in visited:
for page in Page.iter_pages():
if page.parent is None or page.check_button is None:
continue
if self.appear(page.check_button, offset=offset, interval=5):
@ -286,7 +218,6 @@ class UI(InfoHandler):
button = page.links[page.parent]
self.device.click(button)
self.ui_button_interval_reset(button)
confirm_timer.reset()
clicked = True
break
if clicked:
@ -297,8 +228,7 @@ class UI(InfoHandler):
continue
# Reset connection
for page in self.ui_pages:
page.parent = None
Page.clear_connection()
def ui_ensure(self, destination, skip_first_screenshot=True):
"""
@ -332,14 +262,14 @@ class UI(InfoHandler):
return self.ui_ensure(destination=page_sp)
def ui_ensure_index(
self,
index,
letter,
next_button,
prev_button,
skip_first_screenshot=False,
fast=True,
interval=(0.2, 0.3),
self,
index,
letter,
next_button,
prev_button,
skip_first_screenshot=False,
fast=True,
interval=(0.2, 0.3),
):
"""
Args:
@ -350,8 +280,6 @@ class UI(InfoHandler):
skip_first_screenshot (bool):
fast (bool): Default true. False when index is not continuous.
interval (tuple, int, float): Seconds between two click.
step_sleep (tuple, int, float): Seconds between two step.
finish_sleep (tuple, int, float): Second to wait when arrive.
"""
logger.hr("UI ensure index")
retry = Timer(1, count=2)
@ -457,7 +385,8 @@ class UI(InfoHandler):
if self._opsi_reset_fleet_preparation_click >= 5:
logger.critical("Failed to confirm OpSi fleets, too many click on RESET_FLEET_PREPARATION")
logger.critical("Possible reason #1: You haven't set any fleets in operation siren")
logger.critical("Possible reason #2: Your fleets haven't satisfied the level restrictions in operation siren")
logger.critical(
"Possible reason #2: Your fleets haven't satisfied the level restrictions in operation siren")
raise RequestHumanTakeover
if self.appear_then_click(RESET_TICKET_POPUP, offset=(30, 30), interval=3):
return True