fix(*): 修复若干 bug
1. 修复了TextNotFoundError 消息格式化有误 2. 修复了某些情况下无法进入 Vo/Da/Vi 行动 3. 修复了某些情况下会卡在练习结束页面、考试开始页面
This commit is contained in:
parent
36dc50ce97
commit
1a8346d0e3
|
@ -113,10 +113,7 @@ class TextNotFoundError(Exception):
|
||||||
def __init__(self, pattern: str | re.Pattern | StringMatchFunction, image: 'MatLike'):
|
def __init__(self, pattern: str | re.Pattern | StringMatchFunction, image: 'MatLike'):
|
||||||
self.pattern = pattern
|
self.pattern = pattern
|
||||||
self.image = image
|
self.image = image
|
||||||
if isinstance(pattern, (str, re.Pattern)):
|
super().__init__(f"Expected text not found: {pattern}")
|
||||||
super().__init__(f"Expected text not found: {pattern}")
|
|
||||||
else:
|
|
||||||
super().__init__(f"Expected text not found: {pattern.__name__}")
|
|
||||||
|
|
||||||
class TextComparator:
|
class TextComparator:
|
||||||
def __init__(self, name: str, text: str, func: Callable[[str], bool]):
|
def __init__(self, name: str, text: str, func: Callable[[str], bool]):
|
||||||
|
|
|
@ -193,18 +193,30 @@ class AdaptiveWait:
|
||||||
self.start_time = None
|
self.start_time = None
|
||||||
|
|
||||||
class Countdown:
|
class Countdown:
|
||||||
def __init__(self, seconds: float):
|
def __init__(self, sec: float):
|
||||||
self.seconds = seconds
|
self.seconds = sec
|
||||||
self.start_time = time.time()
|
self.start_time: float | None = None
|
||||||
|
|
||||||
def __str__(self):
|
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):
|
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:
|
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):
|
def reset(self):
|
||||||
self.start_time = time.time()
|
self.start_time = time.time()
|
||||||
|
|
|
@ -106,11 +106,11 @@ def handle_recommended_action(final_week: bool = False) -> ActionType:
|
||||||
return None
|
return None
|
||||||
if not final_week:
|
if not final_week:
|
||||||
if result.index == 0:
|
if result.index == 0:
|
||||||
lesson_text = contains("Da")
|
lesson_text = regex("Da")
|
||||||
elif result.index == 1:
|
elif result.index == 1:
|
||||||
lesson_text = regex("Vo|V0")
|
lesson_text = regex("Vo|V0|VO")
|
||||||
elif result.index == 2:
|
elif result.index == 2:
|
||||||
lesson_text = contains("Vi")
|
lesson_text = regex("Vi|V1|VI")
|
||||||
elif result.index == 3:
|
elif result.index == 3:
|
||||||
rest()
|
rest()
|
||||||
return 'rest'
|
return 'rest'
|
||||||
|
@ -380,7 +380,10 @@ def until_practice_scene():
|
||||||
@action('等待进入考试场景')
|
@action('等待进入考试场景')
|
||||||
def until_exam_scene():
|
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()
|
until_acquisition_clear()
|
||||||
|
|
||||||
@action('执行练习', screenshot_mode='manual')
|
@action('执行练习', screenshot_mode='manual')
|
||||||
|
@ -403,6 +406,7 @@ def practice():
|
||||||
# 循环打出推荐卡,直到练习结束
|
# 循环打出推荐卡,直到练习结束
|
||||||
wait = cycle([0.1, 0.3, 0.5]) # 见下方解释
|
wait = cycle([0.1, 0.3, 0.5]) # 见下方解释
|
||||||
tries = 1
|
tries = 1
|
||||||
|
break_cd = Countdown(sec=3)
|
||||||
while True:
|
while True:
|
||||||
start_time = time.time()
|
start_time = time.time()
|
||||||
img = device.screenshot()
|
img = device.screenshot()
|
||||||
|
@ -454,14 +458,20 @@ def practice():
|
||||||
delay = next(wait)
|
delay = next(wait)
|
||||||
logger.info("Tries: %d, Delay: %.2f", tries, delay)
|
logger.info("Tries: %d, Delay: %.2f", tries, delay)
|
||||||
sleep(delay)
|
sleep(delay)
|
||||||
elif (
|
|
||||||
|
if (
|
||||||
card_count == 0
|
card_count == 0
|
||||||
and not image.find_multi([
|
and not image.find_multi([
|
||||||
R.InPurodyuusu.TextClearUntil,
|
R.InPurodyuusu.TextClearUntil,
|
||||||
R.InPurodyuusu.TextPerfectUntil
|
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.")
|
logger.info("CLEAR/PERFECT not found. Practice finished.")
|
||||||
|
@ -664,9 +674,9 @@ def produce_end():
|
||||||
if image.find(R.Common.ButtonClose):
|
if image.find(R.Common.ButtonClose):
|
||||||
logger.info("Activity award claim dialog found. Click to close.")
|
logger.info("Activity award claim dialog found. Click to close.")
|
||||||
device.click()
|
device.click()
|
||||||
elif image.find(R.Common.ButtonNextNoIcon):
|
elif image.find(R.Common.ButtonNextNoIcon, colored=True):
|
||||||
logger.debug("Click next")
|
logger.debug("Click next")
|
||||||
device.click(image.expect_wait(R.Common.ButtonNextNoIcon))
|
device.click()
|
||||||
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 conf().produce.follow_producer:
|
||||||
|
|
|
@ -134,9 +134,9 @@ class DailyMoneyShopItems(IntEnum):
|
||||||
RechallengeTicket = 12
|
RechallengeTicket = 12
|
||||||
"""再挑戦チケット 重新挑战券"""
|
"""再挑戦チケット 重新挑战券"""
|
||||||
RecordKey = 13
|
RecordKey = 13
|
||||||
|
"""記録の鍵 解锁交流的物品"""
|
||||||
|
|
||||||
# 碎片
|
# 碎片
|
||||||
"""記録の鍵 解锁交流的物品"""
|
|
||||||
IdolPiece_倉本千奈_WonderScale = 14
|
IdolPiece_倉本千奈_WonderScale = 14
|
||||||
"""倉本千奈 WonderScale 碎片"""
|
"""倉本千奈 WonderScale 碎片"""
|
||||||
IdolPiece_篠泽广_光景 = 15
|
IdolPiece_篠泽广_光景 = 15
|
||||||
|
|
|
@ -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.CheckboxIconSupportPtBoost))
|
||||||
device.click(image.expect_wait(R.Produce.ButtonProduceStart))
|
device.click(image.expect_wait(R.Produce.ButtonProduceStart))
|
||||||
# 5. 相关设置弹窗 [screenshots/produce/skip_commu.png]
|
# 5. 相关设置弹窗 [screenshots/produce/skip_commu.png]
|
||||||
cd = Countdown(5)
|
cd = Countdown(5).start()
|
||||||
while not cd.expired():
|
while not cd.expired():
|
||||||
device.screenshot()
|
device.screenshot()
|
||||||
if image.find(R.Produce.RadioTextSkipCommu):
|
if image.find(R.Produce.RadioTextSkipCommu):
|
||||||
|
|
Loading…
Reference in New Issue