mirror of
https://github.com/LmeSzinc/AzurLaneAutoScript.git
synced 2025-01-08 12:27:33 +08:00
Fix: Stop scheduler if a task failed 3 or more times
- Add: Clear click record - Opt: Check the type of user setting and display invalid settings
This commit is contained in:
parent
1fa344c2d3
commit
3098aa31aa
34
alas.py
34
alas.py
@ -9,7 +9,7 @@ from cached_property import cached_property
|
||||
import module.config.server as server
|
||||
from module.config.config import AzurLaneConfig, TaskEnd
|
||||
from module.config.config_updater import ConfigUpdater
|
||||
from module.config.utils import deep_get
|
||||
from module.config.utils import deep_get, deep_set
|
||||
from module.exception import *
|
||||
from module.logger import logger
|
||||
|
||||
@ -26,6 +26,9 @@ class AzurLaneAutoScript:
|
||||
# Set server before loading any buttons.
|
||||
server.server = deep_get(config.data, keys='Alas.Emulator.Server', default='cn')
|
||||
return config
|
||||
except RequestHumanTakeover:
|
||||
logger.critical('Request human takeover')
|
||||
exit(1)
|
||||
except Exception as e:
|
||||
logger.exception(e)
|
||||
exit(1)
|
||||
@ -250,24 +253,41 @@ class AzurLaneAutoScript:
|
||||
def loop(self):
|
||||
logger.set_file_logger(self.config_name)
|
||||
logger.info(f'Start scheduler loop: {self.config_name}')
|
||||
|
||||
is_first = True
|
||||
failure_record = {}
|
||||
|
||||
while 1:
|
||||
# Skip first restart
|
||||
if is_first and self.config.task == 'Restart':
|
||||
logger.info('Skip task `Restart` at scheduler start')
|
||||
self.config.task_delay(server_update=True)
|
||||
del self.__dict__['config']
|
||||
|
||||
logger.info(f'Scheduler: Start task `{self.config.task}`')
|
||||
# Run
|
||||
task = self.config.task
|
||||
logger.info(f'Scheduler: Start task `{task}`')
|
||||
self.device.stuck_record_clear()
|
||||
self.device.click_record_clear()
|
||||
self.device.screenshot()
|
||||
logger.hr(self.config.task, level=0)
|
||||
success = self.run(inflection.underscore(self.config.task))
|
||||
|
||||
logger.info(f'Scheduler: End task `{self.config.task}`')
|
||||
logger.hr(task, level=0)
|
||||
success = self.run(inflection.underscore(task))
|
||||
logger.info(f'Scheduler: End task `{task}`')
|
||||
del self.__dict__['config']
|
||||
is_first = False
|
||||
|
||||
# Check failures
|
||||
failed = deep_get(failure_record, keys=task, default=0)
|
||||
failed = 0 if success else failed + 1
|
||||
deep_set(failure_record, keys=task, value=failed)
|
||||
if failed >= 3:
|
||||
logger.critical(f"Task `{task}` failed 3 or more times.")
|
||||
logger.critical("Possible reason: You haven't used it correctly. "
|
||||
"Please read the help text of the options.")
|
||||
logger.critical("Possible reason: There is a problem with this task. "
|
||||
"Please contact developers or try to fix it yourself.")
|
||||
logger.critical('Request human takeover')
|
||||
exit(1)
|
||||
|
||||
if success:
|
||||
continue
|
||||
elif self.config.Error_HandleError:
|
||||
|
@ -81,6 +81,7 @@ class AzurLaneConfig(ConfigUpdater, ManualConfig, GeneratedConfig):
|
||||
|
||||
def load(self):
|
||||
self.data = self.read_file(self.config_name)
|
||||
ConfigTypeChecker.check(self.data)
|
||||
|
||||
for path, value in self.modified.items():
|
||||
deep_set(self.data, keys=path, value=value)
|
||||
@ -489,3 +490,32 @@ class MultiSetWrapper:
|
||||
def __exit__(self, exc_type, exc_val, exc_tb):
|
||||
self.main.update()
|
||||
self.main.auto_update = True
|
||||
|
||||
|
||||
class ConfigTypeChecker:
|
||||
checkers = [
|
||||
(['Scheduler', 'NextRun'], datetime),
|
||||
(['Emotion', 'Fleet1Record'], datetime),
|
||||
(['Emotion', 'Fleet2Record'], datetime),
|
||||
(['Exercise', 'OpponentRefreshRecord'], datetime),
|
||||
]
|
||||
|
||||
@classmethod
|
||||
def check(cls, data):
|
||||
"""
|
||||
Args:
|
||||
data (dict): User config.
|
||||
|
||||
Raises:
|
||||
RequestHumanTakeover: If there's invalid setting.
|
||||
"""
|
||||
for func, func_data in data.items():
|
||||
for path, typ in cls.checkers:
|
||||
value = deep_get(func_data, keys=path, default=None)
|
||||
if value is None:
|
||||
continue
|
||||
if not isinstance(value, typ):
|
||||
logger.critical(f'Task `{func}` has an invalid setting {".".join(path)}="{str(value)}". '
|
||||
f'Current type: {type_to_str(value)}, expected type: {type_to_str(typ)}')
|
||||
logger.critical('Please check your settings')
|
||||
raise RequestHumanTakeover
|
||||
|
@ -439,3 +439,19 @@ def to_list(text, length=1):
|
||||
return [int(text)] * length
|
||||
out = [int(letter.strip()) for letter in text.split(',')]
|
||||
return out
|
||||
|
||||
|
||||
def type_to_str(typ):
|
||||
"""
|
||||
Convert any types or any objects to a string。
|
||||
Remove <> to prevent them from being parsed as HTML tags.
|
||||
|
||||
Args:
|
||||
typ:
|
||||
|
||||
Returns:
|
||||
str: Such as `int`, 'datetime.datetime'.
|
||||
"""
|
||||
if not isinstance(typ, type):
|
||||
typ = type(typ)
|
||||
return str(typ).strip("<class '>").replace('<', '_').replace('>', '_')
|
||||
|
@ -45,14 +45,19 @@ class Control(MiniTouch):
|
||||
if count[0][1] >= 12:
|
||||
logger.warning(f'Too many click for a button: {count[0][0]}')
|
||||
logger.warning(f'History click: {[str(prev) for prev in self.click_record]}')
|
||||
self.click_record_clear()
|
||||
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.warning(f'History click: {[str(prev) for prev in self.click_record]}')
|
||||
self.click_record_clear()
|
||||
raise GameTooManyClickError(f'Too many click between 2 buttons: {count[0][0]}, {count[1][0]}')
|
||||
|
||||
return False
|
||||
|
||||
def click_record_clear(self):
|
||||
self.click_record.clear()
|
||||
|
||||
def click(self, button, record_check=True):
|
||||
"""Method to click a button.
|
||||
|
||||
|
@ -84,6 +84,7 @@ class LoginHandler(Combat):
|
||||
"""
|
||||
for _ in range(3):
|
||||
self.device.stuck_record_clear()
|
||||
self.device.click_record_clear()
|
||||
try:
|
||||
self._handle_app_login()
|
||||
return True
|
||||
|
Loading…
Reference in New Issue
Block a user