fix(*): 修复若干 bug

1. 修复了TextNotFoundError 消息格式化有误
2. 修复了某些情况下无法进入 Vo/Da/Vi 行动
3. 修复了某些情况下会卡在练习结束页面、考试开始页面
This commit is contained in:
XcantloadX 2025-02-13 20:32:56 +08:00
parent 36dc50ce97
commit 1a8346d0e3
5 changed files with 39 additions and 20 deletions

View File

@ -113,10 +113,7 @@ class TextNotFoundError(Exception):
def __init__(self, pattern: str | re.Pattern | StringMatchFunction, image: 'MatLike'):
self.pattern = pattern
self.image = image
if isinstance(pattern, (str, re.Pattern)):
super().__init__(f"Expected text not found: {pattern}")
else:
super().__init__(f"Expected text not found: {pattern.__name__}")
super().__init__(f"Expected text not found: {pattern}")
class TextComparator:
def __init__(self, name: str, text: str, func: Callable[[str], bool]):

View File

@ -193,18 +193,30 @@ class AdaptiveWait:
self.start_time = None
class Countdown:
def __init__(self, seconds: float):
self.seconds = seconds
self.start_time = time.time()
def __init__(self, sec: float):
self.seconds = sec
self.start_time: float | None = None
def __str__(self):
return f"{self.seconds - (time.time() - self.start_time):.0f}s"
if self.start_time is None:
return "Unstarted"
else:
return f"{self.seconds - (time.time() - self.start_time):.0f}s"
@property
def started(self) -> bool:
return self.start_time is not None
def start(self):
self.start_time = time.time()
if self.start_time is None:
self.start_time = time.time()
return self
def expired(self) -> bool:
return time.time() - self.start_time > self.seconds
if self.start_time is None:
return False
else:
return time.time() - self.start_time > self.seconds
def reset(self):
self.start_time = time.time()

View File

@ -106,11 +106,11 @@ def handle_recommended_action(final_week: bool = False) -> ActionType:
return None
if not final_week:
if result.index == 0:
lesson_text = contains("Da")
lesson_text = regex("Da")
elif result.index == 1:
lesson_text = regex("Vo|V0")
lesson_text = regex("Vo|V0|VO")
elif result.index == 2:
lesson_text = contains("Vi")
lesson_text = regex("Vi|V1|VI")
elif result.index == 3:
rest()
return 'rest'
@ -380,7 +380,10 @@ def until_practice_scene():
@action('等待进入考试场景')
def until_exam_scene():
"""等待进入考试场景"""
while ocr.find(regex("合格条件|三位以上")) is None:
# NOTE: is_exam_scene() 通过 OCR 剩余回合数判断是否处于考试场景。
# 本来有可能会与练习场景混淆,
# 但是在确定后续只是考试场景的情况下应该不会
while ocr.find(regex("合格条件|三位以上")) is None and not is_exam_scene():
until_acquisition_clear()
@action('执行练习', screenshot_mode='manual')
@ -403,6 +406,7 @@ def practice():
# 循环打出推荐卡,直到练习结束
wait = cycle([0.1, 0.3, 0.5]) # 见下方解释
tries = 1
break_cd = Countdown(sec=3)
while True:
start_time = time.time()
img = device.screenshot()
@ -454,14 +458,20 @@ def practice():
delay = next(wait)
logger.info("Tries: %d, Delay: %.2f", tries, delay)
sleep(delay)
elif (
if (
card_count == 0
and not image.find_multi([
R.InPurodyuusu.TextClearUntil,
R.InPurodyuusu.TextPerfectUntil
])
):
break
if not break_cd.started:
break_cd.start()
if break_cd.expired():
break
else:
break_cd.reset()
# 结束动画
logger.info("CLEAR/PERFECT not found. Practice finished.")
@ -664,9 +674,9 @@ def produce_end():
if image.find(R.Common.ButtonClose):
logger.info("Activity award claim dialog found. Click to close.")
device.click()
elif image.find(R.Common.ButtonNextNoIcon):
elif image.find(R.Common.ButtonNextNoIcon, colored=True):
logger.debug("Click next")
device.click(image.expect_wait(R.Common.ButtonNextNoIcon))
device.click()
elif image.find(R.InPurodyuusu.ButtonCancel):
logger.info("Follow producer dialog found. Click to close.")
if conf().produce.follow_producer:

View File

@ -134,9 +134,9 @@ class DailyMoneyShopItems(IntEnum):
RechallengeTicket = 12
"""再挑戦チケット 重新挑战券"""
RecordKey = 13
"""記録の鍵 解锁交流的物品"""
# 碎片
"""記録の鍵 解锁交流的物品"""
IdolPiece_倉本千奈_WonderScale = 14
"""倉本千奈 WonderScale 碎片"""
IdolPiece_篠泽广_光景 = 15

View File

@ -166,7 +166,7 @@ def do_produce(idol: PIdol, mode: Literal['regular', 'pro']):
device.click(image.expect_wait(R.Produce.CheckboxIconSupportPtBoost))
device.click(image.expect_wait(R.Produce.ButtonProduceStart))
# 5. 相关设置弹窗 [screenshots/produce/skip_commu.png]
cd = Countdown(5)
cd = Countdown(5).start()
while not cd.expired():
device.screenshot()
if image.find(R.Produce.RadioTextSkipCommu):