feat(task): 新增支持指定回忆编成编号
This commit is contained in:
parent
f146038d36
commit
64829624bb
Binary file not shown.
After Width: | Height: | Size: 955 KiB |
|
@ -0,0 +1 @@
|
|||
{"definitions":{"7e3e3a94-e05c-477e-bd92-0afc172bdb94":{"name":"Produce.BoxSetCountIndicator","displayName":"培育开始页面 当前编成编号","type":"hint-box","annotationId":"7e3e3a94-e05c-477e-bd92-0afc172bdb94","useHintRect":false},"389bdefb-4b76-4ac3-9460-d59c144f8de7":{"name":"Produce.PointProduceNextSet","displayName":"培育开始页面 下一个编成","type":"hint-point","annotationId":"389bdefb-4b76-4ac3-9460-d59c144f8de7","useHintRect":false},"745d904e-19eb-4e15-b734-ef116e6e7c48":{"name":"Produce.PointProducePrevSet","displayName":"培育开始页面 上一个编成","type":"hint-point","annotationId":"745d904e-19eb-4e15-b734-ef116e6e7c48","useHintRect":false}},"annotations":[{"id":"7e3e3a94-e05c-477e-bd92-0afc172bdb94","type":"rect","data":{"x1":17,"y1":671,"x2":119,"y2":707}},{"id":"389bdefb-4b76-4ac3-9460-d59c144f8de7","type":"point","data":{"x":702,"y":832}},{"id":"745d904e-19eb-4e15-b734-ef116e6e7c48","type":"point","data":{"x":14,"y":832}}]}
|
|
@ -320,7 +320,6 @@ class ProduceConfig(ConfigBaseModel):
|
|||
memory_sets: list[int] = []
|
||||
"""要使用的回忆编成编号,从 1 开始。将会按顺序循环选择使用。"""
|
||||
support_card_sets: list[int] = []
|
||||
|
||||
"""要使用的支援卡编成编号,从 1 开始。将会按顺序循环选择使用。"""
|
||||
auto_set_memory: bool = False
|
||||
"""是否自动编成回忆。此选项优先级高于回忆编成编号。"""
|
||||
|
|
|
@ -185,6 +185,7 @@ class CommuEventButtonUI:
|
|||
img = device.screenshot()
|
||||
rects = filter_rectangles(img, (WHITE_LOW, WHITE_HIGH), 3, 1000, rect=self.rect)
|
||||
rects.sort(key=lambda x: x[1])
|
||||
# TODO: 这里 rects 可能为空,需要加入判断重试
|
||||
ocr_result = ocr.raw().ocr(img, rect=rects[0])
|
||||
return ocr_result.squash().text
|
||||
|
||||
|
|
|
@ -99,6 +99,56 @@ def select_idol(target_titles: list[str] | PIdol):
|
|||
device.click(image.expect(R.Common.ButtonConfirmNoIcon))
|
||||
return found
|
||||
|
||||
@action('培育开始.编成翻页', screenshot_mode='manual-inherit')
|
||||
def select_set(index: int):
|
||||
"""
|
||||
选择指定编号的支援卡/回忆编成。
|
||||
|
||||
前置条件:STEP 2/3 页面
|
||||
结束状态:STEP 2/3 页面
|
||||
|
||||
:param index: 支援卡/回忆编成的编号,从 1 开始。
|
||||
"""
|
||||
def _current():
|
||||
numbers = []
|
||||
while not numbers:
|
||||
device.screenshot()
|
||||
numbers = ocr.ocr(rect=R.Produce.BoxSetCountIndicator).squash().numbers()
|
||||
if not numbers:
|
||||
logger.warning('Failed to get current set number. Retrying...')
|
||||
sleep(0.2)
|
||||
return numbers[0]
|
||||
|
||||
max_retries = 3
|
||||
retry_count = 0
|
||||
|
||||
while retry_count < max_retries:
|
||||
current = _current()
|
||||
logger.info(f'Navigate to set #{index}. Now at set #{current}.')
|
||||
|
||||
# 计算需要点击的次数
|
||||
click_count = abs(index - current)
|
||||
if click_count == 0:
|
||||
logger.info(f'Already at set #{current}.')
|
||||
return
|
||||
click_target = R.Produce.PointProduceNextSet if current < index else R.Produce.PointProducePrevSet
|
||||
|
||||
# 点击
|
||||
for _ in range(click_count):
|
||||
device.click(click_target)
|
||||
sleep(0.1)
|
||||
|
||||
# 确认
|
||||
final_current = _current()
|
||||
if final_current == index:
|
||||
logger.info(f'Arrived at set #{final_current}.')
|
||||
return
|
||||
else:
|
||||
retry_count += 1
|
||||
logger.warning(f'Failed to navigate to set #{index}. Current set is #{final_current}. Retrying... ({retry_count}/{max_retries})')
|
||||
|
||||
logger.error(f'Failed to navigate to set #{index} after {max_retries} retries.')
|
||||
|
||||
@action('继续当前培育')
|
||||
def resume_produce():
|
||||
"""
|
||||
|
@ -119,7 +169,11 @@ def resume_produce():
|
|||
resume_regular_produce()
|
||||
|
||||
@action('执行培育', screenshot_mode='manual-inherit')
|
||||
def do_produce(idol: PIdol, mode: Literal['regular', 'pro']) -> bool:
|
||||
def do_produce(
|
||||
idol: PIdol,
|
||||
mode: Literal['regular', 'pro'],
|
||||
memory_set_index: Optional[int] = None
|
||||
) -> bool:
|
||||
"""
|
||||
进行培育流程
|
||||
|
||||
|
@ -171,24 +225,32 @@ def do_produce(idol: PIdol, mode: Literal['regular', 'pro']) -> bool:
|
|||
it.wait()
|
||||
# 3. 选择回忆 自动编成 [screenshots/produce/select_memory.png]
|
||||
ocr.expect_wait(contains('メモリー'), rect=R.Produce.BoxStepIndicator)
|
||||
device.click(image.expect_wait(R.Produce.ButtonAutoSet))
|
||||
wait(0.5, before='screenshot')
|
||||
device.screenshot()
|
||||
# 自动编成
|
||||
if memory_set_index is not None and not 1 <= memory_set_index <= 10:
|
||||
raise ValueError('`memory_set_index` must be in range [1, 10].')
|
||||
if memory_set_index is None:
|
||||
device.click(image.expect_wait(R.Produce.ButtonAutoSet))
|
||||
wait(0.5, before='screenshot')
|
||||
device.screenshot()
|
||||
# 指定编号
|
||||
else:
|
||||
select_set(memory_set_index)
|
||||
(SimpleDispatcher('do_produce.step_3')
|
||||
.click(R.Common.ButtonNextNoIcon)
|
||||
.click(R.Common.ButtonConfirm)
|
||||
.until(contains('開始確認'), rect=R.Produce.BoxStepIndicator)
|
||||
).run()
|
||||
|
||||
# 4. 选择道具 [screenshots/produce/select_end.png]
|
||||
# TODO: 如果道具不足,这里加入推送提醒
|
||||
if conf().produce.use_note_boost:
|
||||
if image.find(R.Produce.CheckboxIconNoteBoost):
|
||||
device.click()
|
||||
sleep(0.2)
|
||||
sleep(0.1)
|
||||
if conf().produce.use_pt_boost:
|
||||
if image.find(R.Produce.CheckboxIconSupportPtBoost):
|
||||
device.click()
|
||||
sleep(0.2)
|
||||
sleep(0.1)
|
||||
device.click(image.expect_wait(R.Produce.ButtonProduceStart))
|
||||
# 5. 相关设置弹窗 [screenshots/produce/skip_commu.png]
|
||||
cd = Countdown(5).start()
|
||||
|
@ -206,9 +268,10 @@ def do_produce(idol: PIdol, mode: Literal['regular', 'pro']) -> bool:
|
|||
|
||||
@task('培育')
|
||||
def produce_task(
|
||||
mode: Literal['regular', 'pro'] | None = None,
|
||||
mode: Optional[Literal['regular', 'pro']] = None,
|
||||
count: Optional[int] = None,
|
||||
idols: Optional[list[PIdol]] = None
|
||||
idols: Optional[list[PIdol]] = None,
|
||||
memory_sets: Optional[list[int]] = None
|
||||
):
|
||||
"""
|
||||
培育任务
|
||||
|
@ -225,6 +288,8 @@ def produce_task(
|
|||
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
|
||||
# 数据验证
|
||||
|
@ -233,9 +298,19 @@ def produce_task(
|
|||
return
|
||||
|
||||
idol_iterator = cycle(idols)
|
||||
memory_set_iterator = cycle(memory_sets)
|
||||
for i in range(count):
|
||||
start_time = time.time()
|
||||
if not do_produce(next(idol_iterator), mode):
|
||||
idol = next(idol_iterator)
|
||||
if conf().produce.auto_set_memory:
|
||||
memory_set = None
|
||||
else:
|
||||
memory_set = next(memory_set_iterator, None)
|
||||
logger.info(
|
||||
f'Produce start with: '
|
||||
f'idol: {idol.value}, mode: {mode}, memory_set: #{memory_set}'
|
||||
)
|
||||
if not do_produce(idol, mode, memory_set):
|
||||
user.info('AP 不足', f'由于 AP 不足,跳过了 {count - i} 次培育。')
|
||||
logger.info('%d produce(s) skipped because of insufficient AP.', count - i)
|
||||
break
|
||||
|
@ -261,7 +336,14 @@ if __name__ == '__main__':
|
|||
init_context(config_type=BaseConfig)
|
||||
conf().produce.enabled = True
|
||||
conf().produce.mode = 'pro'
|
||||
# conf().produce.idols = [PIdol.花海佑芽_学園生活]
|
||||
conf().produce.produce_count = 1
|
||||
conf().produce.idols = [PIdol.月村手毬_アイヴイ]
|
||||
conf().produce.memory_sets = [5]
|
||||
conf().produce.auto_set_memory = False
|
||||
# do_produce(PIdol.月村手毬_初声, 'pro', 5)
|
||||
produce_task()
|
||||
# a()
|
||||
# select_idol(PIdol.藤田ことね_学園生活)
|
||||
# select_idol(PIdol.藤田ことね_学園生活)
|
||||
# select_set(10)
|
||||
# manual_context().begin()
|
||||
# print(ocr.ocr(rect=R.Produce.BoxSetCountIndicator).squash().numbers())
|
|
@ -242,6 +242,7 @@ class KotoneBotUI:
|
|||
produce_mode: Literal["regular"],
|
||||
produce_count: int,
|
||||
produce_idols: List[str],
|
||||
memory_sets: List[str],
|
||||
auto_set_memory: bool,
|
||||
auto_set_support: bool,
|
||||
use_pt_boost: bool,
|
||||
|
@ -294,6 +295,7 @@ class KotoneBotUI:
|
|||
mode=produce_mode,
|
||||
produce_count=produce_count,
|
||||
idols=[PIdol[idol] for idol in produce_idols],
|
||||
memory_sets=[int(i) for i in memory_sets],
|
||||
auto_set_memory=auto_set_memory,
|
||||
auto_set_support_card=auto_set_support,
|
||||
use_pt_boost=use_pt_boost,
|
||||
|
@ -323,7 +325,7 @@ class KotoneBotUI:
|
|||
with gr.Row():
|
||||
run_btn = gr.Button("启动", scale=1)
|
||||
debug_btn = gr.Button("调试", scale=1)
|
||||
gr.Markdown("脚本报错或者卡住?点击“日志”选项卡中的“一键导出报告”可以快速反馈!")
|
||||
gr.Markdown('脚本报错或者卡住?点击"日志"选项卡中的"一键导出报告"可以快速反馈!')
|
||||
|
||||
task_status = gr.Dataframe(
|
||||
headers=["任务", "状态"],
|
||||
|
@ -493,7 +495,7 @@ class KotoneBotUI:
|
|||
)
|
||||
return assignment_enabled, mini_live_reassign, mini_live_duration, online_live_reassign, online_live_duration
|
||||
|
||||
def _create_produce_settings(self) -> Tuple[gr.Checkbox, gr.Dropdown, gr.Number, gr.Dropdown, gr.Checkbox, gr.Checkbox, gr.Checkbox, gr.Checkbox, gr.Checkbox]:
|
||||
def _create_produce_settings(self) -> Tuple[gr.Checkbox, gr.Dropdown, gr.Number, gr.Dropdown, gr.Dropdown, gr.Checkbox, gr.Checkbox, gr.Checkbox, gr.Checkbox, gr.Checkbox]:
|
||||
with gr.Column():
|
||||
gr.Markdown("### 培育设置")
|
||||
produce_enabled = gr.Checkbox(
|
||||
|
@ -531,6 +533,16 @@ class KotoneBotUI:
|
|||
value=self.current_config.options.produce.auto_set_memory,
|
||||
info=ProduceConfig.model_fields['auto_set_memory'].description
|
||||
)
|
||||
# 添加回忆编成选择
|
||||
with gr.Group(visible=not self.current_config.options.produce.auto_set_memory) as memory_sets_group:
|
||||
memory_sets = gr.Dropdown(
|
||||
choices=[str(i) for i in range(1, 11)], # 假设最多10个编成位
|
||||
value=[str(i) for i in self.current_config.options.produce.memory_sets],
|
||||
label="回忆编成编号",
|
||||
multiselect=True,
|
||||
interactive=True,
|
||||
info=ProduceConfig.model_fields['memory_sets'].description
|
||||
)
|
||||
auto_set_support = gr.Checkbox(
|
||||
label="自动编成支援卡",
|
||||
value=self.current_config.options.produce.auto_set_support_card,
|
||||
|
@ -557,7 +569,13 @@ class KotoneBotUI:
|
|||
inputs=[produce_enabled],
|
||||
outputs=[produce_group]
|
||||
)
|
||||
return produce_enabled, produce_mode, produce_count, produce_idols, auto_set_memory, auto_set_support, use_pt_boost, use_note_boost, follow_producer
|
||||
|
||||
auto_set_memory.change(
|
||||
fn=lambda x: gr.Group(visible=not x),
|
||||
inputs=[auto_set_memory],
|
||||
outputs=[memory_sets_group]
|
||||
)
|
||||
return produce_enabled, produce_mode, produce_count, produce_idols, memory_sets, auto_set_memory, auto_set_support, use_pt_boost, use_note_boost, follow_producer
|
||||
|
||||
def _create_settings_tab(self) -> None:
|
||||
with gr.Tab("设置"):
|
||||
|
|
Loading…
Reference in New Issue