Refactor: More accurate exceptions and add friendly advices

This commit is contained in:
LmeSzinc 2021-09-16 12:09:00 +08:00
parent 5dd0459de9
commit 61cbe75527
22 changed files with 474 additions and 142 deletions

77
alas.py
View File

@ -1,4 +1,7 @@
import os
import re
import time
from datetime import datetime
import inflection
from cached_property import cached_property
@ -11,7 +14,8 @@ from module.config.db import Database
from module.device.device import Device
from module.exception import *
from module.handler.login import LoginHandler
from module.logger import logger
from module.handler.sensitive_info import handle_sensitive_image, handle_sensitive_logs
from module.logger import logger, log_file
from module.research.research import RewardResearch
from module.tactical.tactical_class import RewardTacticalClass
from module.ui.ui import UI, page_main
@ -33,7 +37,6 @@ class AzurLaneAutoScript:
return device
def run(self, command):
while 1:
try:
self.__getattribute__(command)()
UI(config=self.config, device=self.device).ui_ensure(page_main)
@ -42,30 +45,29 @@ class AzurLaneAutoScript:
return True
except GameNotRunningError as e:
logger.warning(e)
az = LoginHandler(self.config, device=self.device)
az.app_restart()
az.ensure_no_unfinished_campaign()
continue
except GameTooManyClickError as e:
self.config.task_call('Restart')
return True
except (GameStuckError, GameTooManyClickError) as e:
logger.warning(e)
self.save_error_log()
az = LoginHandler(self.config, device=self.device)
az.handle_game_stuck()
continue
except GameStuckError as e:
logger.warning(e)
self.save_error_log()
az = LoginHandler(self.config, device=self.device)
az.handle_game_stuck()
continue
logger.warning(f'Game stuck, {self.config.Emulator_PackageName} will be restarted in 10 seconds')
logger.warning('If you are playing by hand, please stop Alas')
self.config.task_call('Restart')
self.device.sleep(10)
return False
except LogisticsRefreshBugHandler as e:
logger.warning(e)
self.save_error_log()
az = LoginHandler(self.config, device=self.device)
az.device.app_stop()
time.sleep(600)
az.app_ensure_start()
continue
self.config.task_call('Restart')
self.device.sleep(10)
return False
except ScriptError as e:
logger.critical(e)
logger.critical('This is likely to be a mistake of developers, but sometimes just random issues')
exit(1)
except RequestHumanTakeover:
logger.critical('Request human takeover')
exit(1)
except Exception as e:
logger.exception(e)
self.save_error_log()
@ -76,7 +78,27 @@ class AzurLaneAutoScript:
Save last 60 screenshots in ./log/error/<timestamp>
Save logs to ./log/error/<timestamp>/log.txt
"""
pass
if self.config.Error_SaveError:
folder = f'./log/error/{int(time.time() * 1000)}'
logger.warning(f'Saving error: {folder}')
os.mkdir(folder)
for data in self.device.screenshot_deque:
image_time = datetime.strftime(data['time'], '%Y-%m-%d_%H-%M-%S-%f')
image = handle_sensitive_image(data['image'])
image.save(f'{folder}/{image_time}.png')
with open(log_file, 'r', encoding='utf-8') as f:
lines = f.readlines()
start = 0
for index, line in enumerate(lines):
if re.search('\+-{15,}\+', line):
start = index
lines = lines[start - 2:]
lines = handle_sensitive_logs(lines)
with open(f'{folder}/log.txt', 'w', encoding='utf-8') as f:
f.writelines(lines)
def restart(self):
LoginHandler(self.config, device=self.device).app_restart()
def research(self):
RewardResearch(config=self.config, device=self.device).run()
@ -102,12 +124,19 @@ class AzurLaneAutoScript:
def loop(self):
while 1:
logger.info(f'Scheduler: Start task `{self.config.task}`')
logger.hr(self.config.task, level=0)
success = self.run(inflection.underscore(self.config.task))
logger.info(f'Scheduler: End task `{self.config.task}`')
del self.__dict__['config']
if not success:
if success:
del self.__dict__['config']
continue
elif self.config.Error_HandleError:
# self.config.task_delay(success=False)
del self.__dict__['config']
continue
else:
break

View File

@ -1,6 +1,6 @@
from module.base.button import Button
from module.base.utils import area_offset, get_color, random_rectangle_vector
from module.base.utils import random_rectangle_vector
from module.campaign.campaign_base import CampaignBase as CampaignBase_
from module.exception import RequestHumanTakeover
from module.logger import logger
from module.ui.assets import WAR_ARCHIVES_CHECK
from module.ui.page import page_archives
@ -90,10 +90,9 @@ class CampaignBase(CampaignBase_):
skip_first_screenshot=True)
self.handle_stage_icon_spawn()
else:
logger.warning(
'Respective server may not yet support the chosen War Archives campaign, check back in the next '
'app update')
exit(1)
logger.critical('Respective server may not yet support the chosen War Archives campaign, '
'check back in the next app update')
raise RequestHumanTakeover
# Subsequent runs all set False
if self.first_run:

View File

@ -44,6 +44,14 @@ General:
OldRetireR: true
OldRetireSR: false
OldRetireSSR: false
Restart:
Scheduler:
Enable: false
NextRun: 2020-01-01 00:00:00
Command: Restart
SuccessInterval: 0
FailureInterval: 0
ServerUpdate: 00:00
Main:
Scheduler:
Enable: main

View File

@ -5,6 +5,7 @@ import os
from module.campaign.assets import *
from module.campaign.campaign_base import CampaignBase
from module.config.config import AzurLaneConfig
from module.exception import RequestHumanTakeover
from module.exception import ScriptEnd
from module.logger import logger
from module.ocr.ocr import Digit
@ -53,7 +54,11 @@ class CampaignRun(UI):
else:
files = [f[:-3] for f in os.listdir(folder) if f[-3:] == '.py']
logger.warning(f'Existing files: {files}')
exit(1)
logger.critical('Please update Alas')
logger.critical('If file is still missing after update, '
'contact developers, or make map files yourself using dev_tools/map_extractor.py')
raise RequestHumanTakeover
config = copy.copy(self.config).merge(self.module.Config())
device = self.device

View File

@ -56,6 +56,16 @@ General:
OldRetireR: true
OldRetireSR: false
OldRetireSSR: false
Restart:
_info:
Menu: Alas
Scheduler:
Enable: false
NextRun: 2020-01-01 00:00:00
Command: Restart
SuccessInterval: 0
FailureInterval: 0
ServerUpdate: 00:00
Main:
_info:
Menu: Main

View File

@ -8,6 +8,7 @@ from module.base.utils import ensure_time
from module.config.config_generated import GeneratedConfig
from module.config.config_manual import ManualConfig
from module.config.utils import *
from module.exception import RequestHumanTakeover, ScriptError
from module.logger import logger
@ -123,8 +124,9 @@ class AzurLaneConfig(ManualConfig, GeneratedConfig):
time.sleep(waiting.next_run.timestamp() - datetime.now().timestamp() + 1)
return self.get_next()
else:
logger.warning('No task waiting or pending')
exit(1)
logger.critical('No task waiting or pending')
logger.critical('Please enable at least one task')
raise RequestHumanTakeover
def save(self):
if not self.modified:
@ -187,7 +189,7 @@ class AzurLaneConfig(ManualConfig, GeneratedConfig):
logger.info(f'Delay task `{self.task}` to {run} ({kv})')
self.Scheduler_NextRun = run
else:
logger.warning('Missing argument in delay_next_run, should set at least one')
raise ScriptError('Missing argument in delay_next_run, should set at least one')
def task_call(self, task):
"""
@ -203,9 +205,12 @@ class AzurLaneConfig(ManualConfig, GeneratedConfig):
"""
path = f'{task}.Scheduler.NextRun'
if deep_get(self.data, keys=path, default=None) is None:
logger.warning(f'Task to call: `{task}` does not exist in user config')
raise ScriptError(f'Task to call: `{task}` does not exist in user config')
else:
self.modified[path] = datetime.now().replace(microsecond=0)
if task == 'Restart':
# Restart is forced to enable
self.modified[f'{task}.Scheduler.Enable'] = True
self.update()
def task_stop(self, message=''):

View File

@ -44,6 +44,8 @@ class GeneratedConfig:
Retirement_OldRetireSR = False
Retirement_OldRetireSSR = False
# Func `Restart`
# Func `Main`
Campaign_Name = '7-2'
Campaign_Event = 'campaign_main'

View File

@ -489,6 +489,96 @@ type: input
value: false
option: {}
---
func: Restart
group: _info
arg: _info
lang: en-US
name: Restart._info._info.name
help: Restart._info._info.help
type: ''
value: ''
option: {}
---
func: Restart
group: _info
arg: Menu
lang: en-US
name: Restart._info.Menu.name
help: Restart._info.Menu.help
type: input
value: Alas
option: {}
---
func: Restart
group: Scheduler
arg: _info
lang: en-US
name: Restart.Scheduler._info.name
help: Restart.Scheduler._info.help
type: ''
value: ''
option: {}
---
func: Restart
group: Scheduler
arg: Enable
lang: en-US
name: Restart.Scheduler.Enable.name
help: Restart.Scheduler.Enable.help
type: input
value: false
option: {}
---
func: Restart
group: Scheduler
arg: NextRun
lang: en-US
name: Restart.Scheduler.NextRun.name
help: Restart.Scheduler.NextRun.help
type: input
value: 2020-01-01 00:00:00
option: {}
---
func: Restart
group: Scheduler
arg: Command
lang: en-US
name: Restart.Scheduler.Command.name
help: Restart.Scheduler.Command.help
type: input
value: Restart
option: {}
---
func: Restart
group: Scheduler
arg: SuccessInterval
lang: en-US
name: Restart.Scheduler.SuccessInterval.name
help: Restart.Scheduler.SuccessInterval.help
type: input
value: 0
option: {}
---
func: Restart
group: Scheduler
arg: FailureInterval
lang: en-US
name: Restart.Scheduler.FailureInterval.name
help: Restart.Scheduler.FailureInterval.help
type: input
value: 0
option: {}
---
func: Restart
group: Scheduler
arg: ServerUpdate
lang: en-US
name: Restart.Scheduler.ServerUpdate.name
help: Restart.Scheduler.ServerUpdate.help
type: input
value: 00:00
option: {}
---
func: Main
group: _info
arg: _info
@ -1611,7 +1701,7 @@ lang: en-US
name: GemsFarming.Fleet.FleetOrder.name
help: GemsFarming.Fleet.FleetOrder.help
type: input
value: fleet1_mob_fleet2_boss
value: fleet1_all_fleet2_standby
option:
fleet1_mob_fleet2_boss: fleet1_mob_fleet2_boss
fleet1_all_fleet2_standby: fleet1_all_fleet2_standby
@ -1623,7 +1713,7 @@ lang: en-US
name: GemsFarming.Fleet.AutoSearchFleetOrder.name
help: GemsFarming.Fleet.AutoSearchFleetOrder.help
type: input
value: fleet1_mob_fleet2_boss
value: fleet1_all_fleet2_standby
option:
fleet1_mob_fleet2_boss: fleet1_mob_fleet2_boss
fleet1_boss_fleet2_mob: fleet1_boss_fleet2_mob

View File

@ -489,6 +489,96 @@ type: input
value: false
option: {}
---
func: Restart
group: _info
arg: _info
lang: zh-CN
name: Restart._info._info.name
help: Restart._info._info.help
type: ''
value: ''
option: {}
---
func: Restart
group: _info
arg: Menu
lang: zh-CN
name: Restart._info.Menu.name
help: Restart._info.Menu.help
type: input
value: Alas
option: {}
---
func: Restart
group: Scheduler
arg: _info
lang: zh-CN
name: Restart.Scheduler._info.name
help: Restart.Scheduler._info.help
type: ''
value: ''
option: {}
---
func: Restart
group: Scheduler
arg: Enable
lang: zh-CN
name: Restart.Scheduler.Enable.name
help: Restart.Scheduler.Enable.help
type: input
value: false
option: {}
---
func: Restart
group: Scheduler
arg: NextRun
lang: zh-CN
name: Restart.Scheduler.NextRun.name
help: Restart.Scheduler.NextRun.help
type: input
value: 2020-01-01 00:00:00
option: {}
---
func: Restart
group: Scheduler
arg: Command
lang: zh-CN
name: Restart.Scheduler.Command.name
help: Restart.Scheduler.Command.help
type: input
value: Restart
option: {}
---
func: Restart
group: Scheduler
arg: SuccessInterval
lang: zh-CN
name: Restart.Scheduler.SuccessInterval.name
help: Restart.Scheduler.SuccessInterval.help
type: input
value: 0
option: {}
---
func: Restart
group: Scheduler
arg: FailureInterval
lang: zh-CN
name: Restart.Scheduler.FailureInterval.name
help: Restart.Scheduler.FailureInterval.help
type: input
value: 0
option: {}
---
func: Restart
group: Scheduler
arg: ServerUpdate
lang: zh-CN
name: Restart.Scheduler.ServerUpdate.name
help: Restart.Scheduler.ServerUpdate.help
type: input
value: 00:00
option: {}
---
func: Main
group: _info
arg: _info
@ -1611,7 +1701,7 @@ lang: zh-CN
name: GemsFarming.Fleet.FleetOrder.name
help: GemsFarming.Fleet.FleetOrder.help
type: input
value: fleet1_mob_fleet2_boss
value: fleet1_all_fleet2_standby
option:
fleet1_mob_fleet2_boss: fleet1_mob_fleet2_boss
fleet1_all_fleet2_standby: fleet1_all_fleet2_standby
@ -1623,7 +1713,7 @@ lang: zh-CN
name: GemsFarming.Fleet.AutoSearchFleetOrder.name
help: GemsFarming.Fleet.AutoSearchFleetOrder.help
type: input
value: fleet1_mob_fleet2_boss
value: fleet1_all_fleet2_standby
option:
fleet1_mob_fleet2_boss: fleet1_mob_fleet2_boss
fleet1_boss_fleet2_mob: fleet1_boss_fleet2_mob

View File

@ -489,6 +489,96 @@ type: input
value: false
option: {}
---
func: Restart
group: _info
arg: _info
lang: zh-TW
name: Restart._info._info.name
help: Restart._info._info.help
type: ''
value: ''
option: {}
---
func: Restart
group: _info
arg: Menu
lang: zh-TW
name: Restart._info.Menu.name
help: Restart._info.Menu.help
type: input
value: Alas
option: {}
---
func: Restart
group: Scheduler
arg: _info
lang: zh-TW
name: Restart.Scheduler._info.name
help: Restart.Scheduler._info.help
type: ''
value: ''
option: {}
---
func: Restart
group: Scheduler
arg: Enable
lang: zh-TW
name: Restart.Scheduler.Enable.name
help: Restart.Scheduler.Enable.help
type: input
value: false
option: {}
---
func: Restart
group: Scheduler
arg: NextRun
lang: zh-TW
name: Restart.Scheduler.NextRun.name
help: Restart.Scheduler.NextRun.help
type: input
value: 2020-01-01 00:00:00
option: {}
---
func: Restart
group: Scheduler
arg: Command
lang: zh-TW
name: Restart.Scheduler.Command.name
help: Restart.Scheduler.Command.help
type: input
value: Restart
option: {}
---
func: Restart
group: Scheduler
arg: SuccessInterval
lang: zh-TW
name: Restart.Scheduler.SuccessInterval.name
help: Restart.Scheduler.SuccessInterval.help
type: input
value: 0
option: {}
---
func: Restart
group: Scheduler
arg: FailureInterval
lang: zh-TW
name: Restart.Scheduler.FailureInterval.name
help: Restart.Scheduler.FailureInterval.help
type: input
value: 0
option: {}
---
func: Restart
group: Scheduler
arg: ServerUpdate
lang: zh-TW
name: Restart.Scheduler.ServerUpdate.name
help: Restart.Scheduler.ServerUpdate.help
type: input
value: 00:00
option: {}
---
func: Main
group: _info
arg: _info
@ -1611,7 +1701,7 @@ lang: zh-TW
name: GemsFarming.Fleet.FleetOrder.name
help: GemsFarming.Fleet.FleetOrder.help
type: input
value: fleet1_mob_fleet2_boss
value: fleet1_all_fleet2_standby
option:
fleet1_mob_fleet2_boss: fleet1_mob_fleet2_boss
fleet1_all_fleet2_standby: fleet1_all_fleet2_standby
@ -1623,7 +1713,7 @@ lang: zh-TW
name: GemsFarming.Fleet.AutoSearchFleetOrder.name
help: GemsFarming.Fleet.AutoSearchFleetOrder.help
type: input
value: fleet1_mob_fleet2_boss
value: fleet1_all_fleet2_standby
option:
fleet1_mob_fleet2_boss: fleet1_mob_fleet2_boss
fleet1_boss_fleet2_mob: fleet1_boss_fleet2_mob

View File

@ -1,5 +1,7 @@
from module.device.connection import Connection
from module.logger import logger
from uiautomator2.exceptions import BaseError
from module.exception import RequestHumanTakeover
class AppControl(Connection):
@ -12,8 +14,16 @@ class AppControl(Connection):
def app_stop(self):
logger.info(f'App stop: {self.config.Emulator_PackageName}')
try:
self.device.app_stop(self.config.Emulator_PackageName)
except BaseError as e:
logger.critical(e)
raise RequestHumanTakeover
def app_start(self):
logger.info(f'App start: {self.config.Emulator_PackageName}')
try:
self.device.app_start(self.config.Emulator_PackageName)
except BaseError as e:
logger.critical(e)
raise RequestHumanTakeover

View File

@ -6,6 +6,7 @@ import numpy as np
from PIL import Image
from module.device.connection import Connection
from module.exception import RequestHumanTakeover
from module.logger import logger
@ -25,9 +26,9 @@ class AScreenCap(Connection):
filepath = os.path.join(self.config.ASCREENCAP_FILEPATH_LOCAL, arc, 'ascreencap')
if int(sdk) not in range(21, 26) or not os.path.exists(filepath):
logger.warning('No suitable version of aScreenCap lib is available')
logger.info('Please use ADB or uiautomator2 screenshot instead')
exit(1)
logger.critical('No suitable version of aScreenCap lib available for this device')
logger.critical('Please use ADB or uiautomator2 for screenshots instead')
raise RequestHumanTakeover
logger.info(f'pushing {filepath}')
self.adb_push([filepath, self.config.ASCREENCAP_FILEPATH_REMOTE])

View File

@ -44,11 +44,11 @@ class Control(MiniTouch):
count = sorted(count.items(), key=lambda item: item[1])
if count[0][1] >= 12:
logger.warning(f'Too many click for a button: {count[0][0]}')
logger.info(f'History click: {[str(prev) for prev in self.click_record]}')
logger.warning(f'History click: {[str(prev) for prev in self.click_record]}')
raise GameTooManyClickError(f'Too many click for a button: {count[0][0]}')
if len(count) >= 2 and count[0][1] >= 6 and count[1][1] >= 6:
logger.warning(f'Too many click between 2 buttons: {count[0][0]}, {count[1][0]}')
logger.info(f'History click: {[str(prev) for prev in self.click_record]}')
logger.warning(f'History click: {[str(prev) for prev in self.click_record]}')
raise GameTooManyClickError(f'Too many click between 2 buttons: {count[0][0]}, {count[1][0]}')
return False

View File

@ -1,15 +1,14 @@
from datetime import datetime, timedelta
from datetime import datetime
from module.base.timer import Timer
from module.base.utils import get_color
from module.config.utils import get_server_next_update
from module.device.app import AppControl
from module.device.control import Control
from module.device.screenshot import Screenshot
from module.exception import GameStuckError
from module.exception import GameStuckError, RequestHumanTakeover
from module.handler.assets import GET_MISSION
from module.logger import logger
from module.config.utils import get_server_next_update
import sys
class Device(Screenshot, Control, AppControl):
@ -17,17 +16,18 @@ class Device(Screenshot, Control, AppControl):
stuck_record = set()
stuck_timer = Timer(60, count=60).start()
stuck_timer_long = Timer(300, count=300).start()
stuck_long_wait_list = ['BATTLE_STATUS_S', 'PAUSE']
stuck_long_wait_list = ['BATTLE_STATUS_S', 'PAUSE', 'LOGIN_CHECK']
def send_notification(self, title, message):
if self.config.ENABLE_NOTIFICATIONS and sys.platform == 'win32':
from notifypy import Notify
notification = Notify()
notification.title = title
notification.message = message
notification.application_name = "AzurLaneAutoScript"
notification.icon = "assets/gooey/icon.ico"
notification.send(block=False)
# if self.config.ENABLE_NOTIFICATIONS and sys.platform == 'win32':
# from notifypy import Notify
# notification = Notify()
# notification.title = title
# notification.message = message
# notification.application_name = "AzurLaneAutoScript"
# notification.icon = "assets/gooey/icon.ico"
# notification.send(block=False)
pass
def handle_night_commission(self, daily_trigger='21:00', threshold=30):
"""
@ -79,21 +79,20 @@ class Device(Screenshot, Control, AppControl):
# Check screen size
width, height = self.image.size
logger.attr('Screen_size', f'{width}x{height}')
if width == 1280 and height == 720:
return True
else:
logger.warning(f'Not supported screen size: {width}x{height}')
logger.warning('Alas requires 1280x720')
logger.hr('Script end')
exit(1)
if not (width == 1280 and height == 720):
logger.critical(f'Resolution not supported: {width}x{height}')
logger.critical('Please set emulator resolution to 1280x720')
raise RequestHumanTakeover
# Check screen color
# May get a pure black screenshot on some emulators.
color = get_color(self.image, area=(0, 0, 1280, 720))
if sum(color) < 1:
logger.warning('Received a pure black screenshot')
logger.warning(f'Color: {color}')
exit(1)
logger.critical(f'Received pure black screenshots from emulator, color: {color}')
logger.critical(f'Screenshot method `{self.config.Emulator_ScreenshotMethod}` '
f'may not work on emulator `{self.serial}`')
logger.critical('Please use other screenshot methods')
raise RequestHumanTakeover
def stuck_record_add(self, button):
self.stuck_record.add(str(button))
@ -118,7 +117,6 @@ class Device(Screenshot, Control, AppControl):
logger.warning(f'Waiting for {self.stuck_record}')
self.stuck_record_clear()
if self.config.ENABLE_GAME_STUCK_HANDLER:
raise GameStuckError(f'Wait too long')
def disable_stuck_detection(self):

