feat(测试): 为赛马模拟测试添加实时进度展示选项

添加对测试命令的参数解析,支持通过关键词触发实时展示赛马进度。
调整模拟配置以支持可控的回合间隔,并增加超时时间以适应展示模式。
This commit is contained in:
2026-04-04 21:55:12 +08:00
parent 488c6fa6f6
commit 79d1f69ec5

View File

@@ -199,11 +199,14 @@ class _NoopMessageService:
@test_simulate_race_cmd.handle()
async def handle_test_simulate_race(bot: Bot, event: Event):
if not await check_tester(event):
await test_simulate_race_cmd.finish("权限不足")
await test_simulate_race_cmd.send("权限不足")
return
await test_simulate_race_cmd.send("收到:测试模拟赛马,开始执行完全模拟(无真实积分/数据库副作用)")
raw_msg = str(event.get_message()).strip()
stream_progress = ("展示" in raw_msg) or ("实时" in raw_msg) or ("" in raw_msg)
scope = get_scope(event)
try:
race_engine.stop_race(scope)
@@ -215,12 +218,12 @@ async def handle_test_simulate_race(bot: Bot, event: Event):
original_message_service = commands_mod.message_service
original_tick_interval = commands_mod.config.RACE_TICK_INTERVAL
original_stop_race = commands_mod.race_engine.stop_race
original_send_to_scope = commands_mod._send_to_scope
fake_room_store = _InMemoryRoomStore()
fake_points_service = _InMemoryPointsService()
fake_message_service = _NoopMessageService()
fake_bot = _FakeBot()
start_task: asyncio.Task | None = None
room = None
@@ -230,9 +233,26 @@ async def handle_test_simulate_race(bot: Bot, event: Event):
commands_mod.room_store = fake_room_store
commands_mod.points_service = fake_points_service
commands_mod.message_service = fake_message_service
commands_mod.config.RACE_TICK_INTERVAL = 0
commands_mod.config.RACE_TICK_INTERVAL = 1 if stream_progress else 0
commands_mod.race_engine.stop_race = lambda _scope: commands_mod.race_engine.active_tasks.pop(_scope, None)
progress_count = 0
max_progress = 30
async def _test_send_to_scope(_bot: Bot, _scope: str, message: str):
nonlocal progress_count
await fake_bot.send_msg(message_type="private", user_id=event.user_id, message=message)
if not stream_progress:
return
if message.startswith("【第") and "回合】" in message:
progress_count += 1
if progress_count > max_progress:
return
await test_simulate_race_cmd.send(message)
commands_mod._send_to_scope = _test_send_to_scope
room = fake_room_store.create_room(scope)
horse_names = _generate_random_horse_names(8)
for idx, horse_name in enumerate(horse_names, start=1):
@@ -251,47 +271,47 @@ async def handle_test_simulate_race(bot: Bot, event: Event):
await test_simulate_race_cmd.send("阶段:执行赛程(后台任务)")
start_task = asyncio.create_task(commands_mod.run_race_with_settlement(fake_bot, room, scope))
commands_mod.race_engine.register_task(scope, start_task)
await asyncio.wait_for(start_task, timeout=15)
await asyncio.wait_for(start_task, timeout=60 if stream_progress else 15)
messages = [m.get("message", "") for m in fake_bot.messages]
if not messages:
await test_simulate_race_cmd.finish("完全模拟失败:未捕获到任何消息")
await test_simulate_race_cmd.send("完全模拟失败:未捕获到任何消息")
return
if "比赛开始!" not in messages[0]:
await test_simulate_race_cmd.finish("完全模拟失败:未发送开赛消息")
await test_simulate_race_cmd.send("完全模拟失败:未发送开赛消息")
return
if not any("【第" in msg and "回合】" in msg for msg in messages):
await test_simulate_race_cmd.finish("完全模拟失败:未发送回合进度消息")
await test_simulate_race_cmd.send("完全模拟失败:未发送回合进度消息")
return
result_msg = messages[-1]
if "比赛结束!冠军:" not in result_msg:
await test_simulate_race_cmd.finish("完全模拟失败:未发送结束结算消息")
await test_simulate_race_cmd.send("完全模拟失败:未发送结束结算消息")
return
if not fake_room_store.saved_results:
await test_simulate_race_cmd.finish("完全模拟失败:未写入赛史结果(内存)")
await test_simulate_race_cmd.send("完全模拟失败:未写入赛史结果(内存)")
return
saved = fake_room_store.saved_results[-1]
if saved.champion_name not in room.horses:
await test_simulate_race_cmd.finish("完全模拟失败:赛史冠军不在参赛马匹中")
await test_simulate_race_cmd.send("完全模拟失败:赛史冠军不在参赛马匹中")
return
champion_owner_id = room.horses[saved.champion_name].owner_id
reward_champion_calls = [c for c in fake_points_service.calls if c[0] == "reward_champion"]
if not reward_champion_calls or reward_champion_calls[0][1]["user_id"] != champion_owner_id:
await test_simulate_race_cmd.finish("完全模拟失败:未正确发放冠军奖励(内存记录)")
await test_simulate_race_cmd.send("完全模拟失败:未正确发放冠军奖励(内存记录)")
return
participant_calls = [c for c in fake_points_service.calls if c[0] == "reward_participant"]
if len(participant_calls) != max(0, len(room.horses) - 1):
await test_simulate_race_cmd.finish("完全模拟失败:参赛奖励次数不匹配(内存记录)")
await test_simulate_race_cmd.send("完全模拟失败:参赛奖励次数不匹配(内存记录)")
return
await test_simulate_race_cmd.finish(
await test_simulate_race_cmd.send(
"\n".join(
[
"完全模拟赛马完成(无真实积分/数据库副作用)",
@@ -300,18 +320,20 @@ async def handle_test_simulate_race(bot: Bot, event: Event):
f"总回合:{saved.duration_ticks}",
f"消息条数:{len(messages)}(开赛/进度/结算均已覆盖)",
f"结算调用:{len(fake_points_service.calls)}(冠军/参赛/下注派奖)",
f"过程展示:{'开启' if stream_progress else '关闭'}",
]
)
)
return
except asyncio.TimeoutError:
ticks = room.tick_count if room else 0
await test_simulate_race_cmd.finish(f"完全模拟失败:超时未完成(当前回合:{ticks}")
await test_simulate_race_cmd.send(f"完全模拟失败:超时未完成(当前回合:{ticks}")
except asyncio.CancelledError:
ticks = room.tick_count if room else 0
await test_simulate_race_cmd.finish(f"完全模拟失败:任务被取消(当前回合:{ticks}")
await test_simulate_race_cmd.send(f"完全模拟失败:任务被取消(当前回合:{ticks}")
except Exception as e:
tail = "\n".join(traceback.format_exc().splitlines()[-8:])
await test_simulate_race_cmd.finish(f"完全模拟异常:{type(e).__name__}: {e}\n{tail}")
await test_simulate_race_cmd.send(f"完全模拟异常:{type(e).__name__}: {e}\n{tail}")
finally:
if start_task and not start_task.done():
start_task.cancel()
@@ -320,3 +342,4 @@ async def handle_test_simulate_race(bot: Bot, event: Event):
commands_mod.message_service = original_message_service
commands_mod.config.RACE_TICK_INTERVAL = original_tick_interval
commands_mod.race_engine.stop_race = original_stop_race
commands_mod._send_to_scope = original_send_to_scope