1
0
mirror of https://github.com/sui-feng-cb/AzurLaneAutoScript1.git synced 2026-07-23 06:06:16 +08:00

Merge branch 'dev'

This commit is contained in:
2026-07-18 16:06:08 +08:00
52 changed files with 1918 additions and 339 deletions

View File

@@ -1,11 +1,11 @@
import datetime
from module.config.utils import get_server_last_update
from module.config.utils import get_server_next_update, get_server_last_update
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.page import page_exercise
from module.config.utils import get_server_next_update
from module.smart_mgmt.downtime_fetch import get_downtime_end
class DatedDuration(Ocr):
def __init__(self, buttons, lang='cnocr', letter=(255, 255, 255), threshold=128, alphabet='0123456789:IDS天日d',
@@ -171,18 +171,6 @@ class Exercise(ExerciseCombat):
self.config.set_record(Exercise_OpponentRefreshValue=0)
return 0
def _get_thursday_strategy(self, remain_time):
"""
Args:
remain_time(datetime.timedelta):
Returns:
bool: if use Thursday strategy
"""
if 96 > remain_time >= 84 or 264 > remain_time >= 252:
return True
return False
def _get_exercise_reset_remain(self):
"""
Returns:
@@ -206,52 +194,76 @@ class Exercise(ExerciseCombat):
return preserve, admiral_interval
def run(self):
self.ui_ensure(page_exercise)
server_update = self.config.Scheduler_ServerUpdate
def _get_thursday_strategy(self, remain_hours):
"""
Args:
remain_hours(int):
self.opponent_change_count = self._get_opponent_change_count()
logger.attr("Change_opponent_count", self.opponent_change_count)
logger.attr('Exercise_ExerciseStrategy', self.config.Exercise_ExerciseStrategy)
self.preserve, admiral_interval = self._get_exercise_strategy()
Returns:
bool: if use Thursday strategy
"""
if 96 > remain_hours >= 84 or 264 > remain_hours >= 252:
return True
return False
remain_time = OCR_PERIOD_REMAIN.ocr(self.device.image)
logger.info(f'Exercise period remain: {remain_time}')
def _get_downtime_strategy(self, now):
"""
Check smart_mgmt downtime window to decide whether to clear attempts.
if admiral_interval is not None and remain_time:
admiral_start, admiral_end = admiral_interval
Returns:
bool:
True if today is maintenance day with end time at or after ExerciseClearTime.
False if available but today is not maintenance day.
None if unavailable (disabled, window missing, or parse failed).
"""
end_dt = get_downtime_end(self.config)
if end_dt is None:
return None
if end_dt <= now:
return False
threshold_str = self.config.cross_get('DowntimeMgmt.DowntimeStrategy.ExerciseClearTime', '15:00:00')
threshold_time = datetime.datetime.strptime(threshold_str, '%H:%M:%S').time()
return end_dt.date() == now.date() and end_dt.time() >= threshold_time
if self._get_thursday_strategy(int(remain_time.total_seconds() // 3600)):
logger.info('Reach Thursday for admiral trial, using all attempts.')
self.preserve = 0
forced_run = True
elif admiral_start > int(remain_time.total_seconds() // 3600) >= admiral_end: # set time for getting admiral
logger.info('Reach set time for admiral trial, using all attempts.')
self.preserve = 0
forced_run = True
elif int(remain_time.total_seconds() // 3600) < 6: # if not set to "sun18", still depleting at sunday 18pm.
logger.info('Exercise period remain less than 6 hours, using all attempts.')
self.preserve = 0
forced_run = True
else:
logger.info(f'Preserve {self.preserve} exercise')
forced_run = False
else:
forced_run = False
def _should_force_clear(self, now, remain_time, admiral_interval):
"""Decide whether to clear all exercise attempts this run."""
if admiral_interval is None or not remain_time:
return False
# Delay task to the configured time
if ((get_server_next_update(server_update) - datetime.datetime.now()).seconds >
3600 * self.config.Exercise_DelayUntilHoursBeforeNextUpdate)\
and not forced_run:
logger.warning(f'Exercise should run at {self.config.Exercise_DelayUntilHoursBeforeNextUpdate} '
f'hours before next update. Delay task to it.')
run = False
else:
run = True
remain_hours = int(remain_time.total_seconds() // 3600)
admiral_start, admiral_end = admiral_interval
while run:
downtime_strategy = self._get_downtime_strategy(now)
if downtime_strategy is True:
logger.info('Downtime today, using all attempts before downtime')
return True
elif downtime_strategy is None:
# Fallback to thursday strategy when smart_mgmt is unavailable
if self._get_thursday_strategy(remain_hours):
logger.info('Reach Thursday, using all attempts before downtime')
return True
if admiral_start > remain_hours >= admiral_end:
logger.info('Reach set time for admiral trial, using all attempts')
return True
if remain_hours < 6:
logger.info('Exercise period remain less than 6 hours, using all attempts')
return True
return False
def _should_delay(self, now, next_update, forced_clear):
"""Check whether to delay exercise to the configured time before next update."""
if forced_clear:
return False
seconds_until_update = (next_update - now).seconds
return seconds_until_update > 3600 * self.config.Exercise_DelayUntilHoursBeforeNextUpdate
def _exercise(self, preserve):
"""Consume exercise attempts until remain <= preserve or refresh exhausted."""
while 1:
self.remain = OCR_EXERCISE_REMAIN.ocr(self.device.image)
if self.remain <= self.preserve:
if self.remain <= preserve:
break
logger.hr(f'Exercise remain {self.remain}', level=1)
@@ -263,19 +275,43 @@ class Exercise(ExerciseCombat):
logger.info('New opponent exhausted')
break
def run(self):
self.ui_ensure(page_exercise)
server_update = self.config.Scheduler_ServerUpdate
self.opponent_change_count = self._get_opponent_change_count()
logger.attr("Change_opponent_count", self.opponent_change_count)
logger.attr('Exercise_ExerciseStrategy', self.config.Exercise_ExerciseStrategy)
self.preserve, admiral_interval = self._get_exercise_strategy()
now = datetime.datetime.now()
remain_time = self._get_exercise_reset_remain()
logger.info(f'Exercise period remain: {remain_time}')
forced_clear = self._should_force_clear(now, remain_time, admiral_interval)
if forced_clear:
self.preserve = 0
logger.attr("exercise preserve", self.preserve)
next_update = get_server_next_update(server_update)
should_delay = self._should_delay(now, next_update, forced_clear)
if should_delay:
logger.warning(f'Exercise should run at {self.config.Exercise_DelayUntilHoursBeforeNextUpdate} '
f'hours before next update. Delay task to it.')
else:
self._exercise(self.preserve)
# self.equipment_take_off_when_finished()
# Scheduler
with self.config.multi_set():
self.config.set_record(Exercise_OpponentRefreshValue=self.opponent_change_count)
if self.remain <= self.preserve or self.opponent_change_count >= 5:
next_run = get_server_next_update(server_update) \
- datetime.timedelta(hours=self.config.Exercise_DelayUntilHoursBeforeNextUpdate)
now = datetime.datetime.now()
if next_run < now or run:
next_run = next_update - datetime.timedelta(hours=self.config.Exercise_DelayUntilHoursBeforeNextUpdate)
if next_run >= now or should_delay:
minutes_to_delay = int((next_run - now).total_seconds() / 60 + 1)
self.config.task_delay(minute=minutes_to_delay)
else:
self.config.task_delay(server_update=True)
return
minutes_to_delay = int((next_run - now).total_seconds() / 60 + 1)
self.config.task_delay(minute=minutes_to_delay)
else:
self.config.task_delay(success=False)