mirror of
https://github.com/sui-feng-cb/AzurLaneAutoScript1.git
synced 2026-08-07 17:49:05 +08:00
Upd: GemsFarming
This commit is contained in:
@@ -1,4 +1,7 @@
|
|||||||
|
from datetime import datetime
|
||||||
|
|
||||||
from module.base.decorator import cached_property
|
from module.base.decorator import cached_property
|
||||||
|
from module.base.timer import Timer
|
||||||
from module.campaign.campaign_base import CampaignBase
|
from module.campaign.campaign_base import CampaignBase
|
||||||
from module.campaign.run import CampaignRun
|
from module.campaign.run import CampaignRun
|
||||||
from module.combat.assets import BATTLE_PREPARATION
|
from module.combat.assets import BATTLE_PREPARATION
|
||||||
@@ -16,8 +19,9 @@ from module.retire.assets import (
|
|||||||
TEMPLATE_CASSIN_1, TEMPLATE_CASSIN_2, TEMPLATE_DOWNES_1, TEMPLATE_DOWNES_2,
|
TEMPLATE_CASSIN_1, TEMPLATE_CASSIN_2, TEMPLATE_DOWNES_1, TEMPLATE_DOWNES_2,
|
||||||
TEMPLATE_AULICK, TEMPLATE_FOOTE
|
TEMPLATE_AULICK, TEMPLATE_FOOTE
|
||||||
)
|
)
|
||||||
|
from module.retire.dock import Dock
|
||||||
# TEMPLATE_COMMON_CV and TEMPLATE_COMMON_DD are both used in function find_custom_candidates
|
# TEMPLATE_COMMON_CV and TEMPLATE_COMMON_DD are both used in function find_custom_candidates
|
||||||
from module.retire.retirement import Retirement, TEMPLATE_COMMON_CV, TEMPLATE_COMMON_DD
|
from module.retire.retirement import TEMPLATE_COMMON_CV, TEMPLATE_COMMON_DD
|
||||||
from module.retire.scanner import ShipScanner
|
from module.retire.scanner import ShipScanner
|
||||||
from module.ui.assets import BACK_ARROW, FLEET_CHECK
|
from module.ui.assets import BACK_ARROW, FLEET_CHECK
|
||||||
from module.ui.page import page_fleet
|
from module.ui.page import page_fleet
|
||||||
@@ -47,7 +51,16 @@ class GemsEmotion(Emotion):
|
|||||||
raise CampaignEnd('Emotion control')
|
raise CampaignEnd('Emotion control')
|
||||||
|
|
||||||
def wait(self, fleet_index):
|
def wait(self, fleet_index):
|
||||||
pass
|
"""
|
||||||
|
Override Emotion.wait to trigger stop condition when emotion is too low after battle.
|
||||||
|
"""
|
||||||
|
self.update()
|
||||||
|
self.record()
|
||||||
|
self.show()
|
||||||
|
fleet = self.fleets[fleet_index - 1]
|
||||||
|
recovered = fleet.get_recovered(expected_reduce=self.reduce_per_battle)
|
||||||
|
if recovered > datetime.now():
|
||||||
|
self.config.GEMS_EMOTION_TRIGGERED = True
|
||||||
|
|
||||||
|
|
||||||
class GemsCampaignOverride(CampaignBase):
|
class GemsCampaignOverride(CampaignBase):
|
||||||
@@ -95,47 +108,7 @@ class GemsCampaignOverride(CampaignBase):
|
|||||||
raise CampaignEnd('Emotion withdraw')
|
raise CampaignEnd('Emotion withdraw')
|
||||||
|
|
||||||
|
|
||||||
class GemsEquipmentHandler(EquipmentCodeHandler):
|
class GemsFarming(CampaignRun, Dock):
|
||||||
|
|
||||||
def __init__(self, config, device=None, task=None):
|
|
||||||
super().__init__(config=config,
|
|
||||||
device=device,
|
|
||||||
task=task,
|
|
||||||
key="GemsFarming.GemsFarming.EquipmentCode",
|
|
||||||
ships=['DD', 'bogue', 'hermes', 'langley', 'ranger'])
|
|
||||||
|
|
||||||
def current_ship(self, skip_first_screenshot=True):
|
|
||||||
"""
|
|
||||||
Reuse templates in module.retire.assets,
|
|
||||||
which needs different rescaling to match each current flagship.
|
|
||||||
|
|
||||||
Pages:
|
|
||||||
in: gear_code
|
|
||||||
"""
|
|
||||||
while 1:
|
|
||||||
if skip_first_screenshot:
|
|
||||||
skip_first_screenshot = False
|
|
||||||
else:
|
|
||||||
self.device.screenshot()
|
|
||||||
|
|
||||||
# End
|
|
||||||
if not self.appear(EMPTY_SHIP_R):
|
|
||||||
break
|
|
||||||
else:
|
|
||||||
logger.info('Waiting ship icon loading.')
|
|
||||||
|
|
||||||
if TEMPLATE_BOGUE.match(self.device.image, scaling=1.46): # image has rotation
|
|
||||||
return 'bogue'
|
|
||||||
if TEMPLATE_HERMES.match(self.device.image, scaling=124/89):
|
|
||||||
return 'hermes'
|
|
||||||
if TEMPLATE_RANGER.match(self.device.image, scaling=4/3):
|
|
||||||
return 'ranger'
|
|
||||||
if TEMPLATE_LANGLEY.match(self.device.image, scaling=25/21):
|
|
||||||
return 'langley'
|
|
||||||
return 'DD'
|
|
||||||
|
|
||||||
|
|
||||||
class GemsFarming(CampaignRun, GemsEquipmentHandler, Retirement):
|
|
||||||
def hard_mode_override(self):
|
def hard_mode_override(self):
|
||||||
if self.campaign.config.Campaign_Mode == 'hard':
|
if self.campaign.config.Campaign_Mode == 'hard':
|
||||||
logger.info('Is in hard mode, switch ship changing method.')
|
logger.info('Is in hard mode, switch ship changing method.')
|
||||||
@@ -217,19 +190,25 @@ class GemsFarming(CampaignRun, GemsEquipmentHandler, Retirement):
|
|||||||
def _fleet_detail_enter_hard(self, fleet):
|
def _fleet_detail_enter_hard(self, fleet):
|
||||||
if self.appear(FLEET_PREPARATION, offset=(20, 50)):
|
if self.appear(FLEET_PREPARATION, offset=(20, 50)):
|
||||||
return
|
return
|
||||||
self.campaign.ensure_campaign_ui(self.stage)
|
self.campaign.ensure_campaign_ui(self.stage, 'hard')
|
||||||
self.ui_click(click_button=self.campaign.ENTRANCE, appear_button=BACK_ARROW, check_button=MAP_PREPARATION)
|
self.campaign.ENTRANCE.area = self.campaign.ENTRANCE.button
|
||||||
while 1:
|
campaign_timer = Timer(5)
|
||||||
self.device.screenshot()
|
map_timer = Timer(5)
|
||||||
|
for _ in self.loop():
|
||||||
if self.appear_then_click(MAP_PREPARATION, interval=1):
|
|
||||||
continue
|
|
||||||
|
|
||||||
if self.handle_retirement():
|
|
||||||
continue
|
|
||||||
|
|
||||||
if self.appear(FLEET_PREPARATION, offset=(20, 50)):
|
if self.appear(FLEET_PREPARATION, offset=(20, 50)):
|
||||||
break
|
break
|
||||||
|
if map_timer.reached() \
|
||||||
|
and self.campaign.handle_map_mode_switch('hard') \
|
||||||
|
and self.campaign.handle_map_preparation():
|
||||||
|
self.device.click(MAP_PREPARATION)
|
||||||
|
map_timer.reset()
|
||||||
|
campaign_timer.reset()
|
||||||
|
# Retire
|
||||||
|
if self.campaign.handle_retirement():
|
||||||
|
continue
|
||||||
|
if campaign_timer.reached() and self.appear_then_click(self.campaign.ENTRANCE):
|
||||||
|
campaign_timer.reset()
|
||||||
|
continue
|
||||||
|
|
||||||
def _ship_detail_enter_hard(self, button):
|
def _ship_detail_enter_hard(self, button):
|
||||||
self.ship_info_enter(button)
|
self.ship_info_enter(button)
|
||||||
@@ -254,7 +233,7 @@ class GemsFarming(CampaignRun, GemsEquipmentHandler, Retirement):
|
|||||||
if self.change_flagship_equip:
|
if self.change_flagship_equip:
|
||||||
logger.hr('Unmount flagship equipments', level=2)
|
logger.hr('Unmount flagship equipments', level=2)
|
||||||
self._ship_detail_enter(self.fleet_detail_enter_flagship)
|
self._ship_detail_enter(self.fleet_detail_enter_flagship)
|
||||||
self.clear_all_equip()
|
self.ship_equipment_take_off()
|
||||||
self._fleet_back()
|
self._fleet_back()
|
||||||
|
|
||||||
logger.hr('Change flagship', level=2)
|
logger.hr('Change flagship', level=2)
|
||||||
@@ -263,7 +242,7 @@ class GemsFarming(CampaignRun, GemsEquipmentHandler, Retirement):
|
|||||||
if self.change_flagship_equip:
|
if self.change_flagship_equip:
|
||||||
logger.hr('Mount flagship equipments', level=2)
|
logger.hr('Mount flagship equipments', level=2)
|
||||||
self._ship_detail_enter(self.fleet_detail_enter_flagship)
|
self._ship_detail_enter(self.fleet_detail_enter_flagship)
|
||||||
self.apply_equip_code()
|
self.ship_equipment_take_on()
|
||||||
self._fleet_back()
|
self._fleet_back()
|
||||||
|
|
||||||
return success
|
return success
|
||||||
@@ -281,7 +260,7 @@ class GemsFarming(CampaignRun, GemsEquipmentHandler, Retirement):
|
|||||||
if self.change_vanguard_equip:
|
if self.change_vanguard_equip:
|
||||||
logger.hr('Unmount vanguard equipments', level=2)
|
logger.hr('Unmount vanguard equipments', level=2)
|
||||||
self._ship_detail_enter(self.fleet_detail_enter)
|
self._ship_detail_enter(self.fleet_detail_enter)
|
||||||
self.clear_all_equip()
|
self.ship_equipment_take_off()
|
||||||
self._fleet_back()
|
self._fleet_back()
|
||||||
|
|
||||||
logger.hr('Change vanguard', level=2)
|
logger.hr('Change vanguard', level=2)
|
||||||
@@ -290,19 +269,14 @@ class GemsFarming(CampaignRun, GemsEquipmentHandler, Retirement):
|
|||||||
if self.change_vanguard_equip:
|
if self.change_vanguard_equip:
|
||||||
logger.hr('Mount vanguard equipments', level=2)
|
logger.hr('Mount vanguard equipments', level=2)
|
||||||
self._ship_detail_enter(self.fleet_detail_enter)
|
self._ship_detail_enter(self.fleet_detail_enter)
|
||||||
self.apply_equip_code()
|
self.ship_equipment_take_on()
|
||||||
self._fleet_back()
|
self._fleet_back()
|
||||||
|
|
||||||
return success
|
return success
|
||||||
|
|
||||||
def _dock_reset(self):
|
|
||||||
self.dock_favourite_set(False, wait_loading=False)
|
|
||||||
self.dock_sort_method_dsc_set(wait_loading=False)
|
|
||||||
self.dock_filter_set()
|
|
||||||
|
|
||||||
def _ship_change_confirm(self, button):
|
def _ship_change_confirm(self, button):
|
||||||
self.dock_select_one(button)
|
self.dock_select_one(button)
|
||||||
self._dock_reset()
|
self.dock_reset()
|
||||||
self.dock_select_confirm(check_button=self.page_fleet_check_button)
|
self.dock_select_confirm(check_button=self.page_fleet_check_button)
|
||||||
|
|
||||||
def get_common_rarity_cv(self, lv=31, emotion=16):
|
def get_common_rarity_cv(self, lv=31, emotion=16):
|
||||||
@@ -480,7 +454,7 @@ class GemsFarming(CampaignRun, GemsEquipmentHandler, Retirement):
|
|||||||
filter_string = self.config.__getattribute__(f'GemsFarming_Common{ship_type}Filter')
|
filter_string = self.config.__getattribute__(f'GemsFarming_Common{ship_type}Filter')
|
||||||
sort_dsc_first = ship_type.lower() == 'dd'
|
sort_dsc_first = ship_type.lower() == 'dd'
|
||||||
|
|
||||||
common_ship = self.get_common_ship_filter(filter_string, ship_type=ship_type)
|
common_ship = self.campaign.get_common_ship_filter(filter_string, ship_type=ship_type)
|
||||||
templates = globals()[f'TEMPLATE_COMMON_{ship_type}']
|
templates = globals()[f'TEMPLATE_COMMON_{ship_type}']
|
||||||
find_first = True
|
find_first = True
|
||||||
common_ship_candidates = {}
|
common_ship_candidates = {}
|
||||||
@@ -614,7 +588,7 @@ class GemsFarming(CampaignRun, GemsEquipmentHandler, Retirement):
|
|||||||
else:
|
else:
|
||||||
if self.hard_mode:
|
if self.hard_mode:
|
||||||
raise RequestHumanTakeover
|
raise RequestHumanTakeover
|
||||||
self._dock_reset()
|
self.dock_reset()
|
||||||
self.ui_back(check_button=self.page_fleet_check_button)
|
self.ui_back(check_button=self.page_fleet_check_button)
|
||||||
return False
|
return False
|
||||||
|
|
||||||
@@ -659,7 +633,7 @@ class GemsFarming(CampaignRun, GemsEquipmentHandler, Retirement):
|
|||||||
else:
|
else:
|
||||||
if self.hard_mode:
|
if self.hard_mode:
|
||||||
raise RequestHumanTakeover
|
raise RequestHumanTakeover
|
||||||
self._dock_reset()
|
self.dock_reset()
|
||||||
self.ui_back(check_button=self.page_fleet_check_button)
|
self.ui_back(check_button=self.page_fleet_check_button)
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|||||||
@@ -2,16 +2,11 @@ from module.base.button import ButtonGrid
|
|||||||
from module.base.decorator import cached_property
|
from module.base.decorator import cached_property
|
||||||
from module.base.timer import Timer
|
from module.base.timer import Timer
|
||||||
from module.equipment.assets import *
|
from module.equipment.assets import *
|
||||||
|
from module.equipment.equipment_code import EquipmentCodeHandler
|
||||||
from module.logger import logger
|
from module.logger import logger
|
||||||
from module.retire.assets import DOCK_CHECK, EQUIP_CONFIRM as RETIRE_EQUIP_CONFIRM
|
from module.retire.assets import DOCK_CHECK, EQUIP_CONFIRM as RETIRE_EQUIP_CONFIRM
|
||||||
from module.storage.storage import StorageHandler
|
|
||||||
from module.ui.assets import BACK_ARROW
|
from module.ui.assets import BACK_ARROW
|
||||||
from module.ui.navbar import Navbar
|
from module.ui.navbar import Navbar
|
||||||
from module.ui.switch import Switch
|
|
||||||
|
|
||||||
equipping_filter = Switch('Equiping_filter')
|
|
||||||
equipping_filter.add_state('on', check_button=EQUIPPING_ON)
|
|
||||||
equipping_filter.add_state('off', check_button=EQUIPPING_OFF)
|
|
||||||
|
|
||||||
SWIPE_DISTANCE = 250
|
SWIPE_DISTANCE = 250
|
||||||
SWIPE_RANDOM_RANGE = (-40, -20, 40, 20)
|
SWIPE_RANDOM_RANGE = (-40, -20, 40, 20)
|
||||||
@@ -19,13 +14,9 @@ SWIPE_RANDOM_RANGE = (-40, -20, 40, 20)
|
|||||||
EQUIPMENT_OPEN.match = EQUIPMENT_OPEN.match_luma
|
EQUIPMENT_OPEN.match = EQUIPMENT_OPEN.match_luma
|
||||||
|
|
||||||
|
|
||||||
class Equipment(StorageHandler):
|
class Equipment(EquipmentCodeHandler):
|
||||||
equipment_has_take_on = False
|
equipment_has_take_on = False
|
||||||
|
|
||||||
def equipping_set(self, enable=False):
|
|
||||||
if equipping_filter.set('on' if enable else 'off', main=self):
|
|
||||||
self.wait_until_stable(SWIPE_AREA)
|
|
||||||
|
|
||||||
def _ship_view_swipe(self, distance, check_button=EQUIPMENT_OPEN):
|
def _ship_view_swipe(self, distance, check_button=EQUIPMENT_OPEN):
|
||||||
swipe_count = 0
|
swipe_count = 0
|
||||||
swipe_timer = Timer(5, count=10)
|
swipe_timer = Timer(5, count=10)
|
||||||
@@ -76,23 +67,23 @@ class Equipment(StorageHandler):
|
|||||||
def ship_view_prev(self, check_button=EQUIPMENT_OPEN):
|
def ship_view_prev(self, check_button=EQUIPMENT_OPEN):
|
||||||
return self._ship_view_swipe(distance=SWIPE_DISTANCE, check_button=check_button)
|
return self._ship_view_swipe(distance=SWIPE_DISTANCE, check_button=check_button)
|
||||||
|
|
||||||
def ship_info_enter(self, click_button, check_button=EQUIPMENT_OPEN, long_click=True, skil_first_screenshot=True):
|
def ship_info_enter(self, click_button, check_button=EQUIPMENT_OPEN, long_click=True, skip_first_screenshot=True):
|
||||||
enter_timer = Timer(10)
|
enter_timer = Timer(10)
|
||||||
|
|
||||||
while 1:
|
while 1:
|
||||||
if skil_first_screenshot:
|
if skip_first_screenshot:
|
||||||
skil_first_screenshot = False
|
skip_first_screenshot = False
|
||||||
else:
|
else:
|
||||||
self.device.screenshot()
|
self.device.screenshot()
|
||||||
|
|
||||||
# End
|
# End
|
||||||
if self.appear(check_button):
|
if self.appear(check_button, offset=(5, 5)):
|
||||||
break
|
break
|
||||||
|
|
||||||
# Long click accidentally became normal click, exit from dock
|
# Long click accidentally became normal click, exit from dock
|
||||||
if long_click:
|
if long_click:
|
||||||
if self.appear(DOCK_CHECK, offset=(20, 20), interval=3):
|
if self.appear(DOCK_CHECK, offset=(20, 20), interval=3):
|
||||||
logger.info(f'equip_enter {DOCK_CHECK} -> {BACK_ARROW}')
|
logger.info(f'ship_info_enter {DOCK_CHECK} -> {BACK_ARROW}')
|
||||||
self.device.click(BACK_ARROW)
|
self.device.click(BACK_ARROW)
|
||||||
continue
|
continue
|
||||||
if enter_timer.reached():
|
if enter_timer.reached():
|
||||||
@@ -168,120 +159,8 @@ class Equipment(StorageHandler):
|
|||||||
return True
|
return True
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def ship_equipment_take_off(self, skip_first_screenshot=True):
|
def ship_equipment_take_off(self, name=None):
|
||||||
logger.info('Equipment take off')
|
self.code_clear(name=name)
|
||||||
bar_timer = Timer(5)
|
|
||||||
off_timer = Timer(5)
|
|
||||||
confirm_timer = Timer(5)
|
|
||||||
|
|
||||||
while 1:
|
def ship_equipment_take_on(self, name=None):
|
||||||
if skip_first_screenshot:
|
self.code_apply(name=name)
|
||||||
skip_first_screenshot = False
|
|
||||||
else:
|
|
||||||
self.device.screenshot()
|
|
||||||
|
|
||||||
# End
|
|
||||||
# if self.handle_info_bar():
|
|
||||||
# break
|
|
||||||
if off_timer.started() and self.info_bar_count():
|
|
||||||
break
|
|
||||||
|
|
||||||
if self.handle_storage_full():
|
|
||||||
continue
|
|
||||||
|
|
||||||
if confirm_timer.reached() and self.handle_popup_confirm():
|
|
||||||
confirm_timer.reset()
|
|
||||||
off_timer.reset()
|
|
||||||
bar_timer.reset()
|
|
||||||
continue
|
|
||||||
|
|
||||||
if off_timer.reached():
|
|
||||||
if not self.info_bar_count() and self.appear_then_click(EQUIP_OFF, offset=(20, 20)):
|
|
||||||
off_timer.reset()
|
|
||||||
bar_timer.reset()
|
|
||||||
continue
|
|
||||||
|
|
||||||
if bar_timer.reached():
|
|
||||||
if self.appear(EQUIPMENT_OPEN, offset=(20, 20)) and not self.appear(EQUIP_OFF, offset=(20, 20)):
|
|
||||||
self.device.click(EQUIPMENT_OPEN)
|
|
||||||
bar_timer.reset()
|
|
||||||
continue
|
|
||||||
|
|
||||||
logger.info('Equipment take off ended')
|
|
||||||
|
|
||||||
def fleet_equipment_take_off(self, enter, long_click, out):
|
|
||||||
"""
|
|
||||||
Args:
|
|
||||||
enter (Button): Button to edit equipment.
|
|
||||||
long_click (bool): How to click enter
|
|
||||||
out (Button): Button to confirm exit success.
|
|
||||||
"""
|
|
||||||
logger.hr('Equipment take off')
|
|
||||||
self.ship_info_enter(enter, long_click=long_click)
|
|
||||||
|
|
||||||
while True:
|
|
||||||
self.ship_equipment_take_off()
|
|
||||||
self.ui_click(EQUIPMENT_CLOSE, check_button=EQUIPMENT_OPEN, skip_first_screenshot=True)
|
|
||||||
if not self.ship_view_next():
|
|
||||||
break
|
|
||||||
|
|
||||||
self.ui_back(out)
|
|
||||||
self.equipment_has_take_on = False
|
|
||||||
|
|
||||||
def ship_equipment_take_on_preset(self, index, skip_first_screenshot=True):
|
|
||||||
logger.info('Equipment take on preset')
|
|
||||||
bar_timer = Timer(5)
|
|
||||||
on_timer = Timer(5)
|
|
||||||
|
|
||||||
while 1:
|
|
||||||
if skip_first_screenshot:
|
|
||||||
skip_first_screenshot = False
|
|
||||||
else:
|
|
||||||
self.device.screenshot()
|
|
||||||
|
|
||||||
# End
|
|
||||||
# if self.handle_info_bar():
|
|
||||||
# break
|
|
||||||
if on_timer.started() and self.info_bar_count():
|
|
||||||
break
|
|
||||||
|
|
||||||
if bar_timer.reached() and not self.appear(EQUIP_1, offset=10):
|
|
||||||
self.device.click(EQUIPMENT_OPEN)
|
|
||||||
# self.device.sleep(0.3)
|
|
||||||
bar_timer.reset()
|
|
||||||
continue
|
|
||||||
|
|
||||||
if on_timer.reached() and self.appear(EQUIP_1, offset=10) and not self.info_bar_count():
|
|
||||||
if index == 1:
|
|
||||||
self.device.click(EQUIP_1)
|
|
||||||
elif index == 2:
|
|
||||||
self.device.click(EQUIP_2)
|
|
||||||
elif index == 3:
|
|
||||||
self.device.click(EQUIP_3)
|
|
||||||
|
|
||||||
on_timer.reset()
|
|
||||||
bar_timer.reset()
|
|
||||||
continue
|
|
||||||
|
|
||||||
logger.info('Equipment take on ended')
|
|
||||||
|
|
||||||
def fleet_equipment_take_on_preset(self, enter, out, fleet):
|
|
||||||
"""
|
|
||||||
Args:
|
|
||||||
enter (Button): Long click to edit equipment.
|
|
||||||
out (Button): Button to confirm exit success.
|
|
||||||
fleet (list[int]): list of equipment record. [3, 1, 1, 1, 1, 1]
|
|
||||||
"""
|
|
||||||
logger.hr('Equipment take on')
|
|
||||||
self.ship_info_enter(enter)
|
|
||||||
|
|
||||||
for index in '9'.join([str(x) for x in fleet if x > 0]):
|
|
||||||
index = int(index)
|
|
||||||
if index == 9:
|
|
||||||
self.ship_view_next()
|
|
||||||
else:
|
|
||||||
self.ship_equipment_take_on_preset(index=index)
|
|
||||||
self.ui_click(click_button=EQUIPMENT_CLOSE, check_button=EQUIPMENT_OPEN, offset=None)
|
|
||||||
|
|
||||||
self.ui_back(out)
|
|
||||||
self.equipment_has_take_on = True
|
|
||||||
|
|||||||
@@ -1,276 +1,197 @@
|
|||||||
import re
|
|
||||||
import yaml
|
import yaml
|
||||||
|
|
||||||
from module.config.config import AzurLaneConfig
|
|
||||||
from module.equipment.assets import *
|
from module.equipment.assets import *
|
||||||
from module.exception import RequestHumanTakeover
|
|
||||||
from module.logger import logger
|
from module.logger import logger
|
||||||
|
from module.retire.assets import TEMPLATE_BOGUE, TEMPLATE_HERMES, TEMPLATE_RANGER, TEMPLATE_LANGLEY
|
||||||
from module.storage.assets import EQUIPMENT_FULL
|
from module.storage.assets import EQUIPMENT_FULL
|
||||||
from module.storage.storage import StorageHandler
|
from module.storage.storage import StorageHandler
|
||||||
|
|
||||||
|
EMPTY_CODE = "MC8wLzAvMC8wXDA="
|
||||||
BASE64_REGEX = re.compile('^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$')
|
EQUIPMENT_PREVIEW = list([
|
||||||
EMPTY_GEAR_CODE = "MC8wLzAvMC8wXDA="
|
EQUIPMENT_CODE_EQUIP_0,
|
||||||
|
EQUIPMENT_CODE_EQUIP_1,
|
||||||
def is_equip_code(string):
|
EQUIPMENT_CODE_EQUIP_2,
|
||||||
"""
|
EQUIPMENT_CODE_EQUIP_3,
|
||||||
Checks if current string is None or BASE64 string.
|
EQUIPMENT_CODE_EQUIP_4,
|
||||||
"""
|
EQUIPMENT_CODE_EQUIP_5,
|
||||||
if string is None:
|
])
|
||||||
return True
|
|
||||||
if not isinstance(string, str):
|
|
||||||
return False
|
|
||||||
return BASE64_REGEX.match(string)
|
|
||||||
|
|
||||||
|
|
||||||
class EquipmentCode:
|
|
||||||
config: AzurLaneConfig
|
|
||||||
config_key: str
|
|
||||||
coded_ships: list
|
|
||||||
|
|
||||||
def __setattr__(self, key, value):
|
|
||||||
if key in ['config', 'config_key', 'coded_ships']:
|
|
||||||
super().__setattr__(key, value)
|
|
||||||
elif key in self.coded_ships:
|
|
||||||
if is_equip_code(value):
|
|
||||||
super().__setattr__(key, value)
|
|
||||||
else:
|
|
||||||
logger.error(f'{value} is not a gear code, skip setting {key}')
|
|
||||||
else:
|
|
||||||
logger.error(f'{key} is not in coded ships: {self.coded_ships}')
|
|
||||||
|
|
||||||
def __init__(self, config, key, ships):
|
|
||||||
"""
|
|
||||||
Args:
|
|
||||||
config (AzurLaneConfig):
|
|
||||||
key: location of config containing gear code configs
|
|
||||||
ships (list of string): ships whose gear codes should be memorized
|
|
||||||
"""
|
|
||||||
self.config = config
|
|
||||||
self.config_key = key
|
|
||||||
self.coded_ships = ships
|
|
||||||
_config = config.cross_get(keys=key)
|
|
||||||
codes = dict([(ship, None) for ship in self.coded_ships])
|
|
||||||
for line in _config.splitlines():
|
|
||||||
try:
|
|
||||||
codes.update(yaml.safe_load(line))
|
|
||||||
except Exception as e:
|
|
||||||
logger.error(f'Failed to parse current line of the config: "{line}", skipping')
|
|
||||||
for ship in self.coded_ships:
|
|
||||||
code: str = codes.pop(ship, None)
|
|
||||||
self.__setattr__(ship, code)
|
|
||||||
|
|
||||||
def export_to_config(self):
|
|
||||||
"""
|
|
||||||
Export current ships' gear codes to location {self.config_key} of {self.config}.
|
|
||||||
"""
|
|
||||||
_config = {}
|
|
||||||
for ship in self.coded_ships:
|
|
||||||
_config.update({ship: self.__getattribute__(ship)})
|
|
||||||
value = yaml.safe_dump(_config)
|
|
||||||
logger.info(f'Gear code configs to be exported: {value}')
|
|
||||||
self.config.cross_set(keys=self.config_key, value=value)
|
|
||||||
|
|
||||||
|
|
||||||
class EquipmentCodeHandler(StorageHandler):
|
class EquipmentCodeHandler(StorageHandler):
|
||||||
codes: EquipmentCode
|
last_code: str = None
|
||||||
|
|
||||||
def __init__(self, config, key, ships, device=None, task=None):
|
def get_code(self, name):
|
||||||
super().__init__(config, device=device, task=task)
|
try:
|
||||||
self.codes = EquipmentCode(self.config, key=key, ships=ships)
|
config = {}
|
||||||
|
for item in yaml.safe_load_all(self.config.GemsFarming_EquipmentCode):
|
||||||
|
config.update(item)
|
||||||
|
except Exception:
|
||||||
|
logger.error("Fail to load equipment code config")
|
||||||
|
return None
|
||||||
|
try:
|
||||||
|
name: str = config.pop(name)
|
||||||
|
return name
|
||||||
|
except Exception:
|
||||||
|
logger.error(f"Config does not contain equipment code for {name}")
|
||||||
|
return None
|
||||||
|
|
||||||
def enter_equip_code_page(self, skip_first_screenshot=True):
|
def set_code(self, name, code):
|
||||||
|
config = {}
|
||||||
|
try:
|
||||||
|
for item in yaml.safe_load_all(self.config.GemsFarming_EquipmentCode):
|
||||||
|
config.update(item)
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
|
try:
|
||||||
|
config.update({name: code})
|
||||||
|
config_yaml = yaml.safe_dump(config)
|
||||||
|
self.config.GemsFarming_EquipmentCode = config_yaml
|
||||||
|
except Exception:
|
||||||
|
logger.error("Fail to set equipment code config")
|
||||||
|
|
||||||
|
def current_ship(self):
|
||||||
|
"""
|
||||||
|
Currently, only supports common CV recognization
|
||||||
|
|
||||||
|
Pages:
|
||||||
|
in: equipment_code
|
||||||
|
"""
|
||||||
|
for _ in self.loop():
|
||||||
|
if not self.appear(EMPTY_SHIP_R):
|
||||||
|
break
|
||||||
|
if TEMPLATE_BOGUE.match(self.device.image, scaling=1.46): # image has rotation
|
||||||
|
return 'bogue'
|
||||||
|
elif TEMPLATE_HERMES.match(self.device.image, scaling=124 / 89):
|
||||||
|
return 'hermes'
|
||||||
|
elif TEMPLATE_RANGER.match(self.device.image, scaling=4 / 3):
|
||||||
|
return 'ranger'
|
||||||
|
elif TEMPLATE_LANGLEY.match(self.device.image, scaling=25 / 21):
|
||||||
|
return 'langley'
|
||||||
|
else:
|
||||||
|
return 'DD'
|
||||||
|
|
||||||
|
def _code_enter(self):
|
||||||
"""
|
"""
|
||||||
Pages:
|
Pages:
|
||||||
in: ship_detail
|
in: ship_detail
|
||||||
out: gear_code
|
out: equipment_code
|
||||||
"""
|
"""
|
||||||
while 1:
|
for _ in self.loop():
|
||||||
if skip_first_screenshot:
|
|
||||||
skip_first_screenshot = False
|
|
||||||
else:
|
|
||||||
self.device.screenshot()
|
|
||||||
|
|
||||||
# End
|
|
||||||
if self.appear(EQUIPMENT_CODE_PAGE_CHECK, offset=(5, 5)):
|
if self.appear(EQUIPMENT_CODE_PAGE_CHECK, offset=(5, 5)):
|
||||||
break
|
break
|
||||||
|
|
||||||
if self.appear_then_click(EQUIPMENT_CODE_ENTRANCE, offset=(5, 5), interval=2):
|
if self.appear_then_click(EQUIPMENT_CODE_ENTRANCE, offset=(5, 5), interval=2):
|
||||||
continue
|
continue
|
||||||
|
|
||||||
# def exit_equip_code_page(self):
|
def _code_exit(self):
|
||||||
# """
|
|
||||||
# Pages:
|
|
||||||
# in: gear_code
|
|
||||||
# out: ship_detail
|
|
||||||
# """
|
|
||||||
# self.ui_back(check_button=EQUIPMENT_CODE_ENTRANCE)
|
|
||||||
|
|
||||||
def current_ship(self):
|
|
||||||
# Will be overridden in subclasses.
|
|
||||||
pass
|
|
||||||
|
|
||||||
def click_export_button(self, skip_first_screenshot=True):
|
|
||||||
self.handle_info_bar()
|
|
||||||
while 1:
|
|
||||||
if skip_first_screenshot:
|
|
||||||
skip_first_screenshot = False
|
|
||||||
else:
|
|
||||||
self.device.screenshot()
|
|
||||||
|
|
||||||
# End
|
|
||||||
if self.info_bar_count():
|
|
||||||
break
|
|
||||||
|
|
||||||
if self.appear_then_click(EQUIPMENT_CODE_EXPORT, offset=(5, 5), interval=1):
|
|
||||||
continue
|
|
||||||
|
|
||||||
def export_equip_code(self, ship=None):
|
|
||||||
"""
|
"""
|
||||||
Export current ship's gear code to config file.
|
Pages:
|
||||||
This is done by first using "export" button
|
in: equipment_code
|
||||||
to export gear code to clipboard,
|
out: ship_detail
|
||||||
then update the config file using yaml.safe_dump().
|
|
||||||
"""
|
"""
|
||||||
code = self.device.clipboard
|
self.ui_back(check_button=EQUIPMENT_CODE_ENTRANCE)
|
||||||
if code == EMPTY_GEAR_CODE:
|
|
||||||
logger.info('Detect 0/0/0/0/0\\0 code, continue exporting.')
|
|
||||||
logger.attr("Gear code", code)
|
|
||||||
if not ship in self.codes.coded_ships:
|
|
||||||
ship = self.current_ship()
|
|
||||||
logger.attr("Current ship", ship)
|
|
||||||
logger.info(f'Set gear code of {ship} to be {code}')
|
|
||||||
self.codes.__setattr__(ship, code)
|
|
||||||
self.codes.export_to_config()
|
|
||||||
|
|
||||||
def equip_preview_empty(self):
|
def is_code_preview_loaded(self):
|
||||||
if self.appear(EQUIPMENT_CODE_EQUIP_5_LOCKED):
|
if self.appear(EQUIPMENT_CODE_EQUIP_5_LOCKED, offset=(5, 5)):
|
||||||
max_index = 5
|
max_index = 5
|
||||||
else:
|
else:
|
||||||
max_index = 6
|
max_index = 6
|
||||||
for index in range(max_index):
|
for index in range(max_index):
|
||||||
if not self.appear(globals()['EQUIPMENT_CODE_EQUIP_{index}'.format(index=index)], offset=(5, 5)):
|
if not self.appear(EQUIPMENT_PREVIEW[index], offset=(5, 5)):
|
||||||
return False
|
|
||||||
|
|
||||||
return True
|
|
||||||
|
|
||||||
def clear_equip_preview(self, skip_first_screenshot=True):
|
|
||||||
while 1:
|
|
||||||
if skip_first_screenshot:
|
|
||||||
skip_first_screenshot = False
|
|
||||||
else:
|
|
||||||
self.device.screenshot()
|
|
||||||
|
|
||||||
# End
|
|
||||||
if self.equip_preview_empty():
|
|
||||||
logger.info('Confirm equipment preview cleared.')
|
|
||||||
break
|
|
||||||
|
|
||||||
if self.appear_then_click(EQUIPMENT_CODE_CLEAR, offset=(5, 5), interval=2):
|
|
||||||
continue
|
|
||||||
|
|
||||||
def enter_equip_code_input_mode(self, skip_first_screenshot=True):
|
|
||||||
while 1:
|
|
||||||
if skip_first_screenshot:
|
|
||||||
skip_first_screenshot = False
|
|
||||||
else:
|
|
||||||
self.device.screenshot()
|
|
||||||
|
|
||||||
if self.appear(EQUIPMENT_CODE_ENTER, offset=(5, 5), interval=2):
|
|
||||||
self.device.click(EQUIPMENT_CODE_TEXTBOX)
|
|
||||||
continue
|
|
||||||
|
|
||||||
# End
|
|
||||||
if self.device.ime_shown():
|
|
||||||
break
|
|
||||||
|
|
||||||
def confirm_equip_code(self, skip_first_screenshot=False):
|
|
||||||
check_counter = 0
|
|
||||||
while 1:
|
|
||||||
if skip_first_screenshot:
|
|
||||||
skip_first_screenshot = False
|
|
||||||
else:
|
|
||||||
self.device.screenshot()
|
|
||||||
|
|
||||||
if self.appear_then_click(EQUIPMENT_CODE_ENTER, offset=(5, 5), interval=1):
|
|
||||||
continue
|
|
||||||
|
|
||||||
# End
|
|
||||||
if not self.equip_preview_empty():
|
|
||||||
logger.info('Confirm gear code loaded.')
|
|
||||||
return True
|
return True
|
||||||
else:
|
|
||||||
check_counter += 1
|
|
||||||
if check_counter >= 5:
|
|
||||||
logger.error('Gear code load failed, retrying.')
|
|
||||||
return False
|
|
||||||
|
|
||||||
def confirm_equip_preview(self, skip_first_screenshot=True):
|
return False
|
||||||
while 1:
|
|
||||||
if skip_first_screenshot:
|
|
||||||
skip_first_screenshot = False
|
|
||||||
else:
|
|
||||||
self.device.screenshot()
|
|
||||||
|
|
||||||
if self.appear_then_click(EQUIPMENT_CODE_CONFIRM, offset=(5, 5), interval=5):
|
def _code_preview_clear(self):
|
||||||
|
for _ in self.loop(timeout=2):
|
||||||
|
if not self.is_code_preview_loaded():
|
||||||
|
return True
|
||||||
|
|
||||||
|
if self.appear_then_click(EQUIPMENT_CODE_CLEAR, offset=(5, 5)):
|
||||||
continue
|
continue
|
||||||
|
else:
|
||||||
|
return False
|
||||||
|
|
||||||
if self.handle_popup_confirm('EQUIPMENT_CODE'):
|
def _code_input(self, code):
|
||||||
|
logger.info(f"Code input: {code}")
|
||||||
|
d = self.device.u2
|
||||||
|
for _ in self.loop(timeout=10):
|
||||||
|
_, shown = d.current_ime()
|
||||||
|
if shown:
|
||||||
|
break
|
||||||
|
self.device.click(EQUIPMENT_CODE_TEXTBOX)
|
||||||
|
else:
|
||||||
|
logger.warning("Equipment code load failed")
|
||||||
|
return False
|
||||||
|
d.send_keys(text=code, clear=True)
|
||||||
|
d.send_action(code="done")
|
||||||
|
self.device.sleep((0.3, 0.5))
|
||||||
|
for _ in self.loop(timeout=10, skip_first=False):
|
||||||
|
_, shown = d.current_ime()
|
||||||
|
if shown:
|
||||||
continue
|
continue
|
||||||
|
if self.is_code_preview_loaded():
|
||||||
|
return True
|
||||||
|
if self.appear_then_click(EQUIPMENT_CODE_ENTER, offset=(5, 5), interval=3):
|
||||||
|
continue
|
||||||
|
else:
|
||||||
|
logger.warning("Equipment code load failed")
|
||||||
|
return False
|
||||||
|
|
||||||
# End
|
def _code_confirm(self):
|
||||||
|
logger.info("Code apply")
|
||||||
|
for _ in self.loop(timeout=10):
|
||||||
if self.appear(EQUIPMENT_CODE_ENTRANCE, offset=(5, 5)):
|
if self.appear(EQUIPMENT_CODE_ENTRANCE, offset=(5, 5)):
|
||||||
return True
|
return True
|
||||||
if self.appear(EQUIPMENT_FULL, offset=(30, 30)):
|
if self.appear(EQUIPMENT_FULL, offset=(30, 30)):
|
||||||
return False
|
return False
|
||||||
|
if self.handle_popup_confirm("EQUIPMENT_CODE"):
|
||||||
def clear_all_equip(self):
|
continue
|
||||||
self.enter_equip_code_page()
|
if self.appear_then_click(EQUIPMENT_CODE_CONFIRM, offset=(5, 5), interval=3):
|
||||||
ship = self.current_ship()
|
continue
|
||||||
self.device.u2_set_fastinput_ime(True)
|
|
||||||
logger.attr("Current_ime", self.device.u2_current_ime())
|
|
||||||
if self.codes.__getattribute__(ship) is None:
|
|
||||||
self.click_export_button()
|
|
||||||
self.export_equip_code(ship)
|
|
||||||
self.clear_equip_preview()
|
|
||||||
for _ in range(5):
|
|
||||||
success = self.confirm_equip_preview()
|
|
||||||
if success:
|
|
||||||
return True
|
|
||||||
else:
|
|
||||||
self.handle_storage_full()
|
|
||||||
self.clear_equip_preview()
|
|
||||||
|
|
||||||
raise RequestHumanTakeover(
|
|
||||||
f'Failed to clear all equipment for {ship}, please check manually.'
|
|
||||||
)
|
|
||||||
|
|
||||||
def apply_equip_code(self, code=None):
|
|
||||||
self.enter_equip_code_page()
|
|
||||||
self.clear_equip_preview()
|
|
||||||
if code is None:
|
|
||||||
ship = self.current_ship()
|
|
||||||
code = self.codes.__getattribute__(ship)
|
|
||||||
if code is None:
|
|
||||||
code = self.device.clipboard # assuming clipboard is not modified
|
|
||||||
logger.info(f'Apply gear code {code} for {ship}')
|
|
||||||
else:
|
else:
|
||||||
logger.info(f'Forcefully apply gear code {code} to current ship.')
|
return False
|
||||||
|
|
||||||
|
def _code_apply(self, code=None):
|
||||||
for _ in range(5):
|
for _ in range(5):
|
||||||
if code is not None and code != EMPTY_GEAR_CODE:
|
self._code_preview_clear()
|
||||||
self.enter_equip_code_input_mode()
|
if code is not None and code != EMPTY_CODE:
|
||||||
self.device.text_input_and_confirm(code, clear=True)
|
success = self._code_input(code)
|
||||||
success = self.confirm_equip_code()
|
|
||||||
if not success:
|
if not success:
|
||||||
continue
|
continue
|
||||||
success = self.confirm_equip_preview()
|
success = self._code_confirm()
|
||||||
if success:
|
if success:
|
||||||
logger.info("Gear code import complete.")
|
logger.info("Equipment code apply complete.")
|
||||||
return True
|
return True
|
||||||
else:
|
else:
|
||||||
self.handle_storage_full()
|
self.handle_storage_full()
|
||||||
self.clear_equip_preview()
|
else:
|
||||||
|
return False
|
||||||
|
|
||||||
raise RequestHumanTakeover(
|
def _code_export(self):
|
||||||
f'Failed to apply equipment for {ship}, please check manually.'
|
self.handle_info_bar()
|
||||||
)
|
d = self.device.u2
|
||||||
|
for _ in self.loop(timeout=10):
|
||||||
|
if self.info_bar_count():
|
||||||
|
break
|
||||||
|
if self.appear_then_click(EQUIPMENT_CODE_EXPORT, offset=(5, 5), interval=3):
|
||||||
|
continue
|
||||||
|
code = d.clipboard
|
||||||
|
return code
|
||||||
|
|
||||||
|
def code_clear(self, name=None):
|
||||||
|
self._code_enter()
|
||||||
|
if name is None:
|
||||||
|
name = self.current_ship()
|
||||||
|
if self.get_code(name=name) is None:
|
||||||
|
self.last_code = self._code_export()
|
||||||
|
self.set_code(name=name, code=self.last_code)
|
||||||
|
self._code_apply(code=None)
|
||||||
|
|
||||||
|
def code_apply(self, name=None):
|
||||||
|
self._code_enter()
|
||||||
|
if name is None:
|
||||||
|
name = self.current_ship()
|
||||||
|
code = self.get_code(name=name)
|
||||||
|
if code is None:
|
||||||
|
code = self.last_code
|
||||||
|
self._code_apply(code=code)
|
||||||
|
|||||||
@@ -219,6 +219,11 @@ class Dock(Equipment):
|
|||||||
self.dock_filter.set(sort=sort, index=index, faction=faction, rarity=rarity, extra=extra)
|
self.dock_filter.set(sort=sort, index=index, faction=faction, rarity=rarity, extra=extra)
|
||||||
self.dock_filter_confirm(wait_loading=wait_loading)
|
self.dock_filter_confirm(wait_loading=wait_loading)
|
||||||
|
|
||||||
|
def dock_reset(self):
|
||||||
|
self.dock_favourite_set(False, wait_loading=False)
|
||||||
|
self.dock_sort_method_dsc_set(wait_loading=False)
|
||||||
|
self.dock_filter_set()
|
||||||
|
|
||||||
def dock_select_one(self, button, skip_first_screenshot=True):
|
def dock_select_one(self, button, skip_first_screenshot=True):
|
||||||
"""
|
"""
|
||||||
Args:
|
Args:
|
||||||
|
|||||||
Reference in New Issue
Block a user