704 lines
24 KiB
Python
704 lines
24 KiB
Python
import random
|
||
import time
|
||
from typing import Literal
|
||
from typing_extensions import deprecated
|
||
import cv2
|
||
import unicodedata
|
||
import logging
|
||
from time import sleep
|
||
|
||
from kotonebot import ocr, device, contains, image, debug, regex
|
||
from kotonebot.backend.context import init_context
|
||
from kotonebot.backend.util import crop_y, cropper_y
|
||
from kotonebot.tasks import R
|
||
from kotonebot.tasks.actions import loading
|
||
from .non_lesson_actions import enter_allowance, study_available, enter_study, allowance_available
|
||
from .common import acquisitions, AcquisitionType, acquire_skill_card
|
||
|
||
logger = logging.getLogger(__name__)
|
||
|
||
ActionType = None | Literal['lesson', 'rest']
|
||
def enter_recommended_action(final_week: bool = False) -> ActionType:
|
||
"""
|
||
在行动选择页面,执行推荐行动
|
||
|
||
:param final_week: 是否是考试前复习周
|
||
:return: 是否成功执行推荐行动
|
||
"""
|
||
# 获取课程
|
||
logger.debug("Waiting for recommended lesson...")
|
||
with device.hook(cropper_y(0.00, 0.30)):
|
||
ret = ocr.wait_for(regex('ボーカル|ダンス|ビジュアル|休|体力'))
|
||
logger.debug("ocr.wait_for: %s", ret)
|
||
if ret is None:
|
||
return None
|
||
if not final_week:
|
||
if "ボーカル" in ret.text:
|
||
lesson_text = "Vo"
|
||
elif "ダンス" in ret.text:
|
||
lesson_text = "Da"
|
||
elif "ビジュアル" in ret.text:
|
||
lesson_text = "Vi"
|
||
elif "休" in ret.text or "体力" in ret.text:
|
||
rest()
|
||
return 'rest'
|
||
else:
|
||
return None
|
||
logger.info("Rec. lesson: %s", lesson_text)
|
||
# 点击课程
|
||
logger.debug("Try clicking lesson...")
|
||
lesson_ret = ocr.expect(contains(lesson_text))
|
||
device.double_click(lesson_ret.rect)
|
||
return 'lesson'
|
||
else:
|
||
if "ボーカル" in ret.text:
|
||
template = R.InPurodyuusu.ButtonFinalPracticeVocal
|
||
elif "ダンス" in ret.text:
|
||
template = R.InPurodyuusu.ButtonFinalPracticeDance
|
||
elif "ビジュアル" in ret.text:
|
||
template = R.InPurodyuusu.ButtonFinalPracticeVisual
|
||
else:
|
||
return None
|
||
logger.debug("Try clicking lesson...")
|
||
device.double_click(image.expect_wait(template))
|
||
return 'lesson'
|
||
|
||
def before_start_action():
|
||
"""检测支援卡剧情、领取资源等"""
|
||
raise NotImplementedError()
|
||
|
||
def click_recommended_card(timeout: float = 7, card_count: int = 3) -> int:
|
||
"""点击推荐卡片
|
||
|
||
:param timeout: 超时时间(秒)
|
||
:param card_count: 卡片数量(2-4)
|
||
:return: 执行结果。-1=失败,0~3=卡片位置,10=跳过此回合。
|
||
"""
|
||
import cv2
|
||
import numpy as np
|
||
from cv2.typing import MatLike
|
||
|
||
# 定义检测参数
|
||
TARGET_ASPECT_RATIO_RANGE = (0.73, 0.80)
|
||
TARGET_COLOR = (240, 240, 240)
|
||
YELLOW_LOWER = np.array([20, 100, 100])
|
||
YELLOW_UPPER = np.array([30, 255, 255])
|
||
GLOW_EXTENSION = 10 # 向外扩展的像素数
|
||
GLOW_THRESHOLD = 1200 # 荧光值阈值
|
||
|
||
# 固定的卡片坐标 (for 720x1280)
|
||
CARD_POSITIONS_1 = [
|
||
# 格式:(x, y, w, h, return_value)
|
||
(264, 883, 192, 252, 0)
|
||
]
|
||
CARD_POSITIONS_2 = [
|
||
(156, 883, 192, 252, 1),
|
||
(372, 883, 192, 252, 2),
|
||
# delta_x = 216, delta_x-width = 24
|
||
]
|
||
CARD_POSITIONS_3 = [
|
||
(47, 883, 192, 252, 0), # 左卡片 (x, y, w, h)
|
||
(264, 883, 192, 252, 1), # 中卡片
|
||
(481, 883, 192, 252, 2) # 右卡片
|
||
# delta_x = 217, delta_x-width = 25
|
||
]
|
||
CARD_POSITIONS_4 = [
|
||
(17, 883, 192, 252, 0),
|
||
(182, 883, 192, 252, 1),
|
||
(346, 883, 192, 252, 2),
|
||
(511, 883, 192, 252, 3),
|
||
# delta_x = 165, delta_x-width = -27
|
||
]
|
||
SKIP_POSITION = (621, 739, 85, 85, 10)
|
||
|
||
@deprecated('此方法待改进')
|
||
def calc_pos(card_count: int):
|
||
# 根据卡片数量计算实际位置
|
||
CARD_PAD = 25
|
||
CARD_SCREEN_PAD = 17
|
||
card_positions = []
|
||
|
||
# 计算卡片位置
|
||
if card_count == 1:
|
||
card_positions = [CARD_POSITIONS_3[1]] # 只使用中间位置
|
||
else:
|
||
# 计算原始卡片间距
|
||
card_spacing = CARD_POSITIONS_3[1][0] - CARD_POSITIONS_3[0][0]
|
||
card_width = CARD_POSITIONS_3[0][2]
|
||
|
||
# 计算屏幕可用宽度
|
||
screen_width = 720
|
||
available_width = screen_width - (CARD_SCREEN_PAD * 2)
|
||
|
||
# 计算使用原始间距时的总宽度
|
||
original_total_width = (card_count - 1) * card_spacing + card_width
|
||
|
||
# 判断是否需要重叠布局
|
||
if original_total_width > available_width:
|
||
spacing = (available_width - card_width * card_count - CARD_SCREEN_PAD * 2) // (card_count)
|
||
start_x = CARD_SCREEN_PAD
|
||
else:
|
||
spacing = card_spacing
|
||
start_x = (screen_width - original_total_width) // 2
|
||
|
||
# 生成所有卡片位置
|
||
x = start_x
|
||
for i in range(card_count):
|
||
y = CARD_POSITIONS_3[0][1]
|
||
w = CARD_POSITIONS_3[0][2]
|
||
h = CARD_POSITIONS_3[0][3]
|
||
card_positions.append((round(x), round(y), round(w), round(h)))
|
||
x += spacing + card_width
|
||
return card_positions
|
||
|
||
def calc_pos2(card_count: int):
|
||
if card_count == 1:
|
||
return CARD_POSITIONS_1
|
||
elif card_count == 2:
|
||
return CARD_POSITIONS_2
|
||
elif card_count == 3:
|
||
return CARD_POSITIONS_3
|
||
elif card_count == 4:
|
||
return CARD_POSITIONS_4
|
||
else:
|
||
raise ValueError(f"Unsupported card count: {card_count}")
|
||
|
||
if card_count == 4:
|
||
# 随机选择一张卡片点击
|
||
# TODO: 支持对四张卡片进行检测
|
||
logger.warning("4 cards detected, detecting glowing card in 4 cards is not supported yet.")
|
||
logger.info("Click random card")
|
||
card_index = random.randint(0, 3)
|
||
device.click(CARD_POSITIONS_4[card_index][:4])
|
||
sleep(1)
|
||
device.click(CARD_POSITIONS_4[card_index][:4])
|
||
return card_index
|
||
|
||
start_time = time.time()
|
||
while time.time() - start_time < timeout:
|
||
img = device.screenshot()
|
||
|
||
# 检测卡片
|
||
card_glows = []
|
||
for x, y, w, h, return_value in calc_pos2(card_count) + [SKIP_POSITION]:
|
||
# 获取扩展后的卡片区域坐标
|
||
outer_x = max(0, x - GLOW_EXTENSION)
|
||
outer_y = max(0, y - GLOW_EXTENSION)
|
||
outer_w = w + (GLOW_EXTENSION * 2)
|
||
outer_h = h + (GLOW_EXTENSION * 2)
|
||
|
||
# 获取内外两个区域
|
||
outer_region = img[outer_y:y+h+GLOW_EXTENSION, outer_x:x+w+GLOW_EXTENSION]
|
||
inner_region = img[y:y+h, x:x+w]
|
||
|
||
# 创建掩码
|
||
outer_hsv = cv2.cvtColor(outer_region, cv2.COLOR_BGR2HSV)
|
||
inner_hsv = cv2.cvtColor(inner_region, cv2.COLOR_BGR2HSV)
|
||
|
||
# 计算外部区域的黄色部分
|
||
outer_mask = cv2.inRange(outer_hsv, YELLOW_LOWER, YELLOW_UPPER)
|
||
inner_mask = cv2.inRange(inner_hsv, YELLOW_LOWER, YELLOW_UPPER)
|
||
|
||
# 创建环形区域的掩码(仅计算扩展区域的荧光值)
|
||
ring_mask = outer_mask.copy()
|
||
ring_mask[GLOW_EXTENSION:GLOW_EXTENSION+h, GLOW_EXTENSION:GLOW_EXTENSION+w] = 0
|
||
|
||
# 计算环形区域的荧光值
|
||
glow_value = cv2.countNonZero(ring_mask)
|
||
|
||
card_glows.append((x, y, w, h, glow_value, return_value))
|
||
|
||
# 找到荧光值最高的卡片
|
||
if not card_glows:
|
||
logger.debug("No glowing card found, retrying...")
|
||
continue
|
||
else:
|
||
max_glow_card = max(card_glows, key=lambda x: x[4])
|
||
x, y, w, h, glow_value, return_value = max_glow_card
|
||
if glow_value < GLOW_THRESHOLD:
|
||
logger.debug("Glow value is too low, retrying...")
|
||
continue
|
||
|
||
# 点击卡片中心
|
||
logger.debug(f"Click glowing card at: ({x + w//2}, {y + h//2})")
|
||
device.click(x + w//2, y + h//2)
|
||
sleep(random.uniform(0.5, 1.5))
|
||
device.click(x + w//2, y + h//2)
|
||
# 体力溢出提示框
|
||
ret = image.wait_for(R.InPurodyuusu.ButtonConfirm, timeout=1)
|
||
if ret is not None:
|
||
logger.info("Skill card confirmation dialog detected")
|
||
device.click(ret)
|
||
if return_value == 10:
|
||
logger.info("No enough AP. Skip this turn")
|
||
elif return_value == -1:
|
||
logger.warning("No glowing card found")
|
||
else:
|
||
logger.info("Recommended card is Card %d", return_value + 1)
|
||
return return_value
|
||
return -1
|
||
|
||
@deprecated('此方法待改进')
|
||
def skill_card_count1():
|
||
"""获取当前持有的技能卡数量"""
|
||
img = device.screenshot()
|
||
img = crop_y(img, 0.83, 0.90)
|
||
# 黑白
|
||
img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
|
||
# 白色 -> 黑色
|
||
# 仅将白色(255)替换为黑色(0),保持其他颜色不变
|
||
img[img == 255] = 0
|
||
# 二值化
|
||
_, img = cv2.threshold(img, 240, 255, cv2.THRESH_BINARY)
|
||
debug.show(img)
|
||
ret = ocr.raw('en').ocr(img)
|
||
# 统计字母 A、M 数量
|
||
count = 0
|
||
for item in ret:
|
||
if 'A' in item.text or 'M' in item.text:
|
||
count += 1
|
||
logger.info("Current skill card count: %d", count)
|
||
return count
|
||
|
||
def skill_card_count():
|
||
"""获取当前持有的技能卡数量"""
|
||
img = device.screenshot()
|
||
img = crop_y(img, 0.83, 0.90)
|
||
count = image.raw().count(img, R.InPurodyuusu.A, threshold=0.85)
|
||
count += image.raw().count(img, R.InPurodyuusu.M, threshold=0.85)
|
||
logger.info("Current skill card count: %d", count)
|
||
return count
|
||
|
||
def remaing_turns_and_points():
|
||
"""获取剩余回合数和积分"""
|
||
ret = ocr.ocr()
|
||
logger.debug("ocr.ocr: %s", ret)
|
||
def index_of(text: str) -> int:
|
||
for i, item in enumerate(ret):
|
||
# CLEARまで -> CLEARまで
|
||
if text == unicodedata.normalize('NFKC', item.text):
|
||
return i
|
||
return -1
|
||
turns_tip_index = index_of("残りターン数")
|
||
points_tip_index = index_of("CLEARまで")
|
||
turns_rect = ret[turns_tip_index].rect
|
||
# 向下扩展100像素
|
||
turns_rect_extended = (
|
||
turns_rect[0], # x
|
||
turns_rect[1], # y
|
||
turns_rect[2], # width
|
||
turns_rect[3] + 100 # height + 100
|
||
)
|
||
|
||
# 裁剪并再次识别
|
||
turns_img = device.screenshot()[
|
||
turns_rect_extended[1]:turns_rect_extended[1]+turns_rect_extended[3],
|
||
turns_rect_extended[0]:turns_rect_extended[0]+turns_rect_extended[2]
|
||
]
|
||
turns_ocr = ocr.ocr(turns_img)
|
||
logger.debug("turns_ocr: %s", turns_ocr)
|
||
|
||
|
||
|
||
def rest():
|
||
"""执行休息"""
|
||
logger.info("Rest for this week.")
|
||
# 点击休息
|
||
device.click(image.expect_wait(R.InPurodyuusu.Rest))
|
||
# 确定
|
||
device.click(image.expect_wait(R.InPurodyuusu.RestConfirmBtn))
|
||
|
||
|
||
|
||
def until_action_scene():
|
||
"""等待进入行动场景"""
|
||
# 检测是否到行动页面
|
||
while not image.wait_for_any([
|
||
R.InPurodyuusu.TextPDiary, # 普通周
|
||
R.InPurodyuusu.ButtonFinalPracticeDance # 离考试剩余一周
|
||
], timeout=1):
|
||
logger.info("Action scene not detected. Retry...")
|
||
acquisitions()
|
||
sleep(1)
|
||
else:
|
||
logger.info("Now at action scene.")
|
||
return
|
||
|
||
def until_practice_scene():
|
||
"""等待进入练习场景"""
|
||
while image.wait_for(R.InPurodyuusu.TextClearUntil, timeout=1) is None:
|
||
acquisitions()
|
||
sleep(1)
|
||
|
||
def until_exam_scene():
|
||
"""等待进入考试场景"""
|
||
while ocr.find(regex("合格条件|三位以上")) is None:
|
||
acquisitions()
|
||
sleep(1)
|
||
|
||
def practice():
|
||
"""执行练习"""
|
||
logger.info("Practice started")
|
||
# 循环打出推荐卡
|
||
no_card_count = 0
|
||
MAX_NO_CARD_COUNT = 3
|
||
while True:
|
||
with device.pinned():
|
||
count = skill_card_count()
|
||
if count == 0:
|
||
logger.info("No skill card found. Wait and retry...")
|
||
# no_card_count += 1
|
||
# if no_card_count >= MAX_NO_CARD_COUNT:
|
||
# break
|
||
if not image.find_any([
|
||
R.InPurodyuusu.TextPerfectUntil,
|
||
R.InPurodyuusu.TextClearUntil
|
||
]):
|
||
logger.info("PERFECTまで/CLEARまで not found. Practice finished.")
|
||
break
|
||
sleep(3)
|
||
continue
|
||
if click_recommended_card(card_count=count) == -1:
|
||
logger.info("Click recommended card failed. Retry...")
|
||
continue
|
||
logger.info("Wait for next turn...")
|
||
sleep(9) # TODO: 采用更好的方式检测练习结束
|
||
# 跳过动画
|
||
logger.info("Recommend card not found. Practice finished.")
|
||
ocr.expect_wait(contains("上昇"))
|
||
logger.info("Click to finish 上昇 ")
|
||
device.click_center()
|
||
|
||
def exam():
|
||
"""执行考试"""
|
||
logger.info("Exam started")
|
||
# 循环打出推荐卡
|
||
no_card_count = 0
|
||
MAX_NO_CARD_COUNT = 3
|
||
while True:
|
||
count = skill_card_count()
|
||
if count == 0:
|
||
logger.info("No skill card found. Wait and retry...")
|
||
no_card_count += 1
|
||
if no_card_count >= MAX_NO_CARD_COUNT:
|
||
break
|
||
sleep(3)
|
||
continue
|
||
if click_recommended_card(card_count=count) == -1:
|
||
break
|
||
sleep(9) # TODO: 采用更好的方式检测练习结束
|
||
|
||
# 点击“次へ”
|
||
device.click(image.expect_wait(R.InPurodyuusu.NextBtn))
|
||
while ocr.wait_for(contains("メモリー"), timeout=7):
|
||
device.click_center()
|
||
|
||
def produce_end():
|
||
"""执行考试结束"""
|
||
# 考试结束对话
|
||
image.expect_wait(R.InPurodyuusu.TextAsariProduceEnd, timeout=30)
|
||
bottom = (int(device.screen_size[0] / 2), int(device.screen_size[1] * 0.9))
|
||
device.click(*bottom)
|
||
sleep(3)
|
||
device.click_center()
|
||
sleep(3)
|
||
device.click(*bottom)
|
||
sleep(3)
|
||
device.click(*bottom)
|
||
sleep(3)
|
||
|
||
# MV
|
||
# 等就可以了,反正又不要自己操作(
|
||
|
||
# 结算
|
||
# 最終プロデュース評価
|
||
image.expect_wait(R.InPurodyuusu.TextFinalProduceRating, timeout=60 * 2.5)
|
||
device.click_center()
|
||
sleep(3)
|
||
# 次へ
|
||
device.click(image.expect_wait(R.InPurodyuusu.ButtonNextNoIcon))
|
||
sleep(1)
|
||
# 決定
|
||
device.click(image.expect_wait(R.InPurodyuusu.ButtonConfirm, threshold=0.8))
|
||
sleep(1)
|
||
# 上传图片。注意网络可能会很慢,可能出现上传失败对话框
|
||
retry_count = 0
|
||
MAX_RETRY_COUNT = 5
|
||
while True:
|
||
# 处理上传失败
|
||
if image.find(R.InPurodyuusu.ButtonRetry):
|
||
logger.info("Upload failed. Retry...")
|
||
retry_count += 1
|
||
if retry_count >= MAX_RETRY_COUNT:
|
||
logger.info("Upload failed. Max retry count reached.")
|
||
logger.info("Cancel upload.")
|
||
device.click(image.expect_wait(R.InPurodyuusu.ButtonCancel))
|
||
sleep(2)
|
||
continue
|
||
device.click()
|
||
# 记忆封面保存失败提示
|
||
elif image.find(R.InPurodyuusu.ButtonClose):
|
||
logger.info("Memory cover save failed. Click to close.")
|
||
device.click()
|
||
# 结算完毕
|
||
elif image.find(R.InPurodyuusu.ButtonNextNoIcon):
|
||
logger.info("Finalize")
|
||
device.click()
|
||
device.click(image.expect_wait(R.InPurodyuusu.ButtonNextNoIcon))
|
||
device.click(image.expect_wait(R.InPurodyuusu.ButtonNextNoIcon))
|
||
device.click(image.expect_wait(R.InPurodyuusu.ButtonComplete))
|
||
# 关注提示
|
||
# if image.wait_for(R.InPurodyuusu.ButtonFollowProducer, timeout=2):
|
||
# device.click(image.expect_wait(R.InPurodyuusu.ButtonCancel))
|
||
break
|
||
# 开始生成记忆
|
||
# elif image.find(R.InPurodyuusu.ButtonGenerateMemory):
|
||
# logger.info("Click generate memory button")
|
||
# device.click()
|
||
# 跳过结算内容
|
||
else:
|
||
device.click_center()
|
||
sleep(2)
|
||
|
||
|
||
def hajime_regular(week: int = -1, start_from: int = 1):
|
||
"""
|
||
「初」 Regular 模式
|
||
|
||
:param week: 第几周,从1开始,-1表示全部
|
||
:param start_from: 从第几周开始,从1开始。
|
||
"""
|
||
def week1():
|
||
"""
|
||
第一周 期中考试剩余5周\n
|
||
行动:Vo.レッスン、Da.レッスン、Vi.レッスン
|
||
"""
|
||
enter_recommended_action()
|
||
loading.wait_loading_start()
|
||
logger.info("Loading...")
|
||
loading.wait_loading_end()
|
||
logger.info("Loading end")
|
||
# 支援卡判断
|
||
practice()
|
||
|
||
|
||
def week2():
|
||
"""
|
||
第二周 期中考试剩余4周\n
|
||
行动:授業(学习)
|
||
"""
|
||
# 点击“授業”
|
||
rect = image.expect_wait(R.InPurodyuusu.Action.ActionStudy).rect
|
||
device.click(rect)
|
||
sleep(0.5)
|
||
device.click(rect)
|
||
# 等待加载
|
||
loading.wait_loading_start()
|
||
logger.info("Loading...")
|
||
# 等待加载结束
|
||
loading.wait_loading_end()
|
||
logger.info("Loading end")
|
||
# 判断是否触发支援卡剧情
|
||
|
||
# TODO:检查是否有支援卡要领取的技能卡
|
||
|
||
# 等待加载
|
||
loading.wait_loading_start()
|
||
logger.info("Loading...")
|
||
# 等待加载结束
|
||
loading.wait_loading_end()
|
||
logger.info("Loading end")
|
||
|
||
# 进入授業页面
|
||
pos = image.expect_wait(R.InPurodyuusu.Action.VocalWhiteBg).rect
|
||
device.click(pos)
|
||
sleep(0.5)
|
||
device.click(pos)
|
||
# 选择选项
|
||
# TODO: 不固定点击 Vocal
|
||
device.double_click(image.expect_wait(R.InPurodyuusu.Action.VocalWhiteBg).rect)
|
||
# 领取技能卡
|
||
acquire_skill_card()
|
||
|
||
# 三次加载画面
|
||
loading.wait_loading_start()
|
||
logger.info("Loading 1...")
|
||
loading.wait_loading_end()
|
||
logger.info("Loading 1 end")
|
||
loading.wait_loading_start()
|
||
logger.info("Loading 2...")
|
||
loading.wait_loading_end()
|
||
logger.info("Loading 2 end")
|
||
loading.wait_loading_start()
|
||
logger.info("Loading 3...")
|
||
loading.wait_loading_end()
|
||
logger.info("Loading 3 end")
|
||
|
||
def week3():
|
||
"""
|
||
第三周 期中考试剩余3周\n
|
||
行动:Vo.レッスン、Da.レッスン、Vi.レッスン、授業
|
||
"""
|
||
week1()
|
||
|
||
def week4():
|
||
"""
|
||
第四周 期中考试剩余2周\n
|
||
行动:おでかけ、相談、活動支給
|
||
"""
|
||
week3()
|
||
|
||
def week5():
|
||
"""TODO"""
|
||
|
||
def week6():
|
||
"""期中考试"""
|
||
|
||
def week7():
|
||
"""第七周 期末考试剩余6周"""
|
||
if not enter_recommended_action():
|
||
rest()
|
||
|
||
def week8():
|
||
"""
|
||
第八周 期末考试剩余5周\n
|
||
行动:授業、活動支給
|
||
"""
|
||
if not enter_recommended_action():
|
||
rest()
|
||
|
||
def week_lesson():
|
||
until_action_scene()
|
||
executed_action = enter_recommended_action()
|
||
logger.info("Executed recommended action: %s", executed_action)
|
||
if executed_action == 'lesson':
|
||
sleep(5)
|
||
until_practice_scene()
|
||
practice()
|
||
elif executed_action == 'rest':
|
||
pass
|
||
elif executed_action is None:
|
||
rest()
|
||
until_action_scene()
|
||
|
||
def week_non_lesson():
|
||
"""非练习周。可能可用行动包括:おでかけ、相談、活動支給、授業"""
|
||
until_action_scene()
|
||
if allowance_available():
|
||
enter_allowance()
|
||
# elif study_available():
|
||
# enter_study()
|
||
until_action_scene()
|
||
|
||
def week_final_lesson():
|
||
if enter_recommended_action(final_week=True) != 'lesson':
|
||
raise ValueError("Failed to enter recommended action on final week.")
|
||
sleep(5)
|
||
until_practice_scene()
|
||
practice()
|
||
# until_exam_scene()
|
||
|
||
def week_mid_exam():
|
||
logger.info("Week mid exam started.")
|
||
logger.info("Wait for exam scene...")
|
||
until_exam_scene()
|
||
logger.info("Exam scene detected.")
|
||
sleep(5)
|
||
device.click_center()
|
||
sleep(5)
|
||
exam()
|
||
until_action_scene()
|
||
|
||
def week_final_exam():
|
||
logger.info("Week final exam started.")
|
||
logger.info("Wait for exam scene...")
|
||
until_exam_scene()
|
||
logger.info("Exam scene detected.")
|
||
sleep(5)
|
||
device.click_center()
|
||
sleep(5)
|
||
exam()
|
||
produce_end()
|
||
|
||
weeks = [
|
||
week_lesson, # 1: Vo.レッスン、Da.レッスン、Vi.レッスン
|
||
week_lesson, # 2: 授業
|
||
week_lesson, # 3: Vo.レッスン、Da.レッスン、Vi.レッスン、授業
|
||
week_non_lesson, # 4: おでかけ、相談、活動支給
|
||
week_final_lesson, # 5: 追い込みレッスン
|
||
week_mid_exam, # 6: 中間試験
|
||
week_non_lesson, # 7: おでかけ、活動支給
|
||
week_non_lesson, # 8: 授業、活動支給
|
||
week_lesson, # 9: Vo.レッスン、Da.レッスン、Vi.レッスン
|
||
week_lesson, # 10: Vo.レッスン、Da.レッスン、Vi.レッスン、授業
|
||
week_non_lesson, # 11: おでかけ、相談、活動支給
|
||
week_final_lesson, # 12: 追い込みレッスン
|
||
week_final_exam, # 13: 最終試験
|
||
]
|
||
if week != -1:
|
||
logger.info("Week %d started.", week)
|
||
weeks[week - 1]()
|
||
else:
|
||
for i, w in enumerate(weeks[start_from-1:]):
|
||
logger.info("Week %d started.", i + start_from)
|
||
w()
|
||
|
||
def purodyuusu(
|
||
# TODO: 参数:成员、支援、记忆、 两个道具
|
||
):
|
||
# 流程:
|
||
# 1. Sensei 对话
|
||
# 2. Idol 对话
|
||
# 3. 领取P饮料(?)
|
||
# 4. 触发支援卡事件。触发后必定需要领取物品
|
||
pass
|
||
|
||
|
||
__actions__ = [enter_recommended_action]
|
||
|
||
if __name__ == '__main__':
|
||
from logging import getLogger
|
||
logging.basicConfig(level=logging.INFO, format='[%(asctime)s] [%(levelname)s] [%(name)s] %(message)s')
|
||
getLogger('kotonebot').setLevel(logging.DEBUG)
|
||
getLogger(__name__).setLevel(logging.DEBUG)
|
||
init_context()
|
||
|
||
# while not image.wait_for_any([
|
||
# R.InPurodyuusu.TextPDiary, # 普通周
|
||
# R.InPurodyuusu.ButtonFinalPracticeDance # 离考试剩余一周
|
||
# ], timeout=2):
|
||
# logger.info("Action scene not detected. Retry...")
|
||
# acquisitions()
|
||
# sleep(3)
|
||
|
||
# image.wait_for_any([
|
||
# R.InPurodyuusu.TextPDiary, # 普通周
|
||
# R.InPurodyuusu.ButtonFinalPracticeDance # 离考试剩余一周
|
||
# ], timeout=2)
|
||
# while True:
|
||
# sleep(10)
|
||
|
||
# exam()
|
||
# produce_end()
|
||
# enter_recommended_action()
|
||
# remaing_turns_and_points()
|
||
# practice()
|
||
# until_action_scene()
|
||
# acquisitions()
|
||
# acquire_pdorinku(0)
|
||
# image.wait_for(R.InPurodyuusu.InPractice.PDorinkuIcon)
|
||
hajime_regular(start_from=9)
|
||
# until_practice_scene()
|
||
# device.click(image.expect_wait_any([
|
||
# R.InPurodyuusu.PSkillCardIconBlue,
|
||
# R.InPurodyuusu.PSkillCardIconColorful
|
||
# ]).rect)
|
||
# exam()
|
||
# device.double_click(image.expect_wait(R.InPurodyuusu.Action.VocalWhiteBg).rect)
|
||
# print(skill_card_count())
|
||
# click_recommended_card(card_count=skill_card_count())
|
||
# click_recommended_card(card_count=2)
|
||
# acquire_skill_card()
|
||
# rest()
|
||
# enter_recommended_lesson(final_week=True)
|