mirror of
https://github.com/LmeSzinc/AzurLaneAutoScript.git
synced 2025-01-08 12:27:33 +08:00
Add: TaskHoardingDuration and CloseGameDuringWait (#643)
This commit is contained in:
parent
b1a9157a24
commit
6bf5f9fa92
3
alas.py
3
alas.py
@ -232,8 +232,8 @@ class AzurLaneAutoScript:
|
||||
name=self.config.Campaign_Name, folder=self.config.Campaign_Event, mode=self.config.Campaign_Mode)
|
||||
|
||||
def loop(self):
|
||||
logger.info(f'Start scheduler loop: {self.config_name}')
|
||||
logger.set_file_logger(self.config_name)
|
||||
logger.info(f'Start scheduler loop: {self.config_name}')
|
||||
|
||||
is_first = True
|
||||
while 1:
|
||||
@ -243,6 +243,7 @@ class AzurLaneAutoScript:
|
||||
del self.__dict__['config']
|
||||
|
||||
logger.info(f'Scheduler: Start task `{self.config.task}`')
|
||||
self.device.stuck_record_clear()
|
||||
self.device.screenshot()
|
||||
logger.hr(self.config.task, level=0)
|
||||
success = self.run(inflection.underscore(self.config.task))
|
||||
|
@ -13,7 +13,9 @@
|
||||
"ScreenshotLength": 1
|
||||
},
|
||||
"Optimization": {
|
||||
"CombatScreenshotInterval": 1.0
|
||||
"CombatScreenshotInterval": 1.0,
|
||||
"TaskHoardingDuration": 0,
|
||||
"CloseGameDuringWait": false
|
||||
},
|
||||
"DropRecord": {
|
||||
"SaveFolder": "./screenshots",
|
||||
|
@ -56,6 +56,14 @@
|
||||
"CombatScreenshotInterval": {
|
||||
"type": "input",
|
||||
"value": 1.0
|
||||
},
|
||||
"TaskHoardingDuration": {
|
||||
"type": "input",
|
||||
"value": 0
|
||||
},
|
||||
"CloseGameDuringWait": {
|
||||
"type": "checkbox",
|
||||
"value": false
|
||||
}
|
||||
},
|
||||
"DropRecord": {
|
||||
|
@ -29,6 +29,8 @@ Error:
|
||||
ScreenshotLength: 1
|
||||
Optimization:
|
||||
CombatScreenshotInterval: 1.0
|
||||
TaskHoardingDuration: 0
|
||||
CloseGameDuringWait: false
|
||||
DropRecord:
|
||||
SaveFolder: ./screenshots
|
||||
AzurStatsID: null
|
||||
|
@ -22,10 +22,18 @@ class Function:
|
||||
self.command = deep_get(data, keys='Scheduler.Command', default='Unknown')
|
||||
self.next_run = deep_get(data, keys='Scheduler.NextRun', default=datetime(2020, 1, 1, 0, 0))
|
||||
|
||||
def __str__(self):
|
||||
return f'<{self.command} ({self.enable}, {str(self.next_run)})>'
|
||||
|
||||
__repr__ = __str__
|
||||
|
||||
|
||||
class AzurLaneConfig(ConfigUpdater, ManualConfig, GeneratedConfig):
|
||||
bound = {}
|
||||
|
||||
# Class property
|
||||
is_hoarding_task = True
|
||||
|
||||
def __setattr__(self, key, value):
|
||||
if key in self.bound:
|
||||
path = self.bound[key]
|
||||
@ -36,7 +44,7 @@ class AzurLaneConfig(ConfigUpdater, ManualConfig, GeneratedConfig):
|
||||
super().__setattr__(key, value)
|
||||
|
||||
def __init__(self, config_name, task=None):
|
||||
# This will read ./config/<config_name>.yaml
|
||||
# This will read ./config/<config_name>.json
|
||||
self.config_name = config_name
|
||||
# Raw json data in yaml file.
|
||||
self.data = {}
|
||||
@ -50,18 +58,20 @@ class AzurLaneConfig(ConfigUpdater, ManualConfig, GeneratedConfig):
|
||||
# Force override variables
|
||||
# Key: Argument name in GeneratedConfig. Value: Modified value.
|
||||
self.overridden = {}
|
||||
# Scheduler queue, will be updated in `get_next()`, list of Function objects
|
||||
self.waiting_task = []
|
||||
self.pending_task = []
|
||||
# Task to run and bind.
|
||||
# Task means the name of the function to run in AzurLaneAutoScript class.
|
||||
if config_name == 'template':
|
||||
logger.info('Using template config, which is read only')
|
||||
self.auto_update = False
|
||||
self.task = 'template'
|
||||
else:
|
||||
self.load()
|
||||
if task is None:
|
||||
task = self.get_next()
|
||||
self.bind(task)
|
||||
logger.info(f'Bind task {task}')
|
||||
self.task = task
|
||||
self.load()
|
||||
if task is None:
|
||||
task = self.get_next()
|
||||
self.bind(task)
|
||||
logger.info(f'Bind task {task}')
|
||||
self.task = task
|
||||
|
||||
def load(self):
|
||||
self.data = self.read_file(self.config_name)
|
||||
@ -74,14 +84,14 @@ class AzurLaneConfig(ConfigUpdater, ManualConfig, GeneratedConfig):
|
||||
Args:
|
||||
func (str): Function to run
|
||||
"""
|
||||
func_list = [func, 'General', 'Alas']
|
||||
func_set = {func, 'General', 'Alas'}
|
||||
if 'opsi' in func.lower():
|
||||
func_list.append('OpsiGeneral')
|
||||
func_set.add('OpsiGeneral')
|
||||
|
||||
# Bind arguments
|
||||
visited = set()
|
||||
self.bound = {}
|
||||
for func in func_list:
|
||||
for func in func_set:
|
||||
func_data = self.data.get(func, {})
|
||||
for group, group_data in func_data.items():
|
||||
for arg, value in group_data.items():
|
||||
@ -98,33 +108,55 @@ class AzurLaneConfig(ConfigUpdater, ManualConfig, GeneratedConfig):
|
||||
super().__setattr__(arg, value)
|
||||
|
||||
def get_next(self):
|
||||
"""
|
||||
Returns:
|
||||
str: Command to run
|
||||
"""
|
||||
pending = []
|
||||
waiting = []
|
||||
now = datetime.now()
|
||||
hoarding = timedelta(minutes=deep_get(self.data, keys='Alas.Optimization.TaskHoardingDuration', default=0))
|
||||
close_game = deep_get(self.data, keys='Alas.Optimization.CloseGameDuringWait', default=False)
|
||||
for func in self.data.values():
|
||||
func = Function(func)
|
||||
if func.next_run < datetime.now():
|
||||
if func.next_run + hoarding < now:
|
||||
pending.append(func)
|
||||
else:
|
||||
waiting.append(func)
|
||||
|
||||
self.pending_task = pending
|
||||
if pending:
|
||||
AzurLaneConfig.is_hoarding_task = False
|
||||
f = Filter(regex=r'(.*)', attr=['command'])
|
||||
f.load(self.SCHEDULER_PRIORITY)
|
||||
pending = f.apply(pending, func=lambda x: x.enable)
|
||||
pending = [f.command for f in pending]
|
||||
if pending:
|
||||
logger.info(f'Pending tasks: {pending}')
|
||||
self.pending_task = pending
|
||||
task = pending[0]
|
||||
logger.attr('Task', task)
|
||||
return task
|
||||
else:
|
||||
AzurLaneConfig.is_hoarding_task = True
|
||||
|
||||
self.waiting_task = waiting
|
||||
if waiting:
|
||||
waiting = sorted(waiting, key=operator.attrgetter('next_run'))[0]
|
||||
waiting = sorted(waiting, key=operator.attrgetter('next_run'))
|
||||
self.waiting_task = waiting
|
||||
waiting = waiting[0]
|
||||
target = (waiting.next_run + hoarding).replace(microsecond=0)
|
||||
logger.info('No task pending')
|
||||
logger.info(f'Wait until {waiting.next_run} for task `{waiting.command}`')
|
||||
|
||||
time.sleep(waiting.next_run.timestamp() - datetime.now().timestamp() + 1)
|
||||
return self.get_next()
|
||||
logger.info(f'Wait until {target} for task `{waiting.command}`')
|
||||
if close_game:
|
||||
self.modified['Restart.Scheduler.Enable'] = True
|
||||
self.modified['Restart.Scheduler.NextRun'] = target
|
||||
self.task = 'Restart'
|
||||
self.update()
|
||||
return 'Restart'
|
||||
else:
|
||||
time.sleep(waiting.next_run.timestamp() - datetime.now().timestamp() + 1)
|
||||
return self.get_next()
|
||||
else:
|
||||
logger.critical('No task waiting or pending')
|
||||
logger.critical('Please enable at least one task')
|
||||
@ -242,7 +274,7 @@ class AzurLaneConfig(ConfigUpdater, ManualConfig, GeneratedConfig):
|
||||
if deep_get(self.data, keys=path, default=None) is None:
|
||||
raise ScriptError(f'Task to call: `{task}` does not exist in user config')
|
||||
else:
|
||||
self.modified[path] = datetime.now().replace(microsecond=0)
|
||||
self.modified[path] = datetime(2021, 1, 1, 0, 0, 0)
|
||||
if task == 'Restart':
|
||||
# Restart is forced to enable
|
||||
self.modified[f'{task}.Scheduler.Enable'] = True
|
||||
|
@ -31,6 +31,8 @@ class GeneratedConfig:
|
||||
|
||||
# Group `Optimization`
|
||||
Optimization_CombatScreenshotInterval = 1.0
|
||||
Optimization_TaskHoardingDuration = 0
|
||||
Optimization_CloseGameDuringWait = False
|
||||
|
||||
# Group `DropRecord`
|
||||
DropRecord_SaveFolder = './screenshots'
|
||||
|
@ -50,8 +50,6 @@ class ManualConfig:
|
||||
"""
|
||||
module.device
|
||||
"""
|
||||
SERIAL = ''
|
||||
PACKAGE_NAME = ''
|
||||
ASCREENCAP_FILEPATH_LOCAL = './bin/ascreencap'
|
||||
ASCREENCAP_FILEPATH_REMOTE = '/data/local/tmp/ascreencap'
|
||||
MINITOUCH_FILEPATH_REMOTE = '/data/local/tmp/minitouch'
|
||||
|
@ -263,6 +263,14 @@
|
||||
"CombatScreenshotInterval": {
|
||||
"name": "Optimization.CombatScreenshotInterval.name",
|
||||
"help": "Optimization.CombatScreenshotInterval.help"
|
||||
},
|
||||
"TaskHoardingDuration": {
|
||||
"name": "Optimization.TaskHoardingDuration.name",
|
||||
"help": "Optimization.TaskHoardingDuration.help"
|
||||
},
|
||||
"CloseGameDuringWait": {
|
||||
"name": "Optimization.CloseGameDuringWait.name",
|
||||
"help": "Optimization.CloseGameDuringWait.help"
|
||||
}
|
||||
},
|
||||
"DropRecord": {
|
||||
|
@ -263,6 +263,14 @@
|
||||
"CombatScreenshotInterval": {
|
||||
"name": "Optimization.CombatScreenshotInterval.name",
|
||||
"help": "Optimization.CombatScreenshotInterval.help"
|
||||
},
|
||||
"TaskHoardingDuration": {
|
||||
"name": "Optimization.TaskHoardingDuration.name",
|
||||
"help": "Optimization.TaskHoardingDuration.help"
|
||||
},
|
||||
"CloseGameDuringWait": {
|
||||
"name": "Optimization.CloseGameDuringWait.name",
|
||||
"help": "Optimization.CloseGameDuringWait.help"
|
||||
}
|
||||
},
|
||||
"DropRecord": {
|
||||
|
@ -263,6 +263,14 @@
|
||||
"CombatScreenshotInterval": {
|
||||
"name": "战斗中放慢截图速度至 X 秒一张",
|
||||
"help": "能降低 CPU 占用"
|
||||
},
|
||||
"TaskHoardingDuration": {
|
||||
"name": "囤积任务 X 分钟",
|
||||
"help": "能在收菜期间降低操作游戏的频率\n任务触发后,等待 X 分钟,再一次性执行囤积的任务"
|
||||
},
|
||||
"CloseGameDuringWait": {
|
||||
"name": "无任务时关闭游戏",
|
||||
"help": "能在收菜期间降低 CPU 占用"
|
||||
}
|
||||
},
|
||||
"DropRecord": {
|
||||
|
@ -263,6 +263,14 @@
|
||||
"CombatScreenshotInterval": {
|
||||
"name": "Optimization.CombatScreenshotInterval.name",
|
||||
"help": "Optimization.CombatScreenshotInterval.help"
|
||||
},
|
||||
"TaskHoardingDuration": {
|
||||
"name": "Optimization.TaskHoardingDuration.name",
|
||||
"help": "Optimization.TaskHoardingDuration.help"
|
||||
},
|
||||
"CloseGameDuringWait": {
|
||||
"name": "Optimization.CloseGameDuringWait.name",
|
||||
"help": "Optimization.CloseGameDuringWait.help"
|
||||
}
|
||||
},
|
||||
"DropRecord": {
|
||||
|
@ -1,4 +1,5 @@
|
||||
from datetime import datetime
|
||||
from datetime import datetime, timedelta
|
||||
import time
|
||||
|
||||
import module.config.server as server
|
||||
from module.base.timer import Timer
|
||||
@ -99,9 +100,21 @@ class LoginHandler(Combat):
|
||||
def app_restart(self):
|
||||
logger.hr('App restart')
|
||||
self.device.app_stop()
|
||||
|
||||
if self.config.Scheduler_NextRun > datetime.now():
|
||||
target = self.config.Scheduler_NextRun - timedelta(seconds=5)
|
||||
task = 'unknown'
|
||||
for waiting in self.config.waiting_task:
|
||||
if waiting.command != 'Restart':
|
||||
task = waiting.command
|
||||
break
|
||||
|
||||
logger.info(f'{self.config.Emulator_PackageName} will be started at {target} for task `{task}`')
|
||||
time.sleep(target.timestamp() - datetime.now().timestamp())
|
||||
|
||||
self.device.app_start()
|
||||
self.handle_app_login()
|
||||
self.ensure_no_unfinished_campaign()
|
||||
# self.ensure_no_unfinished_campaign()
|
||||
self.config.task_delay(server_update=True)
|
||||
|
||||
def ensure_no_unfinished_campaign(self, confirm_wait=3):
|
||||
|
@ -322,5 +322,7 @@ class UI(InfoHandler):
|
||||
return True
|
||||
if self.appear_then_click(AUTO_SEARCH_MENU_EXIT, offset=(200, 20), interval=3):
|
||||
return True
|
||||
if self.appear_then_click(WITHDRAW, offset=(20, 20), interval=1.5):
|
||||
return True
|
||||
|
||||
return False
|
||||
|
Loading…
Reference in New Issue
Block a user