feat(task): 新增扭蛋机功能,支持任意次数的任意类型扭蛋
After Width: | Height: | Size: 4.6 KiB |
After Width: | Height: | Size: 1.9 KiB |
After Width: | Height: | Size: 644 KiB |
|
@ -0,0 +1 @@
|
|||
{"definitions":{"26ce71b2-59dc-4237-b50f-41690d7b8ecf":{"name":"Daily.CapsuleToys.NextPageStartPoint","displayName":"日常 扭蛋 下一页起始点","type":"hint-point","annotationId":"26ce71b2-59dc-4237-b50f-41690d7b8ecf","useHintRect":false,"description":"扭蛋页面翻页时的起始点"},"ada5c1e1-1524-4476-bdf9-aa0aab8b35ad":{"name":"Daily.CapsuleToys.NextPageEndPoint","displayName":"日常 扭蛋 下一页终点","type":"hint-point","annotationId":"ada5c1e1-1524-4476-bdf9-aa0aab8b35ad","useHintRect":false,"description":"扭蛋页面翻页时的终点"}},"annotations":[{"id":"26ce71b2-59dc-4237-b50f-41690d7b8ecf","type":"point","data":{"x":360,"y":1167}},{"id":"ada5c1e1-1524-4476-bdf9-aa0aab8b35ad","type":"point","data":{"x":362,"y":267}}]}
|
After Width: | Height: | Size: 359 KiB |
|
@ -0,0 +1 @@
|
|||
{"definitions":{"045e21c4-350b-4b6c-bcb7-aeb007da05b3":{"name":"Daily.CapsuleToys.SliderStartPoint","displayName":"日常 扭蛋 滑动条起点","type":"hint-point","annotationId":"045e21c4-350b-4b6c-bcb7-aeb007da05b3","useHintRect":false,"description":"扭蛋数量滑动条的右端点(置0时的起始点)"},"5ba55176-f5a1-4d3f-8fd8-75e868715ad8":{"name":"Daily.CapsuleToys.SliderEndPoint","displayName":"日常 扭蛋 滑动条终点","type":"hint-point","annotationId":"5ba55176-f5a1-4d3f-8fd8-75e868715ad8","useHintRect":false,"description":"扭蛋数量滑动条的左端点(置0时的终点)"}},"annotations":[{"id":"045e21c4-350b-4b6c-bcb7-aeb007da05b3","type":"point","data":{"x":476,"y":898}},{"id":"5ba55176-f5a1-4d3f-8fd8-75e868715ad8","type":"point","data":{"x":230,"y":898}}]}
|
|
@ -0,0 +1,127 @@
|
|||
"""扭蛋机,支持任意次数的任意扭蛋类型"""
|
||||
import logging
|
||||
|
||||
from kotonebot import task, action, device, image, sleep
|
||||
from kotonebot.backend.image import TemplateMatchResult
|
||||
from . import R
|
||||
from .common import conf
|
||||
from .actions.scenes import at_home, goto_home
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
@action('抽某种类型的扭蛋times次')
|
||||
def draw_capsule_toys(button: TemplateMatchResult, times: int):
|
||||
"""
|
||||
抽某种类型的扭蛋N次
|
||||
|
||||
:param button: 扭蛋按钮
|
||||
:param times: 抽取次数
|
||||
"""
|
||||
|
||||
device.click(button)
|
||||
sleep(0.5)
|
||||
|
||||
device.swipe(
|
||||
R.Daily.CapsuleToys.SliderStartPoint.x,
|
||||
R.Daily.CapsuleToys.SliderStartPoint.y,
|
||||
R.Daily.CapsuleToys.SliderEndPoint.x,
|
||||
R.Daily.CapsuleToys.SliderEndPoint.y,
|
||||
duration=1.0
|
||||
)
|
||||
sleep(0.5)
|
||||
|
||||
# 点击加号按钮
|
||||
add_button = image.expect_wait(R.Daily.ButtonShopCountAdd, timeout=5)
|
||||
for _ in range(times):
|
||||
device.click(add_button)
|
||||
sleep(0.5)
|
||||
|
||||
# 点击确认按钮
|
||||
device.click(image.expect_wait(R.Common.ButtonConfirm, timeout=5))
|
||||
sleep(0.5)
|
||||
|
||||
# 点击关闭按钮(这里同时处理了两种情况:成功,关闭提示页面;扭蛋次数不足,关闭抽扭蛋页面)
|
||||
if image.wait_for(R.Common.ButtonIconClose, timeout=5):
|
||||
device.click()
|
||||
sleep(1)
|
||||
|
||||
@action('获取抽扭蛋按钮')
|
||||
def get_capsule_toys_draw_buttons():
|
||||
"""
|
||||
在扭蛋页面中获取两个抽扭蛋按钮,并按y轴排序
|
||||
"""
|
||||
buttons = image.find_all(R.Daily.ButtonShopCapsuleToysDraw)
|
||||
if len(buttons) != 2:
|
||||
logger.error('Failed to find 2 capsule toys buttons.')
|
||||
return []
|
||||
# 按y轴排序
|
||||
buttons.sort(key=lambda x: x.position[1])
|
||||
return buttons
|
||||
|
||||
@task('扭蛋机')
|
||||
def capsule_toys():
|
||||
"""
|
||||
扭蛋机,支持任意次数的任意扭蛋类型
|
||||
|
||||
自动化思路:\n
|
||||
进入扭蛋机页面后,可以发现扭蛋机总共有4种类型。\n
|
||||
通过硬编码的滑动翻页,把每两种扭蛋分为同一页。
|
||||
第一页:好友扭蛋+感性扭蛋;
|
||||
第二页:逻辑扭蛋+非凡扭蛋。\n
|
||||
划到某一页之后,识别截图中所有“抽扭蛋”按钮,再按照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.')
|
||||
return
|
||||
|
||||
if not at_home():
|
||||
goto_home()
|
||||
|
||||
# 进入扭蛋机页面
|
||||
logger.info('Entering Capsule Toys page')
|
||||
device.click(image.expect_wait(R.Daily.ButtonShop, timeout=5))
|
||||
device.click(image.expect_wait(R.Daily.ButtonShopCapsuleToys, timeout=5))
|
||||
sleep(1)
|
||||
|
||||
# 处理好友扭蛋和感性扭蛋
|
||||
buttons = get_capsule_toys_draw_buttons();
|
||||
if len(buttons) != 2:
|
||||
return
|
||||
|
||||
if conf().capsule_toys.friend_capsule_toys_count > 0:
|
||||
draw_capsule_toys(buttons[0], conf().capsule_toys.friend_capsule_toys_count)
|
||||
|
||||
if conf().capsule_toys.sense_capsule_toys_count > 0:
|
||||
draw_capsule_toys(buttons[1], conf().capsule_toys.sense_capsule_toys_count)
|
||||
|
||||
# 划到第二页
|
||||
device.swipe(
|
||||
R.Daily.CapsuleToys.NextPageStartPoint.x,
|
||||
R.Daily.CapsuleToys.NextPageStartPoint.y,
|
||||
R.Daily.CapsuleToys.NextPageEndPoint.x,
|
||||
R.Daily.CapsuleToys.NextPageEndPoint.y,
|
||||
duration=2.0 # 划慢点,确保精确定位
|
||||
# FIXME: adb不支持swipe duration失效
|
||||
)
|
||||
sleep(1) # 等待滑动静止(由于swipe duration失效,所以这里需要手动等待)
|
||||
|
||||
# 处理逻辑扭蛋扭蛋和非凡扭蛋
|
||||
buttons = get_capsule_toys_draw_buttons();
|
||||
if len(buttons) != 2:
|
||||
return
|
||||
|
||||
if conf().capsule_toys.logic_capsule_toys_count > 0:
|
||||
draw_capsule_toys(buttons[0], conf().capsule_toys.logic_capsule_toys_count)
|
||||
|
||||
if conf().capsule_toys.anomaly_capsule_toys_count > 0:
|
||||
draw_capsule_toys(buttons[1], conf().capsule_toys.anomaly_capsule_toys_count)
|
||||
|
||||
if __name__ == '__main__':
|
||||
import logging
|
||||
logging.basicConfig(level=logging.INFO, format='[%(asctime)s] [%(levelname)s] [%(name)s] [%(funcName)s] [%(lineno)d] %(message)s')
|
||||
logger.setLevel(logging.DEBUG)
|
||||
capsule_toys()
|
||||
|
|
@ -1,3 +1,4 @@
|
|||
from gc import enable
|
||||
import os
|
||||
from importlib import resources
|
||||
from typing import Literal, Dict, NamedTuple, Tuple, TypeVar, Generic
|
||||
|
@ -434,6 +435,22 @@ class UpgradeSupportCardConfig(ConfigBaseModel):
|
|||
enabled: bool = False
|
||||
"""是否启用支援卡升级"""
|
||||
|
||||
class CapsuleToysConfig(ConfigBaseModel):
|
||||
enabled: bool = False
|
||||
"""是否启用扭蛋机"""
|
||||
|
||||
friend_capsule_toys_count: int = 0
|
||||
"""好友扭蛋机次数"""
|
||||
|
||||
sense_capsule_toys_count: int = 0
|
||||
"""感性扭蛋机次数"""
|
||||
|
||||
logic_capsule_toys_count: int = 0
|
||||
"""理性扭蛋机次数"""
|
||||
|
||||
anomaly_capsule_toys_count: int = 0
|
||||
"""非凡扭蛋机次数"""
|
||||
|
||||
class TraceConfig(ConfigBaseModel):
|
||||
recommend_card_detection: bool = False
|
||||
"""跟踪推荐卡检测"""
|
||||
|
@ -479,6 +496,9 @@ class BaseConfig(ConfigBaseModel):
|
|||
upgrade_support_card: UpgradeSupportCardConfig = UpgradeSupportCardConfig()
|
||||
"""支援卡升级配置"""
|
||||
|
||||
capsule_toys: CapsuleToysConfig = CapsuleToysConfig()
|
||||
"""扭蛋机配置"""
|
||||
|
||||
trace: TraceConfig = TraceConfig()
|
||||
"""跟踪配置"""
|
||||
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
from operator import gt
|
||||
import os
|
||||
import zipfile
|
||||
import logging
|
||||
|
@ -13,9 +14,9 @@ import gradio as gr
|
|||
|
||||
from kotonebot.backend.context import task_registry, ContextStackVars
|
||||
from kotonebot.config.manager import load_config, save_config
|
||||
from kotonebot.tasks import upgrade_support_card
|
||||
from kotonebot.tasks import capsule_toys, upgrade_support_card
|
||||
from kotonebot.tasks.common import (
|
||||
BaseConfig, APShopItems, ClubRewardConfig, PurchaseConfig, ActivityFundsConfig,
|
||||
BaseConfig, APShopItems, CapsuleToysConfig, ClubRewardConfig, PurchaseConfig, ActivityFundsConfig,
|
||||
PresentsConfig, AssignmentConfig, ContestConfig, ProduceConfig,
|
||||
MissionRewardConfig, PIdol, DailyMoneyShopItems, ProduceAction,
|
||||
RecommendCardDetectionMode, TraceConfig, StartGameConfig, UpgradeSupportCardConfig
|
||||
|
@ -268,6 +269,12 @@ class KotoneBotUI:
|
|||
selected_note: DailyMoneyShopItems,
|
||||
# upgrade support card
|
||||
upgrade_support_card_enabled: bool,
|
||||
# capsule toys
|
||||
capsule_toys_enabled: bool,
|
||||
friend_capsule_toys_count: int,
|
||||
sense_capsule_toys_count: int,
|
||||
logic_capsule_toys_count: int,
|
||||
anomaly_capsule_toys_count: int,
|
||||
# start game
|
||||
start_game_enabled: bool,
|
||||
start_through_kuyo: bool,
|
||||
|
@ -343,6 +350,13 @@ class KotoneBotUI:
|
|||
upgrade_support_card=UpgradeSupportCardConfig(
|
||||
enabled=upgrade_support_card_enabled
|
||||
),
|
||||
capsule_toys=CapsuleToysConfig(
|
||||
enabled=capsule_toys_enabled,
|
||||
friend_capsule_toys_count=friend_capsule_toys_count,
|
||||
sense_capsule_toys_count=sense_capsule_toys_count,
|
||||
logic_capsule_toys_count=logic_capsule_toys_count,
|
||||
anomaly_capsule_toys_count=anomaly_capsule_toys_count
|
||||
),
|
||||
start_game=StartGameConfig(
|
||||
enabled=start_game_enabled,
|
||||
start_through_kuyo=start_through_kuyo,
|
||||
|
@ -721,6 +735,52 @@ class KotoneBotUI:
|
|||
)
|
||||
return club_reward_enabled, selected_note
|
||||
|
||||
def _create_capsule_toys_settings(self) -> Tuple[gr.Checkbox, gr.Number, gr.Number, gr.Number, gr.Number]:
|
||||
with gr.Column():
|
||||
gr.Markdown("### 扭蛋设置")
|
||||
capsule_toys_enabled = gr.Checkbox(
|
||||
label="是否启用自动扭蛋机",
|
||||
value=self.current_config.options.capsule_toys.enabled,
|
||||
info=CapsuleToysConfig.model_fields['enabled'].description
|
||||
)
|
||||
min_value = 0
|
||||
max_value = 10
|
||||
with gr.Group(visible=self.current_config.options.capsule_toys.enabled) as capsule_toys_group:
|
||||
friend_capsule_toys_count = gr.Number(
|
||||
value=self.current_config.options.capsule_toys.friend_capsule_toys_count,
|
||||
label="好友扭蛋机的扭蛋次数",
|
||||
info=CapsuleToysConfig.model_fields['friend_capsule_toys_count'].description,
|
||||
minimum=0,
|
||||
maximum=5
|
||||
)
|
||||
sense_capsule_toys_count = gr.Number(
|
||||
value=self.current_config.options.capsule_toys.sense_capsule_toys_count,
|
||||
label="感性扭蛋机的扭蛋次数",
|
||||
info=CapsuleToysConfig.model_fields['sense_capsule_toys_count'].description,
|
||||
minimum=0,
|
||||
maximum=5
|
||||
)
|
||||
logic_capsule_toys_count = gr.Number(
|
||||
value=self.current_config.options.capsule_toys.logic_capsule_toys_count,
|
||||
label="逻辑扭蛋机的扭蛋次数",
|
||||
info=CapsuleToysConfig.model_fields['logic_capsule_toys_count'].description,
|
||||
minimum=0,
|
||||
maximum=5
|
||||
)
|
||||
anomaly_capsule_toys_count = gr.Number(
|
||||
value=self.current_config.options.capsule_toys.anomaly_capsule_toys_count,
|
||||
label="非凡扭蛋机的扭蛋次数",
|
||||
info=CapsuleToysConfig.model_fields['anomaly_capsule_toys_count'].description,
|
||||
minimum=0,
|
||||
maximum=5
|
||||
)
|
||||
capsule_toys_enabled.change(
|
||||
fn=lambda x: gr.Group(visible=x),
|
||||
inputs=[capsule_toys_enabled],
|
||||
outputs=[capsule_toys_group]
|
||||
)
|
||||
return capsule_toys_enabled, friend_capsule_toys_count, sense_capsule_toys_count, logic_capsule_toys_count, anomaly_capsule_toys_count
|
||||
|
||||
|
||||
def _create_start_game_settings(self) -> Tuple[gr.Checkbox, gr.Checkbox, gr.Textbox, gr.Textbox]:
|
||||
with gr.Column():
|
||||
|
@ -852,6 +912,8 @@ class KotoneBotUI:
|
|||
info=UpgradeSupportCardConfig.model_fields['enabled'].description
|
||||
)
|
||||
|
||||
capsule_toys_settings = self._create_capsule_toys_settings()
|
||||
|
||||
# 跟踪设置
|
||||
with gr.Column():
|
||||
gr.Markdown("### 跟踪设置")
|
||||
|
@ -883,6 +945,7 @@ class KotoneBotUI:
|
|||
mission_reward,
|
||||
*club_reward_settings,
|
||||
upgrade_support_card_enabled,
|
||||
*capsule_toys_settings,
|
||||
*start_game_settings
|
||||
]
|
||||
|
||||
|
|
After Width: | Height: | Size: 359 KiB |
After Width: | Height: | Size: 516 KiB |
After Width: | Height: | Size: 644 KiB |