mirror of
https://github.com/LmeSzinc/StarRailCopilot.git
synced 2024-11-25 10:01:10 +00:00
Refactor: More compact route files
This commit is contained in:
parent
6eb9317ac4
commit
3fa28fba24
89
dev_tools/route_extract.py
Normal file
89
dev_tools/route_extract.py
Normal file
@ -0,0 +1,89 @@
|
|||||||
|
import os
|
||||||
|
import re
|
||||||
|
from dataclasses import dataclass, fields
|
||||||
|
|
||||||
|
from module.base.code_generator import CodeGenerator
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class RouteData:
|
||||||
|
name: str
|
||||||
|
route: str
|
||||||
|
plane: str
|
||||||
|
floor: str = 'F1'
|
||||||
|
position: tuple = None
|
||||||
|
|
||||||
|
|
||||||
|
class RouteExtract:
|
||||||
|
def __init__(self, folder):
|
||||||
|
self.folder = folder
|
||||||
|
|
||||||
|
def iter_files(self):
|
||||||
|
for path, folders, files in os.walk(self.folder):
|
||||||
|
path = path.replace('\\', '/')
|
||||||
|
for file in files:
|
||||||
|
if file.endswith('.py'):
|
||||||
|
yield f'{path}/{file}'
|
||||||
|
|
||||||
|
def extract_route(self, file):
|
||||||
|
print(f'Extract {file}')
|
||||||
|
with open(file, 'r', encoding='utf-8') as f:
|
||||||
|
content = f.read()
|
||||||
|
|
||||||
|
"""
|
||||||
|
def route_item_enemy(self):
|
||||||
|
self.enter_himeko_trial()
|
||||||
|
self.map_init(plane=Jarilo_BackwaterPass, position=(519.9, 361.5))
|
||||||
|
"""
|
||||||
|
regex = re.compile(
|
||||||
|
r'def (?P<func>[a-zA-Z0-9_]*?)\(self\):.*?'
|
||||||
|
r'self\.map_init\((.*?)\)'
|
||||||
|
, re.DOTALL)
|
||||||
|
file = file.replace(self.folder, '').replace('.py', '').replace('/', '_').strip('_')
|
||||||
|
module = f"{self.folder.strip('./').replace('/', '.')}.{file.replace('_', '.')}"
|
||||||
|
|
||||||
|
for result in regex.findall(content):
|
||||||
|
func, data = result
|
||||||
|
|
||||||
|
res = re.search(r'plane=([a-zA-Z_]*)', data)
|
||||||
|
if res:
|
||||||
|
plane = res.group(1)
|
||||||
|
else:
|
||||||
|
# Must contain plane
|
||||||
|
continue
|
||||||
|
res = re.search(r'floor=([\'"a-zA-Z0-9_]*)', data)
|
||||||
|
if res:
|
||||||
|
floor = res.group(1).strip('"\'')
|
||||||
|
else:
|
||||||
|
floor = 'F1'
|
||||||
|
res = re.search(r'position=\(([0-9.]*)[, ]+([0-9.]*)', data)
|
||||||
|
if res:
|
||||||
|
position = (float(res.group(1)), float(res.group(2)))
|
||||||
|
else:
|
||||||
|
position = None
|
||||||
|
|
||||||
|
yield RouteData(
|
||||||
|
name=f'{file}__{func}',
|
||||||
|
route=f'{module}:{func}',
|
||||||
|
plane=plane,
|
||||||
|
floor=floor,
|
||||||
|
position=position,
|
||||||
|
)
|
||||||
|
|
||||||
|
def write(self, file):
|
||||||
|
gen = CodeGenerator()
|
||||||
|
gen.Import("""
|
||||||
|
from tasks.map.route.base import RouteData
|
||||||
|
""")
|
||||||
|
for f in self.iter_files():
|
||||||
|
for row in self.extract_route(f):
|
||||||
|
with gen.Object(key=row.name, object_class='RouteData'):
|
||||||
|
for key in fields(row):
|
||||||
|
value = getattr(row, key.name)
|
||||||
|
gen.ObjectAttr(key.name, value)
|
||||||
|
gen.write(file)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
os.chdir(os.path.join(os.path.dirname(__file__), '../'))
|
||||||
|
RouteExtract('./route/daily').write('./tasks/map/route/route/daily.py')
|
@ -23,6 +23,7 @@ from tasks.dungeon.ui import DungeonUI
|
|||||||
from tasks.item.consumable_usage import ConsumableUsageUI
|
from tasks.item.consumable_usage import ConsumableUsageUI
|
||||||
from tasks.item.relics import RelicsUI
|
from tasks.item.relics import RelicsUI
|
||||||
from tasks.map.route.loader import RouteLoader
|
from tasks.map.route.loader import RouteLoader
|
||||||
|
from tasks.map.route.route import ROUTE_DAILY
|
||||||
|
|
||||||
|
|
||||||
class DailyQuestOcr(Ocr):
|
class DailyQuestOcr(Ocr):
|
||||||
@ -260,7 +261,7 @@ class DailyQuestUI(DungeonUI, RouteLoader):
|
|||||||
if RelicsUI(self.config, self.device).salvage_relic():
|
if RelicsUI(self.config, self.device).salvage_relic():
|
||||||
done += 1
|
done += 1
|
||||||
if KEYWORDS_DAILY_QUEST.Complete_Forgotten_Hall_1_time in quests:
|
if KEYWORDS_DAILY_QUEST.Complete_Forgotten_Hall_1_time in quests:
|
||||||
self.route_run('daily.forgotten_hall.stage_1')
|
self.route_run(ROUTE_DAILY.ForgottenHallStage1__route)
|
||||||
done += 1
|
done += 1
|
||||||
|
|
||||||
return done
|
return done
|
||||||
|
@ -1,8 +1,19 @@
|
|||||||
|
from dataclasses import dataclass
|
||||||
|
|
||||||
from tasks.map.control.control import MapControl
|
from tasks.map.control.control import MapControl
|
||||||
from tasks.map.control.waypoint import Waypoint
|
from tasks.map.control.waypoint import Waypoint
|
||||||
from tasks.map.keywords import MapPlane
|
from tasks.map.keywords import MapPlane
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class RouteData:
|
||||||
|
name: str
|
||||||
|
route: str
|
||||||
|
plane: str
|
||||||
|
floor: str = 'F1'
|
||||||
|
position: tuple = None
|
||||||
|
|
||||||
|
|
||||||
class RouteBase(MapControl):
|
class RouteBase(MapControl):
|
||||||
"""
|
"""
|
||||||
Base class of `Route`
|
Base class of `Route`
|
||||||
|
@ -1,38 +1,71 @@
|
|||||||
import importlib
|
import importlib
|
||||||
import os
|
import os
|
||||||
|
|
||||||
from module.exception import RequestHumanTakeover
|
from module.base.decorator import del_cached_property
|
||||||
|
from module.exception import ScriptError
|
||||||
from module.logger import logger
|
from module.logger import logger
|
||||||
from tasks.base.ui import UI
|
from tasks.base.ui import UI
|
||||||
from tasks.map.route.base import RouteBase
|
from tasks.map.route.base import RouteBase, RouteData
|
||||||
|
|
||||||
|
|
||||||
class RouteLoader(UI):
|
class RouteLoader(UI):
|
||||||
route: RouteBase
|
route_module: str = ''
|
||||||
|
route_func: str = ''
|
||||||
|
route_obj: RouteBase
|
||||||
|
|
||||||
def route_run(self, route: str):
|
def route_delete(self):
|
||||||
|
del_cached_property(self, 'route_obj')
|
||||||
|
self.route_module = ''
|
||||||
|
self.route_func = ''
|
||||||
|
|
||||||
|
def route_run(self, route: RouteData | str):
|
||||||
"""
|
"""
|
||||||
Args:
|
Args:
|
||||||
route: .py module path such as `daily.forgotten_hall.stage1`
|
route: .py module path such as `route.daily.ForgottenHallStage1:route`
|
||||||
which will load `./route/daily/forgotten_hall/stage1.py`
|
which will load `./route/daily/ForgottenHallStage1.py` and run `Route.route()`
|
||||||
"""
|
"""
|
||||||
folder, name = route.rsplit('.', maxsplit=1)
|
logger.hr('Route run', level=1)
|
||||||
path = f'./route/{route.replace(".", "/")}.py'
|
if isinstance(route, RouteData):
|
||||||
|
route = route.route
|
||||||
|
logger.attr('Route', route)
|
||||||
try:
|
try:
|
||||||
module = importlib.import_module(f'route.{folder}.{name}')
|
module, func = route.split(':')
|
||||||
|
except ValueError:
|
||||||
|
logger.critical(f'Route invalid: {route}')
|
||||||
|
raise ScriptError
|
||||||
|
path = f'./{module.replace(".", "/")}.py'
|
||||||
|
|
||||||
|
# Import route file
|
||||||
|
try:
|
||||||
|
module_obj = importlib.import_module(f'{module}')
|
||||||
except ModuleNotFoundError:
|
except ModuleNotFoundError:
|
||||||
logger.critical(f'Route file not found: {route} ({path})')
|
logger.critical(f'Route file not found: {module} ({path})')
|
||||||
if not os.path.exists(path):
|
if not os.path.exists(path):
|
||||||
logger.critical(f'Route file not exists: {path}')
|
logger.critical(f'Route file not exists: {path}')
|
||||||
raise RequestHumanTakeover
|
raise ScriptError
|
||||||
|
|
||||||
# config = copy.deepcopy(self.config).merge(module.Config())
|
# Create route object
|
||||||
config = self.config
|
# Reuse the previous one
|
||||||
device = self.device
|
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
|
||||||
|
|
||||||
|
# Get route func
|
||||||
try:
|
try:
|
||||||
self.route = module.Route(config=config, device=device)
|
func_obj = self.route_obj.__getattribute__(func)
|
||||||
return self.route.route()
|
|
||||||
except AttributeError as e:
|
except AttributeError as e:
|
||||||
logger.critical(e)
|
logger.critical(e)
|
||||||
logger.critical(f'Route file {route} ({path}) must define Route.route()')
|
logger.critical(f'Route class in {route} ({path}) does not have method {func}')
|
||||||
raise RequestHumanTakeover
|
raise ScriptError
|
||||||
|
self.route_func = func
|
||||||
|
|
||||||
|
# Run
|
||||||
|
func_obj()
|
||||||
|
1
tasks/map/route/route/__init__.py
Normal file
1
tasks/map/route/route/__init__.py
Normal file
@ -0,0 +1 @@
|
|||||||
|
import tasks.map.route.route.daily as ROUTE_DAILY
|
38
tasks/map/route/route/daily.py
Normal file
38
tasks/map/route/route/daily.py
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
from tasks.map.route.base import RouteData
|
||||||
|
|
||||||
|
|
||||||
|
ForgottenHallStage1__route = RouteData(
|
||||||
|
name='ForgottenHallStage1__route',
|
||||||
|
route='route.daily.ForgottenHallStage1:route',
|
||||||
|
plane='Jarilo_BackwaterPass',
|
||||||
|
floor='F1',
|
||||||
|
position=(369.4, 643.4),
|
||||||
|
)
|
||||||
|
HimekoTrial__route_item_enemy = RouteData(
|
||||||
|
name='HimekoTrial__route_item_enemy',
|
||||||
|
route='route.daily.HimekoTrial:route_item_enemy',
|
||||||
|
plane='Jarilo_BackwaterPass',
|
||||||
|
floor='F1',
|
||||||
|
position=(519.9, 361.5),
|
||||||
|
)
|
||||||
|
HimekoTrial__route_item = RouteData(
|
||||||
|
name='HimekoTrial__route_item',
|
||||||
|
route='route.daily.HimekoTrial:route_item',
|
||||||
|
plane='Jarilo_BackwaterPass',
|
||||||
|
floor='F1',
|
||||||
|
position=(519.9, 361.5),
|
||||||
|
)
|
||||||
|
HimekoTrial__route_enemy = RouteData(
|
||||||
|
name='HimekoTrial__route_enemy',
|
||||||
|
route='route.daily.HimekoTrial:route_enemy',
|
||||||
|
plane='Jarilo_BackwaterPass',
|
||||||
|
floor='F1',
|
||||||
|
position=(519.9, 361.5),
|
||||||
|
)
|
||||||
|
HimekoTrial__exit = RouteData(
|
||||||
|
name='HimekoTrial__exit',
|
||||||
|
route='route.daily.HimekoTrial:exit',
|
||||||
|
plane='Jarilo_BackwaterPass',
|
||||||
|
floor='F1',
|
||||||
|
position=(519.9, 361.5),
|
||||||
|
)
|
Loading…
Reference in New Issue
Block a user