feat(task): 配置中支持储存多个培育方案并支持来回切换
This commit is contained in:
parent
4e4b91d670
commit
41e7c8b4a8
|
@ -10,6 +10,7 @@ kotonebot-ui/.vite
|
||||||
dumps*/
|
dumps*/
|
||||||
config.json
|
config.json
|
||||||
config.v*.json
|
config.v*.json
|
||||||
|
conf/
|
||||||
reports/
|
reports/
|
||||||
tmp/
|
tmp/
|
||||||
res/sprites_compiled/
|
res/sprites_compiled/
|
||||||
|
|
|
@ -0,0 +1,221 @@
|
||||||
|
import os
|
||||||
|
import json
|
||||||
|
import uuid
|
||||||
|
import re
|
||||||
|
import logging
|
||||||
|
from typing import Literal
|
||||||
|
from pydantic import BaseModel, ConfigDict
|
||||||
|
|
||||||
|
from .const import ProduceAction, RecommendCardDetectionMode
|
||||||
|
|
||||||
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
class ConfigBaseModel(BaseModel):
|
||||||
|
model_config = ConfigDict(use_attribute_docstrings=True)
|
||||||
|
|
||||||
|
|
||||||
|
class ProduceData(ConfigBaseModel):
|
||||||
|
enabled: bool = False
|
||||||
|
"""是否启用培育"""
|
||||||
|
mode: Literal['regular', 'pro', 'master'] = 'regular'
|
||||||
|
"""
|
||||||
|
培育模式。
|
||||||
|
进行一次 REGULAR 培育需要 ~30min,进行一次 PRO 培育需要 ~1h(具体视设备性能而定)。
|
||||||
|
"""
|
||||||
|
produce_count: int = 1
|
||||||
|
"""培育的次数。"""
|
||||||
|
idols: list[str] = []
|
||||||
|
"""
|
||||||
|
要培育偶像的 IdolCardSkin.id。将会按顺序循环选择培育。
|
||||||
|
"""
|
||||||
|
memory_sets: list[int] = []
|
||||||
|
"""要使用的回忆编成编号,从 1 开始。将会按顺序循环选择使用。"""
|
||||||
|
support_card_sets: list[int] = []
|
||||||
|
"""要使用的支援卡编成编号,从 1 开始。将会按顺序循环选择使用。"""
|
||||||
|
auto_set_memory: bool = False
|
||||||
|
"""是否自动编成回忆。此选项优先级高于回忆编成编号。"""
|
||||||
|
auto_set_support_card: bool = False
|
||||||
|
"""是否自动编成支援卡。此选项优先级高于支援卡编成编号。"""
|
||||||
|
use_pt_boost: bool = False
|
||||||
|
"""是否使用支援强化 Pt 提升。"""
|
||||||
|
use_note_boost: bool = False
|
||||||
|
"""是否使用笔记数提升。"""
|
||||||
|
follow_producer: bool = False
|
||||||
|
"""是否关注租借了支援卡的制作人。"""
|
||||||
|
self_study_lesson: Literal['dance', 'visual', 'vocal'] = 'dance'
|
||||||
|
"""自习课类型。"""
|
||||||
|
prefer_lesson_ap: bool = False
|
||||||
|
"""
|
||||||
|
优先 SP 课程。
|
||||||
|
|
||||||
|
启用后,若出现 SP 课程,则会优先执行 SP 课程,而不是推荐课程。
|
||||||
|
若出现多个 SP 课程,随机选择一个。
|
||||||
|
"""
|
||||||
|
actions_order: list[ProduceAction] = [
|
||||||
|
ProduceAction.RECOMMENDED,
|
||||||
|
ProduceAction.VISUAL,
|
||||||
|
ProduceAction.VOCAL,
|
||||||
|
ProduceAction.DANCE,
|
||||||
|
ProduceAction.ALLOWANCE,
|
||||||
|
ProduceAction.OUTING,
|
||||||
|
ProduceAction.STUDY,
|
||||||
|
ProduceAction.CONSULT,
|
||||||
|
ProduceAction.REST,
|
||||||
|
]
|
||||||
|
"""
|
||||||
|
行动优先级
|
||||||
|
|
||||||
|
每一周的行动将会按这里设置的优先级执行。
|
||||||
|
"""
|
||||||
|
recommend_card_detection_mode: RecommendCardDetectionMode = RecommendCardDetectionMode.NORMAL
|
||||||
|
"""
|
||||||
|
推荐卡检测模式
|
||||||
|
|
||||||
|
严格模式下,识别速度会降低,但识别准确率会提高。
|
||||||
|
"""
|
||||||
|
use_ap_drink: bool = False
|
||||||
|
"""
|
||||||
|
AP 不足时自动使用 AP 饮料
|
||||||
|
"""
|
||||||
|
skip_commu: bool = True
|
||||||
|
"""检测并跳过交流"""
|
||||||
|
|
||||||
|
|
||||||
|
class ProduceSolution(ConfigBaseModel):
|
||||||
|
"""培育方案"""
|
||||||
|
id: str
|
||||||
|
"""方案唯一标识符"""
|
||||||
|
name: str
|
||||||
|
"""方案名称"""
|
||||||
|
description: str | None = None
|
||||||
|
"""方案描述"""
|
||||||
|
data: ProduceData
|
||||||
|
"""培育数据"""
|
||||||
|
|
||||||
|
|
||||||
|
class ProduceSolutionManager:
|
||||||
|
"""培育方案管理器"""
|
||||||
|
|
||||||
|
SOLUTIONS_DIR = "conf/produce"
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
"""初始化管理器,确保目录存在"""
|
||||||
|
os.makedirs(self.SOLUTIONS_DIR, exist_ok=True)
|
||||||
|
|
||||||
|
def _sanitize_filename(self, name: str) -> str:
|
||||||
|
"""
|
||||||
|
清理文件名中的非法字符
|
||||||
|
|
||||||
|
:param name: 原始名称
|
||||||
|
:return: 清理后的文件名
|
||||||
|
"""
|
||||||
|
# 替换 \/:*?"<>| 为下划线
|
||||||
|
return re.sub(r'[\\/:*?"<>|]', '_', name)
|
||||||
|
|
||||||
|
def _get_file_path(self, name: str) -> str:
|
||||||
|
"""
|
||||||
|
根据方案名称获取文件路径
|
||||||
|
|
||||||
|
:param name: 方案名称
|
||||||
|
:return: 文件路径
|
||||||
|
"""
|
||||||
|
safe_name = self._sanitize_filename(name)
|
||||||
|
return os.path.join(self.SOLUTIONS_DIR, f"{safe_name}.json")
|
||||||
|
|
||||||
|
def new(self, name: str) -> ProduceSolution:
|
||||||
|
"""
|
||||||
|
创建新的培育方案
|
||||||
|
|
||||||
|
:param name: 方案名称
|
||||||
|
:return: 新创建的方案
|
||||||
|
"""
|
||||||
|
solution = ProduceSolution(
|
||||||
|
id=uuid.uuid4().hex,
|
||||||
|
name=name,
|
||||||
|
data=ProduceData()
|
||||||
|
)
|
||||||
|
return solution
|
||||||
|
|
||||||
|
def list(self) -> list[ProduceSolution]:
|
||||||
|
"""
|
||||||
|
列出所有培育方案
|
||||||
|
|
||||||
|
:return: 方案列表
|
||||||
|
"""
|
||||||
|
solutions = []
|
||||||
|
if not os.path.exists(self.SOLUTIONS_DIR):
|
||||||
|
return solutions
|
||||||
|
|
||||||
|
for filename in os.listdir(self.SOLUTIONS_DIR):
|
||||||
|
if filename.endswith('.json'):
|
||||||
|
try:
|
||||||
|
file_path = os.path.join(self.SOLUTIONS_DIR, filename)
|
||||||
|
with open(file_path, 'r', encoding='utf-8') as f:
|
||||||
|
data = json.load(f)
|
||||||
|
solution = ProduceSolution.model_validate_json(data)
|
||||||
|
solutions.append(solution)
|
||||||
|
logger.info(f"Loaded produce solution from {file_path}")
|
||||||
|
except Exception:
|
||||||
|
logger.warning(f"Failed to load produce solution from {file_path}")
|
||||||
|
continue
|
||||||
|
|
||||||
|
return solutions
|
||||||
|
|
||||||
|
def delete(self, id: str) -> None:
|
||||||
|
"""
|
||||||
|
删除指定ID的培育方案
|
||||||
|
|
||||||
|
:param id: 方案ID
|
||||||
|
"""
|
||||||
|
if not os.path.exists(self.SOLUTIONS_DIR):
|
||||||
|
return
|
||||||
|
|
||||||
|
for filename in os.listdir(self.SOLUTIONS_DIR):
|
||||||
|
if filename.endswith('.json'):
|
||||||
|
try:
|
||||||
|
file_path = os.path.join(self.SOLUTIONS_DIR, filename)
|
||||||
|
with open(file_path, 'r', encoding='utf-8') as f:
|
||||||
|
data = json.load(f)
|
||||||
|
if data.get('id') == id:
|
||||||
|
os.remove(file_path)
|
||||||
|
return
|
||||||
|
except Exception:
|
||||||
|
continue
|
||||||
|
|
||||||
|
def save(self, id: str, solution: ProduceSolution) -> None:
|
||||||
|
"""
|
||||||
|
保存培育方案
|
||||||
|
|
||||||
|
:param id: 方案ID
|
||||||
|
:param solution: 方案对象
|
||||||
|
"""
|
||||||
|
# 确保ID一致
|
||||||
|
solution.id = id
|
||||||
|
|
||||||
|
file_path = self._get_file_path(solution.name)
|
||||||
|
with open(file_path, 'w', encoding='utf-8') as f:
|
||||||
|
json.dump(solution.model_dump_json(indent=4), f, ensure_ascii=False)
|
||||||
|
|
||||||
|
def read(self, id: str) -> ProduceSolution:
|
||||||
|
"""
|
||||||
|
读取指定ID的培育方案
|
||||||
|
|
||||||
|
:param id: 方案ID
|
||||||
|
:return: 方案对象
|
||||||
|
:raises FileNotFoundError: 当方案不存在时
|
||||||
|
"""
|
||||||
|
if not os.path.exists(self.SOLUTIONS_DIR):
|
||||||
|
raise FileNotFoundError(f"Solution with id '{id}' not found")
|
||||||
|
|
||||||
|
for filename in os.listdir(self.SOLUTIONS_DIR):
|
||||||
|
if filename.endswith('.json'):
|
||||||
|
try:
|
||||||
|
file_path = os.path.join(self.SOLUTIONS_DIR, filename)
|
||||||
|
with open(file_path, 'r', encoding='utf-8') as f:
|
||||||
|
data = json.load(f)
|
||||||
|
if data.get('id') == id:
|
||||||
|
return ProduceSolution.model_validate_json(data)
|
||||||
|
except Exception:
|
||||||
|
continue
|
||||||
|
|
||||||
|
raise FileNotFoundError(f"Solution with id '{id}' not found")
|
|
@ -2,13 +2,12 @@ from typing import TypeVar, Literal, Sequence
|
||||||
from pydantic import BaseModel, ConfigDict
|
from pydantic import BaseModel, ConfigDict
|
||||||
|
|
||||||
from kotonebot import config
|
from kotonebot import config
|
||||||
|
from kotonebot.kaa.config.produce import ProduceSolution, ProduceSolutionManager
|
||||||
from .const import (
|
from .const import (
|
||||||
ConfigEnum,
|
ConfigEnum,
|
||||||
Priority,
|
Priority,
|
||||||
APShopItems,
|
APShopItems,
|
||||||
DailyMoneyShopItems,
|
DailyMoneyShopItems,
|
||||||
ProduceAction,
|
|
||||||
RecommendCardDetectionMode,
|
|
||||||
)
|
)
|
||||||
|
|
||||||
T = TypeVar('T')
|
T = TypeVar('T')
|
||||||
|
@ -70,68 +69,8 @@ class ContestConfig(ConfigBaseModel):
|
||||||
class ProduceConfig(ConfigBaseModel):
|
class ProduceConfig(ConfigBaseModel):
|
||||||
enabled: bool = False
|
enabled: bool = False
|
||||||
"""是否启用培育"""
|
"""是否启用培育"""
|
||||||
mode: Literal['regular', 'pro', 'master'] = 'regular'
|
selected_solution_id: str | None = None
|
||||||
"""
|
"""选中的培育方案ID"""
|
||||||
培育模式。
|
|
||||||
进行一次 REGULAR 培育需要 ~30min,进行一次 PRO 培育需要 ~1h(具体视设备性能而定)。
|
|
||||||
"""
|
|
||||||
produce_count: int = 1
|
|
||||||
"""培育的次数。"""
|
|
||||||
idols: list[str] = []
|
|
||||||
"""
|
|
||||||
要培育偶像的 IdolCardSkin.id。将会按顺序循环选择培育。
|
|
||||||
"""
|
|
||||||
memory_sets: list[int] = []
|
|
||||||
"""要使用的回忆编成编号,从 1 开始。将会按顺序循环选择使用。"""
|
|
||||||
support_card_sets: list[int] = []
|
|
||||||
"""要使用的支援卡编成编号,从 1 开始。将会按顺序循环选择使用。"""
|
|
||||||
auto_set_memory: bool = False
|
|
||||||
"""是否自动编成回忆。此选项优先级高于回忆编成编号。"""
|
|
||||||
auto_set_support_card: bool = False
|
|
||||||
"""是否自动编成支援卡。此选项优先级高于支援卡编成编号。"""
|
|
||||||
use_pt_boost: bool = False
|
|
||||||
"""是否使用支援强化 Pt 提升。"""
|
|
||||||
use_note_boost: bool = False
|
|
||||||
"""是否使用笔记数提升。"""
|
|
||||||
follow_producer: bool = False
|
|
||||||
"""是否关注租借了支援卡的制作人。"""
|
|
||||||
self_study_lesson: Literal['dance', 'visual', 'vocal'] = 'dance'
|
|
||||||
"""自习课类型。"""
|
|
||||||
prefer_lesson_ap: bool = False
|
|
||||||
"""
|
|
||||||
优先 SP 课程。
|
|
||||||
|
|
||||||
启用后,若出现 SP 课程,则会优先执行 SP 课程,而不是推荐课程。
|
|
||||||
若出现多个 SP 课程,随机选择一个。
|
|
||||||
"""
|
|
||||||
actions_order: list[ProduceAction] = [
|
|
||||||
ProduceAction.RECOMMENDED,
|
|
||||||
ProduceAction.VISUAL,
|
|
||||||
ProduceAction.VOCAL,
|
|
||||||
ProduceAction.DANCE,
|
|
||||||
ProduceAction.ALLOWANCE,
|
|
||||||
ProduceAction.OUTING,
|
|
||||||
ProduceAction.STUDY,
|
|
||||||
ProduceAction.CONSULT,
|
|
||||||
ProduceAction.REST,
|
|
||||||
]
|
|
||||||
"""
|
|
||||||
行动优先级
|
|
||||||
|
|
||||||
每一周的行动将会按这里设置的优先级执行。
|
|
||||||
"""
|
|
||||||
recommend_card_detection_mode: RecommendCardDetectionMode = RecommendCardDetectionMode.NORMAL
|
|
||||||
"""
|
|
||||||
推荐卡检测模式
|
|
||||||
|
|
||||||
严格模式下,识别速度会降低,但识别准确率会提高。
|
|
||||||
"""
|
|
||||||
use_ap_drink: bool = False
|
|
||||||
"""
|
|
||||||
AP 不足时自动使用 AP 饮料
|
|
||||||
"""
|
|
||||||
skip_commu: bool = True
|
|
||||||
"""检测并跳过交流"""
|
|
||||||
|
|
||||||
class MissionRewardConfig(ConfigBaseModel):
|
class MissionRewardConfig(ConfigBaseModel):
|
||||||
enabled: bool = False
|
enabled: bool = False
|
||||||
|
@ -284,4 +223,12 @@ class BaseConfig(ConfigBaseModel):
|
||||||
def conf() -> BaseConfig:
|
def conf() -> BaseConfig:
|
||||||
"""获取当前配置数据"""
|
"""获取当前配置数据"""
|
||||||
c = config.to(BaseConfig).current
|
c = config.to(BaseConfig).current
|
||||||
return c.options
|
return c.options
|
||||||
|
|
||||||
|
def produce_solution() -> ProduceSolution:
|
||||||
|
"""获取当前培育方案"""
|
||||||
|
id = conf().produce.selected_solution_id
|
||||||
|
if id is None:
|
||||||
|
raise ValueError("No produce solution selected")
|
||||||
|
# TODO: 这里需要缓存,不能每次都从磁盘读取
|
||||||
|
return ProduceSolutionManager().read(id)
|
||||||
|
|
|
@ -9,6 +9,7 @@ from kotonebot import (
|
||||||
sleep,
|
sleep,
|
||||||
Interval,
|
Interval,
|
||||||
)
|
)
|
||||||
|
from kotonebot.kaa.config.schema import produce_solution
|
||||||
from kotonebot.primitives import Rect
|
from kotonebot.primitives import Rect
|
||||||
from kotonebot.kaa.tasks import R
|
from kotonebot.kaa.tasks import R
|
||||||
from .p_drink import acquire_p_drink
|
from .p_drink import acquire_p_drink
|
||||||
|
@ -188,7 +189,7 @@ def fast_acquisitions() -> AcquisitionType | None:
|
||||||
|
|
||||||
# 跳过未读交流
|
# 跳过未读交流
|
||||||
logger.debug("Check skip commu...")
|
logger.debug("Check skip commu...")
|
||||||
if conf().produce.skip_commu and handle_unread_commu(img):
|
if produce_solution().data.skip_commu and handle_unread_commu(img):
|
||||||
return "SkipCommu"
|
return "SkipCommu"
|
||||||
device.click(10, 10)
|
device.click(10, 10)
|
||||||
|
|
||||||
|
|
|
@ -2,6 +2,7 @@ import logging
|
||||||
from typing_extensions import assert_never
|
from typing_extensions import assert_never
|
||||||
from typing import Literal
|
from typing import Literal
|
||||||
|
|
||||||
|
from kotonebot.kaa.config.schema import produce_solution
|
||||||
from kotonebot.kaa.game_ui.schedule import Schedule
|
from kotonebot.kaa.game_ui.schedule import Schedule
|
||||||
from kotonebot.kaa.tasks import R
|
from kotonebot.kaa.tasks import R
|
||||||
from ..actions import loading
|
from ..actions import loading
|
||||||
|
@ -193,7 +194,7 @@ def practice():
|
||||||
|
|
||||||
def threshold_predicate(card_count: int, result: CardDetectResult):
|
def threshold_predicate(card_count: int, result: CardDetectResult):
|
||||||
border_scores = (result.left_score, result.right_score, result.top_score, result.bottom_score)
|
border_scores = (result.left_score, result.right_score, result.top_score, result.bottom_score)
|
||||||
is_strict_mode = conf().produce.recommend_card_detection_mode == RecommendCardDetectionMode.STRICT
|
is_strict_mode = produce_solution().data.recommend_card_detection_mode == RecommendCardDetectionMode.STRICT
|
||||||
if is_strict_mode:
|
if is_strict_mode:
|
||||||
return (
|
return (
|
||||||
result.score >= 0.05
|
result.score >= 0.05
|
||||||
|
@ -225,7 +226,7 @@ def exam(type: Literal['mid', 'final']):
|
||||||
logger.info("Exam started")
|
logger.info("Exam started")
|
||||||
|
|
||||||
def threshold_predicate(card_count: int, result: CardDetectResult):
|
def threshold_predicate(card_count: int, result: CardDetectResult):
|
||||||
is_strict_mode = conf().produce.recommend_card_detection_mode == RecommendCardDetectionMode.STRICT
|
is_strict_mode = produce_solution().data.recommend_card_detection_mode == RecommendCardDetectionMode.STRICT
|
||||||
total = lambda t: result.score >= t
|
total = lambda t: result.score >= t
|
||||||
def borders(t):
|
def borders(t):
|
||||||
# 卡片数量小于三时无遮挡,以及最后一张卡片也总是无遮挡
|
# 卡片数量小于三时无遮挡,以及最后一张卡片也总是无遮挡
|
||||||
|
@ -423,7 +424,7 @@ def produce_end():
|
||||||
# [screenshots/produce_end/end_follow.png]
|
# [screenshots/produce_end/end_follow.png]
|
||||||
elif image.find(R.InPurodyuusu.ButtonCancel):
|
elif image.find(R.InPurodyuusu.ButtonCancel):
|
||||||
logger.info("Follow producer dialog found. Click to close.")
|
logger.info("Follow producer dialog found. Click to close.")
|
||||||
if conf().produce.follow_producer:
|
if produce_solution().data.follow_producer:
|
||||||
logger.info("Follow producer")
|
logger.info("Follow producer")
|
||||||
device.click(image.expect_wait(R.InPurodyuusu.ButtonFollowNoIcon))
|
device.click(image.expect_wait(R.InPurodyuusu.ButtonFollowNoIcon))
|
||||||
else:
|
else:
|
||||||
|
@ -507,12 +508,12 @@ def week_normal(week_first: bool = False):
|
||||||
action: ProduceAction | None = None
|
action: ProduceAction | None = None
|
||||||
# SP 课程
|
# SP 课程
|
||||||
if (
|
if (
|
||||||
conf().produce.prefer_lesson_ap
|
produce_solution().data.prefer_lesson_ap
|
||||||
and handle_sp_lesson()
|
and handle_sp_lesson()
|
||||||
):
|
):
|
||||||
action = ProduceAction.DANCE
|
action = ProduceAction.DANCE
|
||||||
else:
|
else:
|
||||||
actions = conf().produce.actions_order
|
actions = produce_solution().data.actions_order
|
||||||
for action in actions:
|
for action in actions:
|
||||||
logger.debug("Checking action: %s", action)
|
logger.debug("Checking action: %s", action)
|
||||||
if action := handle_action(action):
|
if action := handle_action(action):
|
||||||
|
@ -540,7 +541,7 @@ def week_normal(week_first: bool = False):
|
||||||
def week_final_lesson():
|
def week_final_lesson():
|
||||||
until_action_scene()
|
until_action_scene()
|
||||||
action: ProduceAction | None = None
|
action: ProduceAction | None = None
|
||||||
actions = conf().produce.actions_order
|
actions = produce_solution().data.actions_order
|
||||||
for action in actions:
|
for action in actions:
|
||||||
logger.debug("Checking action: %s", action)
|
logger.debug("Checking action: %s", action)
|
||||||
if action := handle_action(action, True):
|
if action := handle_action(action, True):
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
"""
|
"""
|
||||||
from logging import getLogger
|
from logging import getLogger
|
||||||
|
|
||||||
|
from kotonebot.kaa.config.schema import produce_solution
|
||||||
from kotonebot.kaa.game_ui import dialog
|
from kotonebot.kaa.game_ui import dialog
|
||||||
|
|
||||||
from kotonebot.kaa.tasks import R
|
from kotonebot.kaa.tasks import R
|
||||||
|
@ -66,7 +67,7 @@ def enter_study():
|
||||||
R.InPurodyuusu.TextSelfStudyVocal
|
R.InPurodyuusu.TextSelfStudyVocal
|
||||||
]):
|
]):
|
||||||
logger.info("授業 type: Self study.")
|
logger.info("授業 type: Self study.")
|
||||||
target = conf().produce.self_study_lesson
|
target = produce_solution().data.self_study_lesson
|
||||||
if target == 'dance':
|
if target == 'dance':
|
||||||
logger.debug("Clicking on lesson dance.")
|
logger.debug("Clicking on lesson dance.")
|
||||||
device.double_click(image.expect(R.InPurodyuusu.TextSelfStudyDance))
|
device.double_click(image.expect(R.InPurodyuusu.TextSelfStudyDance))
|
||||||
|
|
|
@ -3,6 +3,7 @@ from itertools import cycle
|
||||||
from typing import Optional, Literal
|
from typing import Optional, Literal
|
||||||
from typing_extensions import assert_never
|
from typing_extensions import assert_never
|
||||||
|
|
||||||
|
from kotonebot.kaa.config.schema import produce_solution
|
||||||
from kotonebot.ui import user
|
from kotonebot.ui import user
|
||||||
from kotonebot.kaa.tasks import R
|
from kotonebot.kaa.tasks import R
|
||||||
from kotonebot.kaa.config import conf
|
from kotonebot.kaa.config import conf
|
||||||
|
@ -242,7 +243,7 @@ def do_produce(
|
||||||
result = False
|
result = False
|
||||||
break
|
break
|
||||||
if not result:
|
if not result:
|
||||||
if conf().produce.use_ap_drink:
|
if produce_solution().data.use_ap_drink:
|
||||||
# [kotonebot-resource\sprites\jp\produce\screenshot_no_enough_ap_1.png]
|
# [kotonebot-resource\sprites\jp\produce\screenshot_no_enough_ap_1.png]
|
||||||
# [kotonebot-resource\sprites\jp\produce\screenshot_no_enough_ap_2.png]
|
# [kotonebot-resource\sprites\jp\produce\screenshot_no_enough_ap_2.png]
|
||||||
# [kotonebot-resource\sprites\jp\produce\screenshot_no_enough_ap_3.png]
|
# [kotonebot-resource\sprites\jp\produce\screenshot_no_enough_ap_3.png]
|
||||||
|
@ -351,11 +352,11 @@ def do_produce(
|
||||||
|
|
||||||
# 4. 选择道具 [screenshots/produce/screenshot_produce_start_4_end.png]
|
# 4. 选择道具 [screenshots/produce/screenshot_produce_start_4_end.png]
|
||||||
# TODO: 如果道具不足,这里加入推送提醒
|
# TODO: 如果道具不足,这里加入推送提醒
|
||||||
if conf().produce.use_note_boost:
|
if produce_solution().data.use_note_boost:
|
||||||
if image.find(R.Produce.CheckboxIconNoteBoost):
|
if image.find(R.Produce.CheckboxIconNoteBoost):
|
||||||
device.click()
|
device.click()
|
||||||
sleep(0.1)
|
sleep(0.1)
|
||||||
if conf().produce.use_pt_boost:
|
if produce_solution().data.use_pt_boost:
|
||||||
if image.find(R.Produce.CheckboxIconSupportPtBoost):
|
if image.find(R.Produce.CheckboxIconSupportPtBoost):
|
||||||
device.click()
|
device.click()
|
||||||
sleep(0.1)
|
sleep(0.1)
|
||||||
|
@ -384,14 +385,14 @@ def produce():
|
||||||
"""
|
"""
|
||||||
培育任务
|
培育任务
|
||||||
"""
|
"""
|
||||||
if not conf().produce.enabled:
|
if not produce_solution().data.enabled:
|
||||||
logger.info('Produce is disabled.')
|
logger.info('Produce is disabled.')
|
||||||
return
|
return
|
||||||
import time
|
import time
|
||||||
count = conf().produce.produce_count
|
count = produce_solution().data.produce_count
|
||||||
idols = conf().produce.idols
|
idols = produce_solution().data.idols
|
||||||
memory_sets = conf().produce.memory_sets
|
memory_sets = produce_solution().data.memory_sets
|
||||||
mode = conf().produce.mode
|
mode = produce_solution().data.mode
|
||||||
# 数据验证
|
# 数据验证
|
||||||
if count < 0:
|
if count < 0:
|
||||||
user.warning('配置有误', '培育次数不能小于 0。将跳过本次培育。')
|
user.warning('配置有误', '培育次数不能小于 0。将跳过本次培育。')
|
||||||
|
@ -402,7 +403,7 @@ def produce():
|
||||||
for i in range(count):
|
for i in range(count):
|
||||||
start_time = time.time()
|
start_time = time.time()
|
||||||
idol = next(idol_iterator)
|
idol = next(idol_iterator)
|
||||||
if conf().produce.auto_set_memory:
|
if produce_solution().data.auto_set_memory:
|
||||||
memory_set = None
|
memory_set = None
|
||||||
else:
|
else:
|
||||||
memory_set = next(memory_set_iterator, None)
|
memory_set = next(memory_set_iterator, None)
|
||||||
|
@ -426,12 +427,12 @@ if __name__ == '__main__':
|
||||||
from kotonebot.kaa.common import BaseConfig
|
from kotonebot.kaa.common import BaseConfig
|
||||||
from kotonebot.kaa.main import Kaa
|
from kotonebot.kaa.main import Kaa
|
||||||
|
|
||||||
conf().produce.enabled = True
|
produce_solution().data.enabled = True
|
||||||
conf().produce.mode = 'pro'
|
produce_solution().data.mode = 'pro'
|
||||||
conf().produce.produce_count = 1
|
produce_solution().data.produce_count = 1
|
||||||
# conf().produce.idols = ['i_card-skin-hski-3-002']
|
# produce_solution().data.idols = ['i_card-skin-hski-3-002']
|
||||||
conf().produce.memory_sets = [1]
|
produce_solution().data.memory_sets = [1]
|
||||||
conf().produce.auto_set_memory = False
|
produce_solution().data.auto_set_memory = False
|
||||||
# do_produce(PIdol.月村手毬_初声, 'pro', 5)
|
# do_produce(PIdol.月村手毬_初声, 'pro', 5)
|
||||||
produce()
|
produce()
|
||||||
# a()
|
# a()
|
||||||
|
|
Loading…
Reference in New Issue