View File

@ -19,6 +19,7 @@ class CampaignNameError(Exception):
class ScriptError(Exception):
# This is likely to be a mistake of developers, but sometimes a random issue
pass
@ -29,12 +30,20 @@ class ScriptEnd(Exception):
class GameStuckError(Exception):
pass
class LogisticsRefreshBugHandler(Exception):
pass
class GameTooManyClickError(Exception):
pass
class GameNotRunningError(Exception):
pass
class RequestHumanTakeover(Exception):
# Request human takeover
# Alas is unable to handle such error, probably because of wrong settings.
pass

View File

@ -340,6 +340,7 @@ class GuildLogistics(GuildBase):
# To fix this, you have to enter guild logistics once, then restart.
# If exchange for 5 times, this bug is considered to be triggered.
logger.warning('Triggered guild logistics refresh bug')
logger.warning('This is a bug in Azur Lane, Alas will close game and wait 600 seconds')
raise LogisticsRefreshBugHandler('Triggered guild logistics refresh bug')
else:

View File

@ -3,7 +3,7 @@ from datetime import datetime
import module.config.server as server
from module.base.timer import Timer
from module.combat.combat import Combat
from module.exception import GameTooManyClickError, ScriptError
from module.exception import GameTooManyClickError, GameStuckError, RequestHumanTakeover
from module.handler.assets import *
from module.logger import logger
from module.map.assets import *
@ -79,36 +79,30 @@ class LoginHandler(Combat):
bool: If login success
Raises:
ScriptError: If login failed more than 3
RequestHumanTakeover: If login failed more than 3
"""
for _ in range(3):
self.device.stuck_record_clear()
try:
self._handle_app_login()
return True
except GameTooManyClickError as e:
except (GameTooManyClickError, GameStuckError) as e:
logger.warning(e)
self.device.app_stop()
self.device.app_start()
continue
logger.warning('Login failed more than 3')
self.device.send_notification('ScriptError', 'Login failed more than 3')
raise ScriptError('Login failed more than 3')
logger.critical('Login failed more than 3')
logger.critical('Azur Lane server may be under maintenance, or you may lost network connection')
raise RequestHumanTakeover
def app_restart(self):
logger.hr('App restart')
self.device.app_stop()
self.device.app_start()
self.handle_app_login()
def app_ensure_start(self):
if not self.device.app_is_running():
self.device.app_start()
self.handle_app_login()
return True
return False
self.ensure_no_unfinished_campaign()
self.config.Scheduler_Enable = False
def ensure_no_unfinished_campaign(self, confirm_wait=3):
"""
@ -132,15 +126,6 @@ class LoginHandler(Combat):
confirm_wait=confirm_wait, skip_first_screenshot=True)
self.ui_goto_main()
def handle_game_stuck(self):
logger.warning(f'{self.config.PACKAGE_NAME} will be restart in 10 seconds')
logger.warning('If you are playing by hand, please stop Alas')
self.device.send_notification('Game stucked', 'will be restart in 10 seconds')
self.device.sleep(10)
self.app_restart()
self.ensure_no_unfinished_campaign()
def handle_user_agreement(self):
"""
For CN only.

View File

@ -1,5 +1,6 @@
from module.base.utils import *
from module.config.config import AzurLaneConfig
from module.exception import ScriptError
from module.logger import logger
from module.map_detection.utils import *
from module.map_detection.utils_assets import *
@ -163,7 +164,9 @@ class GridPredictor:
for name, template in self.template_enemy_genre.items():
if template is None:
logger.warning(f'Enemy detection template not found: {name}')
exit(1)
logger.warning('Please create it with dev_tools/relative_record.py or dev_tools/relative_crop.py, '
'then place it under ./assets/<server>/template')
raise ScriptError(f'Enemy detection template not found: {name}')
short_name = name[6:] if name.startswith('Siren_') else name
scaling = scaling_dic.get(short_name, 1)

View File

@ -8,6 +8,7 @@ from cnocr.cn_ocr import data_dir, read_charset, check_model_name, load_module,
from cnocr.fit.ctc_metrics import CtcMetrics
from cnocr.hyperparams.cn_hyperparams import CnHyperparams as Hyperparams
from module.exception import RequestHumanTakeover
from module.logger import logger
@ -115,7 +116,9 @@ class AlOcr(CnOcr):
# Disable auto downloading cnocr models when model not found.
# get_model_file(model_dir)
logger.warning(f'Ocr model not prepared: {model_dir}')
exit(1)
logger.warning(f'Required files: {model_files}')
logger.critical('Please check if required files of pre-trained OCR model exist')
raise RequestHumanTakeover
def _get_module(self, context):
network, self._hp = gen_network(self._model_name, self._hp, self._net_prefix)

View File

@ -3,6 +3,7 @@ import numpy as np
from module.campaign.run import OCR_OIL
from module.combat.assets import *
from module.combat.combat import Combat
from module.exception import ScriptError
from module.logger import logger
from module.map.map_operation import MapOperation
from module.ocr.ocr import DigitCounter
@ -34,8 +35,7 @@ def raid_name_shorten(name):
elif name == 'raid_20210708':
return 'SURUGA'
else:
logger.warning(f'Unknown raid name: {name}')
exit(1)
raise ScriptError(f'Unknown raid name: {name}')
def raid_entrance(raid, mode):
@ -51,8 +51,7 @@ def raid_entrance(raid, mode):
try:
return globals()[key]
except KeyError:
logger.warning(f'Raid entrance asset not exists: {key}')
exit(1)
raise ScriptError(f'Raid entrance asset not exists: {key}')
def raid_ocr(raid, mode):
@ -73,8 +72,7 @@ def raid_ocr(raid, mode):
elif raid == 'SURUGA':
return RaidCounter(button, letter=(49, 48, 49), threshold=128)
except KeyError:
logger.warning(f'Raid entrance asset not exists: {key}')
exit(1)
raise ScriptError(f'Raid entrance asset not exists: {key}')
class Raid(MapOperation, Combat):

View File

@ -2,6 +2,7 @@ from module.base.button import ButtonGrid
from module.base.timer import Timer
from module.base.utils import get_color, color_similar
from module.combat.assets import GET_ITEMS_1
from module.exception import RequestHumanTakeover, ScriptError
from module.logger import logger
from module.retire.assets import *
from module.retire.enhancement import Enhancement
@ -294,21 +295,19 @@ class Retirement(Enhancement):
self.dock_favourite_set(enable=False)
total = self.retire_ships_one_click()
if not total:
logger.warning('No ship retired, exit')
logger.warning('Please configure your one-click-retire in game, '
logger.critical('No ship retired')
logger.critical('Please configure your one-click-retire in game, '
'make sure it can select ships to retire')
exit(1)
raise RequestHumanTakeover
elif mode == 'old_retire':
total = self.retire_ships_old()
if not total:
logger.warning('No ship retired, exit')
logger.warning('Please configure your retirement settings in Alas, '
logger.critical('No ship retired')
logger.critical('Please configure your retirement settings in Alas, '
'make sure it can select ships to retire')
exit(1)
raise RequestHumanTakeover
else:
logger.warning(f'Unknown retire mode: {self.config.Retirement_RetireMode}')
total = 0
exit(1)
raise ScriptError(f'Unknown retire mode: {self.config.Retirement_RetireMode}')
self._retirement_quit()
self.config.DOCK_FULL_TRIGGERED = True
@ -366,11 +365,5 @@ class Retirement(Enhancement):
def keep_one_common_cv(self):
button = self.retirement_get_common_rarity_cv()
if button is not None:
if self._retire_select_one(button, skip_first_screenshot=False):
self._retire_select_one(button, skip_first_screenshot=False)
self._have_keeped_cv = True
else:
logger.warning('No ship retired, exit')
logger.info(
'This may happens because some filters are set in dock')
exit(1)

View File

@ -1,7 +1,7 @@
from module.base.button import Button
from module.base.timer import Timer
from module.combat.assets import *
from module.exception import GameNotRunningError
from module.exception import GameNotRunningError, RequestHumanTakeover
from module.handler.assets import *
from module.handler.info_handler import InfoHandler
from module.logger import logger
@ -125,7 +125,8 @@ class UI(InfoHandler):
if not self.device.app_is_running():
raise GameNotRunningError('Game not running')
else:
exit(1)
logger.critical('Please switch to a supported page before starting Alas')
raise RequestHumanTakeover
def ui_goto(self, destination, offset=(20, 20), confirm_wait=0, skip_first_screenshot=True):
"""
@ -260,6 +261,8 @@ class UI(InfoHandler):
# Research popup, lost connection popup
if self.handle_popup_confirm('UI_ADDITIONAL'):
return True
if self.handle_urgent_commission():
return True
# Guild popup
if self.handle_guild_popup_cancel():