feat(core): 为 Task 类新增 id 字段

This commit is contained in:
XcantloadX 2025-04-11 09:57:39 +08:00
parent d5ff1f4af3
commit 2f68f406e1
6 changed files with 42 additions and 35 deletions

View File

@ -1,3 +1,3 @@
from .context import *
from .context import _c
from .task_action import task, action, task_registry, action_registry, current_callstack, Task, Action
from .task_action import task, action, task_registry, action_registry, current_callstack, Task, Action, tasks_from_id

View File

@ -8,6 +8,7 @@ from cv2.typing import MatLike
from .context import ContextStackVars, ScreenshotMode
from ..dispatch import dispatcher as dispatcher_decorator, DispatcherContext
from ...errors import TaskNotFoundError
P = ParamSpec('P')
R = TypeVar('R')
@ -16,6 +17,7 @@ logger = logging.getLogger(__name__)
@dataclass
class Task:
name: str
id: str
description: str
func: Callable
priority: int
@ -43,6 +45,7 @@ def _placeholder():
def task(
name: str,
task_id: str|None = None,
description: str|None = None,
*,
pass_through: bool = False,
@ -53,16 +56,21 @@ def task(
`task` 装饰器用于标记一个函数为任务函数
:param name: 任务名称
:param task_id: 任务 ID如果为 None则使用函数名称作为 ID
:param description: 任务描述如果为 None则使用函数的 docstring 作为描述
:param pass_through:
默认情况下 @task 装饰器会包裹任务函数跟踪其执行情况
如果不想跟踪则设置此参数为 False
:param priority: 任务优先级数字越大优先级越高
"""
# 设置 ID
# 获取 caller 信息
def _task_decorator(func: Callable[P, R]) -> Callable[P, R]:
nonlocal description
nonlocal description, task_id
description = description or func.__doc__ or ''
task = Task(name, description, _placeholder, priority)
# TODO: task_id 冲突检测
task_id = task_id or func.__name__
task = Task(name, task_id, description, _placeholder, priority)
task_registry[name] = task
logger.debug(f'Task "{name}" registered.')
if pass_through:
@ -195,3 +203,11 @@ def action(*args, **kwargs):
return _wrapper
return _action_decorator
def tasks_from_id(task_ids: list[str]) -> list[Task]:
result = []
for tid in task_ids:
target = next(task for task in task_registry.values() if task.id == tid)
if target is None:
raise TaskNotFoundError(f'Task "{tid}" not found.')
result.append(target)
return result

View File

@ -18,4 +18,9 @@ class ResourceFileMissingError(KotonebotError):
def __init__(self, file_path: str, description: str):
self.file_path = file_path
self.description = description
super().__init__(f'Resource file ({description}) "{file_path}" is missing.')
super().__init__(f'Resource file ({description}) "{file_path}" is missing.')
class TaskNotFoundError(KotonebotError):
def __init__(self, task_id: str):
self.task_id = task_id
super().__init__(f'Task "{task_id}" not found.')

View File

@ -71,16 +71,16 @@ def get_capsule_toys_draw_buttons():
def capsule_toys():
"""
扭蛋机支持任意次数的任意扭蛋类型
自动化思路\n
进入扭蛋机页面后可以发现扭蛋机总共有4种类型\n
通过硬编码的滑动翻页把每两种扭蛋分为同一页
第一页好友扭蛋+感性扭蛋
第二页逻辑扭蛋+非凡扭蛋\n
划到某一页之后识别截图中所有抽扭蛋按钮再按照y轴排序即可以实现选择扭蛋类型
"""
#[screenshots/shop/capsule_toys_upper.png]
#[screenshots/shop/capsule_toys_lower.png]
# 自动化思路:
# 进入扭蛋机页面后可以发现扭蛋机总共有4种类型。
# 通过硬编码的滑动翻页,把每两种扭蛋分为同一页。
# 第一页:好友扭蛋+感性扭蛋;
# 第二页:逻辑扭蛋+非凡扭蛋。
# 划到某一页之后识别截图中所有“抽扭蛋”按钮再按照y轴排序即可以实现选择扭蛋类型。
# [screenshots/shop/capsule_toys_upper.png]
# [screenshots/shop/capsule_toys_lower.png]
if not conf().capsule_toys.enabled:
logger.info('"Capsule Toys" is disabled.')

View File

@ -13,11 +13,10 @@ logger = logging.getLogger(__name__)
def upgrade_support_card():
"""
升级一张支援卡优先升级低等级支援卡
自动化思路是这样的
进入支援卡页面后一直往下滑滑倒底部低等级支援卡区域
然后点击左上角第一张支援卡将左上角第一张支援卡提升一级
"""
# 自动化思路是这样的:
# 进入支援卡页面后,一直往下滑,滑倒底部(低等级支援卡区域);
# 然后点击左上角第一张支援卡,将左上角第一张支援卡提升一级。
if not conf().upgrade_support_card.enabled:
logger.info('"Upgrade support card" is disabled.')

View File

@ -287,31 +287,18 @@ def do_produce(
return True
@task('培育')
def produce_task(
mode: Optional[Literal['regular', 'pro']] = None,
count: Optional[int] = None,
idols: Optional[list[str]] = None,
memory_sets: Optional[list[int]] = None
):
def produce():
"""
培育任务
:param mode: 培育模式若为 None则从配置文件中读入
:param count: 培育次数若为 None则从配置文件中读入
:param idols: 要培育的偶像的 IdolCardSkin.id若为 None则从配置文件中读入
"""
if not conf().produce.enabled:
logger.info('Produce is disabled.')
return
import time
if count is None:
count = conf().produce.produce_count
if idols is None:
idols = conf().produce.idols
if memory_sets is None:
memory_sets = conf().produce.memory_sets
if mode is None:
mode = conf().produce.mode
count = conf().produce.produce_count
idols = conf().produce.idols
memory_sets = conf().produce.memory_sets
mode = conf().produce.mode
# 数据验证
if count < 0:
user.warning('配置有误', '培育次数不能小于 0。将跳过本次培育。')