StarRailCopilot/tasks/map/route/loader.py

105 lines
3.4 KiB
Python
Raw Normal View History

2023-09-23 11:19:53 +00:00
import importlib
import os
2023-09-23 22:52:52 +00:00
from module.base.decorator import del_cached_property
2023-11-28 17:40:08 +00:00
from module.exception import GameStuckError, GameTooManyClickError, ScriptError
2023-09-23 11:19:53 +00:00
from module.logger import logger
from tasks.base.ui import UI
2023-10-01 15:03:57 +00:00
from tasks.map.route.base import RouteBase
from tasks.map.route.model import RouteModel
def empty_function(*arg, **kwargs):
return False
2023-09-23 11:19:53 +00:00
class RouteLoader(UI):
2023-09-23 22:52:52 +00:00
route_module: str = ''
route_func: str = ''
route_obj: RouteBase
2023-09-23 11:19:53 +00:00
2023-09-23 22:52:52 +00:00
def route_delete(self):
del_cached_property(self, 'route_obj')
self.route_module = ''
self.route_func = ''
2023-10-01 15:03:57 +00:00
def route_run(self, route: RouteModel | str):
2023-09-23 11:19:53 +00:00
"""
Args:
2023-09-23 22:52:52 +00:00
route: .py module path such as `route.daily.ForgottenHallStage1:route`
which will load `./route/daily/ForgottenHallStage1.py` and run `Route.route()`
2023-09-23 11:19:53 +00:00
"""
2023-09-23 22:52:52 +00:00
logger.hr('Route run', level=1)
2023-10-01 15:03:57 +00:00
if isinstance(route, RouteModel):
2023-09-23 22:52:52 +00:00
route = route.route
logger.attr('Route', route)
try:
module, func = route.split(':')
except ValueError:
logger.critical(f'Route invalid: {route}')
raise ScriptError
path = f'./{module.replace(".", "/")}.py'
# Import route file
2023-09-23 11:19:53 +00:00
try:
2023-09-23 22:52:52 +00:00
module_obj = importlib.import_module(f'{module}')
2023-09-23 11:19:53 +00:00
except ModuleNotFoundError:
2023-09-23 22:52:52 +00:00
logger.critical(f'Route file not found: {module} ({path})')
2023-09-23 11:19:53 +00:00
if not os.path.exists(path):
logger.critical(f'Route file not exists: {path}')
2023-09-23 22:52:52 +00:00
raise ScriptError
2023-09-23 11:19:53 +00:00
2023-09-23 22:52:52 +00:00
# Create route object
# Reuse the previous one
if self.route_module != module:
# config = copy.deepcopy(self.config).merge(module.Config())
config = self.config
device = self.device
try:
self.route_obj = module_obj.Route(config=config, device=device)
except AttributeError as e:
logger.critical(e)
logger.critical(f'Route file {route} ({path}) must define class Route')
raise ScriptError
self.route_module = module
self.route_obj.route_module = module
2023-09-23 22:52:52 +00:00
self.route_obj.plane = self.plane
2023-10-01 15:03:57 +00:00
# before_route()
try:
before_func_obj = self.route_obj.__getattribute__('before_route')
except AttributeError:
before_func_obj = empty_function
2023-12-06 08:55:59 +00:00
try:
before_func_obj()
except (GameStuckError, GameTooManyClickError):
logger.error(f'Route failed: {route}')
raise
2023-10-01 15:03:57 +00:00
# Run route
2023-09-23 11:19:53 +00:00
try:
2023-09-23 22:52:52 +00:00
func_obj = self.route_obj.__getattribute__(func)
2023-09-23 11:19:53 +00:00
except AttributeError as e:
logger.critical(e)
2023-09-23 22:52:52 +00:00
logger.critical(f'Route class in {route} ({path}) does not have method {func}')
raise ScriptError
2023-12-06 08:55:59 +00:00
self.route_func = func
self.route_obj.route_func = func
try:
func_obj()
2023-11-28 17:40:08 +00:00
except (GameStuckError, GameTooManyClickError):
logger.error(f'Route failed: {route}')
raise
2023-10-01 15:03:57 +00:00
# after_route()
try:
after_route_obj = self.route_obj.__getattribute__('after_route')
except AttributeError:
after_route_obj = empty_function
2023-12-06 08:55:59 +00:00
try:
after_route_obj()
except (GameStuckError, GameTooManyClickError):
logger.error(f'Route failed: {route}')
raise