StarRailCopilot/tasks/assignment/dispatch.py

219 lines
8.1 KiB
Python
Raw Normal View History

2023-06-19 00:39:41 +00:00
from datetime import datetime, timedelta
from module.base.base import ModuleBase
2023-06-19 00:39:41 +00:00
from module.base.timer import Timer
from module.config.stored.classes import now
2023-06-19 00:39:41 +00:00
from module.logger import logger
from module.ui.switch import Switch
2023-06-19 00:39:41 +00:00
from tasks.assignment.assets.assets_assignment_dispatch import *
from tasks.assignment.assets.assets_assignment_ui import DISPATCHED
from tasks.assignment.keywords import *
from tasks.assignment.ui import AssignmentUI
class AssignmentSwitch(Switch):
def __init__(self, name, active_color: tuple[int, int, int], is_selector=True):
super().__init__(name, is_selector)
self.active_color = active_color
def get(self, main: ModuleBase):
"""
Use image_color_count instead to determine whether the button is selected/active
Args:
main (ModuleBase):
Returns:
str: state name or 'unknown'.
"""
for data in self.state_list:
if main.image_color_count(data['check_button'], self.active_color):
return data['state']
return 'unknown'
2023-06-19 00:39:41 +00:00
ASSIGNMENT_DURATION_SWITCH = AssignmentSwitch(
'AssignmentDurationSwitch',
(160, 130, 100)
)
ASSIGNMENT_DURATION_SWITCH.add_state('4', DURATION_4)
ASSIGNMENT_DURATION_SWITCH.add_state('8', DURATION_8)
ASSIGNMENT_DURATION_SWITCH.add_state('12', DURATION_12)
ASSIGNMENT_DURATION_SWITCH.add_state('20', DURATION_20)
class AssignmentDispatch(AssignmentUI):
dispatched: dict[AssignmentEntry, datetime] = dict()
has_new_dispatch: bool = False
2023-06-19 00:39:41 +00:00
2023-09-26 07:06:43 +00:00
def dispatch(self, assignment: AssignmentEntry, duration: int | None):
2023-06-19 00:39:41 +00:00
"""
2023-06-19 17:00:34 +00:00
Dispatch assignment.
Should be called only when limit is checked
2023-06-19 00:39:41 +00:00
Args:
assignment (AssignmentEntry):
2023-09-26 07:06:43 +00:00
duration (int | None): user specified duration, None for event assignments
2023-06-19 00:39:41 +00:00
Pages:
in: EMPTY_SLOT
2023-06-19 17:00:34 +00:00
out: DISPATCHED
2023-06-19 00:39:41 +00:00
"""
self._select_characters()
2023-09-26 07:06:43 +00:00
if isinstance(assignment, AssignmentEventEntry):
self._select_support()
duration = self._get_assignment_time().total_seconds() / 3600
else:
self._select_duration(duration)
self._confirm_assignment()
self._wait_until_assignment_started()
future = now() + timedelta(hours=duration)
logger.info(f'Assignment dispatched, will finish at {future}')
self.dispatched[assignment] = future
self.has_new_dispatch = True
2023-06-19 00:39:41 +00:00
def _select_characters(self):
"""
Pages:
in: EMPTY_SLOT
out: EMPTY_SLOT
2023-06-19 00:39:41 +00:00
"""
logger.info('Select characters')
2023-06-19 00:39:41 +00:00
skip_first_screenshot = True
self.interval_clear(
(CHARACTER_LIST, CHARACTER_1_SELECTED, CHARACTER_2_SELECTED), interval=2)
2023-06-19 00:39:41 +00:00
while 1:
if skip_first_screenshot:
skip_first_screenshot = False
else:
self.device.screenshot()
# End
if self.appear(CONFIRM_ASSIGNMENT):
if self.image_color_count(CONFIRM_ASSIGNMENT.button, color=(227, 227, 227), count=1000):
logger.info('Characters are all selected (light button)')
break
if self.image_color_count(CONFIRM_ASSIGNMENT.button, color=(144, 144, 144), count=1000):
logger.info('Characters are all selected (gray button)')
break
2023-06-19 00:39:41 +00:00
# Ensure character list
# Search EMPTY_SLOT to load offset
if not self.appear(CHARACTER_LIST) and self.appear(EMPTY_SLOT):
if self.interval_is_reached(CHARACTER_LIST, interval=2):
2023-06-19 00:39:41 +00:00
self.device.click(EMPTY_SLOT)
self.interval_reset(CHARACTER_LIST, interval=2)
2023-06-19 00:39:41 +00:00
continue
# Select
if self.interval_is_reached(CHARACTER_1_SELECTED, interval=2):
if not self.image_color_count(CHARACTER_1_SELECTED, (240, 240, 240), threshold=221, count=160):
self.device.click(CHARACTER_1)
self.interval_reset(CHARACTER_1_SELECTED, interval=2)
if self.interval_is_reached(CHARACTER_2_SELECTED, interval=2):
if not self.image_color_count(CHARACTER_2_SELECTED, (240, 240, 240), threshold=221, count=160):
self.device.click(CHARACTER_2)
self.interval_reset(CHARACTER_2_SELECTED, interval=2)
2023-06-19 00:39:41 +00:00
# CHARACTER_LIST -> CONFIRM_ASSIGNMENT
logger.info('Close character list')
self.interval_clear([CHARACTER_LIST, EMPTY_SLOT], interval=2)
skip_first_screenshot = True
while 1:
if skip_first_screenshot:
skip_first_screenshot = False
else:
self.device.screenshot()
# End
if self.appear(CONFIRM_ASSIGNMENT):
if self.image_color_count(CONFIRM_ASSIGNMENT.button, color=(227, 227, 227), count=1000):
logger.info(
'Characters are all selected (light button)')
break
if self.appear(CHARACTER_LIST, interval=2):
# EMPTY_SLOT appeared above
self.device.click(EMPTY_SLOT)
continue
2023-09-26 07:06:43 +00:00
def _select_support(self):
skip_first_screenshot = True
self.interval_clear(
(CHARACTER_SUPPORT_LIST, CHARACTER_SUPPORT_SELECTED), interval=2)
while 1:
if skip_first_screenshot:
skip_first_screenshot = False
else:
self.device.screenshot()
# End
if self.match_color(CHARACTER_SUPPORT_SELECTED):
logger.info('Support character is selected')
break
# Ensure support list
if not self.appear(CHARACTER_SUPPORT_LIST):
if self.interval_is_reached(CHARACTER_SUPPORT_LIST, interval=2):
self.device.click(EMPTY_SLOT_SUPPORT)
self.interval_reset(CHARACTER_SUPPORT_LIST, interval=2)
2023-09-26 07:06:43 +00:00
continue
# Select
if self.interval_is_reached(CHARACTER_SUPPORT_SELECTED, interval=2):
self.device.click(CHARACTER_SUPPORT)
self.interval_reset(CHARACTER_SUPPORT_SELECTED, interval=2)
2023-09-26 07:06:43 +00:00
2023-06-19 00:39:41 +00:00
def _select_duration(self, duration: int):
if duration not in {4, 8, 12, 20}:
logger.warning(
f'Duration {duration} is out of scope, reset it to 20')
duration = 20
ASSIGNMENT_DURATION_SWITCH.set(str(duration), self)
def _confirm_assignment(self):
2023-06-19 00:39:41 +00:00
"""
Pages:
in: CONFIRM_ASSIGNMENT
2023-06-19 00:39:41 +00:00
out: DISPATCHED
"""
skip_first_screenshot = True
while 1:
if skip_first_screenshot:
skip_first_screenshot = False
else:
self.device.screenshot()
# End
if self.appear(DISPATCHED):
logger.info(f'Assignment dispatched')
break
2023-06-19 00:39:41 +00:00
# Click
if self.appear_then_click(CONFIRM_ASSIGNMENT, interval=2):
2023-06-19 00:39:41 +00:00
continue
def _wait_until_assignment_started(self):
"""
Pages:
in: DISPATCHED
out: ASSIGNMENT_STARTED_CHECK
"""
skip_first_screenshot = True
timeout = Timer(2, count=4).start()
while 1:
if skip_first_screenshot:
skip_first_screenshot = False
else:
self.device.screenshot()
# End
if self.appear(ASSIGNMENT_START):
logger.info('Assignment start')
break
# Timeout
if timeout.reached():
logger.warning('Wait for assignment start timeout')
break
skip_first_screenshot = True
while 1:
if skip_first_screenshot:
skip_first_screenshot = False
else:
self.device.screenshot()
# End
2023-09-27 05:53:15 +00:00
if self.match_color(ASSIGNMENT_STARTED_CHECK):
logger.info('Assignment started')
break