Refactor: Exercise module, mode easiest_else_exp might have issues

This commit is contained in:
LmeSzinc 2021-09-23 02:31:08 +08:00
parent eb7886df61
commit e607c920cf
9 changed files with 114 additions and 45 deletions

View File

@ -15,6 +15,7 @@ from module.daily.daily import Daily
from module.device.device import Device from module.device.device import Device
from module.dorm.dorm import RewardDorm from module.dorm.dorm import RewardDorm
from module.exception import * from module.exception import *
from module.exercise.exercise import Exercise
from module.guild.guild_reward import RewardGuild from module.guild.guild_reward import RewardGuild
from module.handler.login import LoginHandler from module.handler.login import LoginHandler
from module.handler.sensitive_info import handle_sensitive_image, handle_sensitive_logs from module.handler.sensitive_info import handle_sensitive_image, handle_sensitive_logs
@ -131,6 +132,9 @@ class AzurLaneAutoScript:
def hard(self): def hard(self):
CampaignHard(config=self.config, device=self.device).run() CampaignHard(config=self.config, device=self.device).run()
def exercise(self):
Exercise(config=self.config, device=self.device).run()
def main(self): def main(self):
CampaignRun(config=self.config, device=self.device).run( CampaignRun(config=self.config, device=self.device).run(
name=self.config.Campaign_Name, name=self.config.Campaign_Name,

View File

@ -314,3 +314,20 @@ Hard:
Hard: Hard:
HardStage: 11-4 HardStage: 11-4
HardFleet: 1 HardFleet: 1
Exercise:
Scheduler:
Enable: false
NextRun: 2020-01-01 00:00:00
Command: Exercise
SuccessInterval: 120
FailureInterval: 120
ServerUpdate: 00:00, 12:00, 18:00
Exercise:
OpponentChooseMode: max_exp
OpponentTrial: 1
ExercisePreserve: 0
LowHpThreshold: 0.4
LowHpConfirmWait: 0.1
OpponentRefresh:
Count: 0
Record: 2020-01-01 00:00:00

View File

@ -398,7 +398,7 @@ Meowfficer:
FortChoreMeowfficer: true FortChoreMeowfficer: true
Daily: Daily:
_info: _info:
Menu: Reward Menu: Daily
Scheduler: Scheduler:
Enable: false Enable: false
NextRun: 2020-01-01 00:00:00 NextRun: 2020-01-01 00:00:00
@ -437,7 +437,7 @@ Daily:
option: ['no', 'first', 'second', 'third'] option: ['no', 'first', 'second', 'third']
Hard: Hard:
_info: _info:
Menu: Reward Menu: Daily
Scheduler: Scheduler:
Enable: false Enable: false
NextRun: 2020-01-01 00:00:00 NextRun: 2020-01-01 00:00:00
@ -450,3 +450,24 @@ Hard:
HardFleet: HardFleet:
value: 1 value: 1
option: [1, 2] option: [1, 2]
Exercise:
_info:
Menu: Daily
Scheduler:
Enable: false
NextRun: 2020-01-01 00:00:00
Command: Exercise
SuccessInterval: 120
FailureInterval: 120
ServerUpdate: 00:00, 12:00, 18:00
Exercise:
OpponentChooseMode:
value: max_exp
option: ['max_exp', 'easiest', 'leftmost', 'easiest_else_exp']
OpponentTrial: 1
ExercisePreserve: 0
LowHpThreshold: 0.4
LowHpConfirmWait: 0.1
OpponentRefresh:
Count: 0
Record: 2020-01-01 00:00:00

View File

@ -161,6 +161,23 @@ class AzurLaneConfig(ManualConfig, GeneratedConfig):
self.overridden[arg] = value self.overridden[arg] = value
super().__setattr__(arg, value) super().__setattr__(arg, value)
def set_record(self, **kwargs):
"""
Args:
**kwargs: For example, `Emotion1_Value=150`
will set `Emotion1_Value=150` and `Emotion1_Record=now()`
"""
self.auto_update = False
for arg, value in kwargs.items():
group, _ = arg.split('_', 1)
record = f'{group}_Record'
self.__setattr__(arg, value)
self.__setattr__(record, datetime.now().replace(microsecond=0))
self.update()
self.auto_update = True
def task_delay(self, success=None, server_update=None, target=None, minute=None): def task_delay(self, success=None, server_update=None, target=None, minute=None):
""" """
Set Scheduler.NextRun Set Scheduler.NextRun

View File

@ -152,4 +152,13 @@ class GeneratedConfig:
# Func `Hard` # Func `Hard`
Hard_HardStage = '11-4' Hard_HardStage = '11-4'
Hard_HardFleet = 1 Hard_HardFleet = 1 # 1, 2
# Func `Exercise`
Exercise_OpponentChooseMode = 'max_exp' # max_exp, easiest, leftmost, easiest_else_exp
Exercise_OpponentTrial = 1
Exercise_ExercisePreserve = 0
Exercise_LowHpThreshold = 0.4
Exercise_LowHpConfirmWait = 0.1
OpponentRefresh_Count = 0
OpponentRefresh_Record = datetime.datetime(2020, 1, 1, 0, 0)

View File

@ -15,7 +15,7 @@ class ExerciseCombat(HpDaemon, OpponentChoose, ExerciseEquipment):
Returns: Returns:
bool: bool:
""" """
return self.appear(PAUSE) and np.max(self.device.image.crop(PAUSE_DOUBLE_CHECK.area)) < 153 return self.appear(PAUSE) and np.max(self.image_area(PAUSE_DOUBLE_CHECK)) < 153
def _combat_preparation(self): def _combat_preparation(self):
logger.info('Combat preparation') logger.info('Combat preparation')
@ -23,7 +23,7 @@ class ExerciseCombat(HpDaemon, OpponentChoose, ExerciseEquipment):
self.device.screenshot() self.device.screenshot()
if self.appear(BATTLE_PREPARATION): if self.appear(BATTLE_PREPARATION):
self.equipment_take_on() # self.equipment_take_on()
pass pass
self.device.click(BATTLE_PREPARATION) self.device.click(BATTLE_PREPARATION)
@ -39,7 +39,7 @@ class ExerciseCombat(HpDaemon, OpponentChoose, ExerciseEquipment):
bool: True if wins. False if quit. bool: True if wins. False if quit.
""" """
logger.info('Combat execute') logger.info('Combat execute')
self.low_hp_confirm_timer = Timer(self.config.LOW_HP_CONFIRM_WAIT, count=2).start() self.low_hp_confirm_timer = Timer(self.config.Exercise_LowHpConfirmWait, count=2).start()
show_hp_timer = Timer(5) show_hp_timer = Timer(5)
success = True success = True
end = False end = False
@ -139,7 +139,7 @@ class ExerciseCombat(HpDaemon, OpponentChoose, ExerciseEquipment):
""" """
self._choose_opponent(opponent) self._choose_opponent(opponent)
for n in range(1, self.config.OPPONENT_CHALLENGE_TRIAL + 1): for n in range(1, self.config.Exercise_OpponentTrial + 1):
logger.hr('Try: %s' % n) logger.hr('Try: %s' % n)
self._combat_preparation() self._combat_preparation()
success = self._combat_execute() success = self._combat_execute()

View File

@ -1,5 +1,6 @@
from datetime import datetime from datetime import timedelta
from module.config.utils import get_server_next_update
from module.exercise.assets import * from module.exercise.assets import *
from module.exercise.combat import ExerciseCombat from module.exercise.combat import ExerciseCombat
from module.logger import logger from module.logger import logger
@ -7,9 +8,6 @@ from module.ocr.ocr import Digit
from module.ui.ui import page_exercise from module.ui.ui import page_exercise
OCR_EXERCISE_REMAIN = Digit(OCR_EXERCISE_REMAIN, letter=(173, 247, 74), threshold=128) OCR_EXERCISE_REMAIN = Digit(OCR_EXERCISE_REMAIN, letter=(173, 247, 74), threshold=128)
RECORD_OPTION = ('DailyRecord', 'exercise')
RECORD_COUNT = ('DailyRecord', 'exercise_count')
RECORD_SINCE = (0, 12, 18,)
class Exercise(ExerciseCombat): class Exercise(ExerciseCombat):
@ -22,20 +20,21 @@ class Exercise(ExerciseCombat):
self.opponent_change_count += 1 self.opponent_change_count += 1
logger.attr("Change_opponent_count", self.opponent_change_count) logger.attr("Change_opponent_count", self.opponent_change_count)
self.config.config.set(*RECORD_COUNT, str(self.opponent_change_count)) self.config.set_record(OpponentRefresh_Count=self.opponent_change_count)
self.config.save()
self.ensure_no_info_bar(timeout=3) self.ensure_no_info_bar(timeout=3)
def _opponent_fleet_check_all(self): def _opponent_fleet_check_all(self):
if self.config.EXERCISE_CHOOSE_MODE != 'leftmost': if self.config.Exercise_OpponentChooseMode != 'leftmost':
super()._opponent_fleet_check_all() super()._opponent_fleet_check_all()
def _opponent_sort(self): def _opponent_sort(self, method=None):
if self.config.EXERCISE_CHOOSE_MODE != 'leftmost': if method is None:
return super()._opponent_sort() method = self.config.Exercise_OpponentChooseMode
if method != 'leftmost':
return super()._opponent_sort(method=method)
else: else:
return [0, 1, 2 ,3] return [0, 1, 2, 3]
def _exercise_once(self): def _exercise_once(self):
"""Execute exercise once. """Execute exercise once.
@ -48,6 +47,7 @@ class Exercise(ExerciseCombat):
self._opponent_fleet_check_all() self._opponent_fleet_check_all()
while 1: while 1:
for opponent in self._opponent_sort(): for opponent in self._opponent_sort():
logger.hr(f'Opponent {opponent}', level=2)
success = self._combat(opponent) success = self._combat(opponent)
if success: if success:
return success return success
@ -66,14 +66,17 @@ class Exercise(ExerciseCombat):
Returns: Returns:
bool: True if success to defeat one opponent. False if failed to defeat any opponent and refresh exhausted. bool: True if success to defeat one opponent. False if failed to defeat any opponent and refresh exhausted.
""" """
restore = 0 method = "easiest_else_exp"
restore = self.config.Exercise_LowHpThreshold
threshold = self.config.Exercise_LowHpThreshold
self._opponent_fleet_check_all() self._opponent_fleet_check_all()
while 1: while 1:
opponents = self._opponent_sort() opponents = self._opponent_sort(method=method)
logger.hr(f'Opponent {opponents[0]}', level=2)
self.config.override(Exercise_LowHpThreshold=threshold)
success = self._combat(opponents[0]) success = self._combat(opponents[0])
if success: if success:
self.config.EXERCISE_CHOOSE_MODE = "easiest_else_exp" self.config.override(Exercise_LowHpThreshold=restore)
self.config.LOW_HP_THRESHOLD = restore if not self.config.LOW_HP_THRESHOLD else self.config.LOW_HP_THRESHOLD
return success return success
else: else:
if self.opponent_change_count < 5: if self.opponent_change_count < 5:
@ -83,9 +86,8 @@ class Exercise(ExerciseCombat):
continue continue
else: else:
logger.info("Cannot beat calculated easiest opponent, MAX EXP then") logger.info("Cannot beat calculated easiest opponent, MAX EXP then")
self.config.EXERCISE_CHOOSE_MODE = "max_exp" method = "max_exp"
restore = self.config.LOW_HP_THRESHOLD threshold = 0
self.config.LOW_HP_THRESHOLD = 0
def _get_opponent_change_count(self): def _get_opponent_change_count(self):
""" """
@ -95,29 +97,28 @@ class Exercise(ExerciseCombat):
Returns: Returns:
int: int:
""" """
record = datetime.strptime(self.config.config.get(*RECORD_OPTION), self.config.TIME_FORMAT) record = self.config.OpponentRefresh_Record
update = self.config.get_server_last_update(RECORD_SINCE) update = get_server_next_update('00:00') - timedelta(days=1)
if record.date() == update.date(): if record.date() == update.date():
# Same Day # Same Day
return self.config.config.getint(*RECORD_COUNT, fallback=6) return self.config.OpponentRefresh_Count
else: else:
# New Day # New Day
self.config.set_record(OpponentRefresh_Count=0)
return 0 return 0
def run(self): def run(self):
self.ui_ensure(page_exercise) self.ui_ensure(page_exercise)
logger.hr('Exercise', level=1)
self.opponent_change_count = self._get_opponent_change_count() self.opponent_change_count = self._get_opponent_change_count()
logger.attr("Change_opponent_count", self.opponent_change_count) logger.attr("Change_opponent_count", self.opponent_change_count)
while 1: while 1:
self.device.screenshot()
self.remain = OCR_EXERCISE_REMAIN.ocr(self.device.image) self.remain = OCR_EXERCISE_REMAIN.ocr(self.device.image)
if self.remain <= self.config.EXERCISE_PRESERVE: if self.remain <= self.config.Exercise_ExercisePreserve:
break break
logger.hr('Remain: %s' % self.remain) logger.hr(f'Exercise remain {self.remain}', level=1)
if self.config.EXERCISE_CHOOSE_MODE == "easiest_else_exp": if self.config.Exercise_OpponentChooseMode == "easiest_else_exp":
success = self._exercise_easiest_else_exp() success = self._exercise_easiest_else_exp()
else: else:
success = self._exercise_once() success = self._exercise_once()
@ -125,14 +126,11 @@ class Exercise(ExerciseCombat):
logger.info('New opponent exhausted') logger.info('New opponent exhausted')
break break
self.equipment_take_off_when_finished() # self.equipment_take_off_when_finished()
def record_executed_since(self): # Scheduler
return self.config.record_executed_since(option=RECORD_OPTION, since=RECORD_SINCE) self.config.set_record(OpponentRefresh_Count=self.opponent_change_count)
if self.remain <= self.config.Exercise_ExercisePreserve or self.opponent_change_count >= 5:
def record_save(self): self.config.task_delay(server_update=True)
self.config.config.set(*RECORD_COUNT, str(self.opponent_change_count))
if self.remain <= self.config.EXERCISE_PRESERVE or self.opponent_change_count >= 5:
return self.config.record_save(option=RECORD_OPTION)
else: else:
self.config.save() self.config.task_delay(success=False)

View File

@ -57,7 +57,7 @@ class HpDaemon(ModuleBase):
def _at_low_hp(self, image): def _at_low_hp(self, image):
self.attacker_hp = self._calculate_hp(image, area=ATTACKER_HP_AREA.area, reverse=True) self.attacker_hp = self._calculate_hp(image, area=ATTACKER_HP_AREA.area, reverse=True)
self.defender_hp = self._calculate_hp(image, area=DEFENDER_HP_AREA.area, reverse=False) self.defender_hp = self._calculate_hp(image, area=DEFENDER_HP_AREA.area, reverse=False)
if 0.01 < self.attacker_hp <= self.config.LOW_HP_THRESHOLD: if 0.01 < self.attacker_hp <= self.config.Exercise_LowHpThreshold:
if self.low_hp_confirm_timer.reached() and self.low_hp_confirm_timer.current() < 300: if self.low_hp_confirm_timer.reached() and self.low_hp_confirm_timer.current() < 300:
self._show_hp(self.low_hp_confirm_timer.current()) self._show_hp(self.low_hp_confirm_timer.current())
return True return True

View File

@ -110,12 +110,15 @@ class OpponentChoose(UI):
self.ui_click(click_button=BACK_ARROW, check_button=NEW_OPPONENT, self.ui_click(click_button=BACK_ARROW, check_button=NEW_OPPONENT,
appear_button=EXERCISE_PREPARATION, skip_first_screenshot=True) appear_button=EXERCISE_PREPARATION, skip_first_screenshot=True)
def _opponent_sort(self): def _opponent_sort(self, method="max_exp"):
""" """
Args:
method: EXERCISE_CHOOSE_MODE
Returns: Returns:
list[int]: List of opponent index, such as [2, 1, 0, 3]. list[int]: List of opponent index, such as [2, 1, 0, 3].
Attack one by one. Attack one by one.
""" """
order = np.argsort([- x.get_priority(self.config.EXERCISE_CHOOSE_MODE) for x in self.opponents]) order = np.argsort([- x.get_priority(method) for x in self.opponents])
logger.attr('Order', str(order)) logger.attr('Order', str(order))
return order return order