添加赛马实时进度播报

将比赛循环从race_engine移到commands中,每回合发送进度条:
  马匹名  |████████░░░░░░| 45.2m
race_engine改为提供tick/determine_champion/format_progress方法

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-04-04 01:32:42 +08:00
parent 1dd247ab4b
commit adccbfebb5
2 changed files with 64 additions and 50 deletions

View File

@@ -97,40 +97,55 @@ async def settle_race(room: Room):
room_store.save_race_result(result)
async def run_race_with_settlement(bot: Bot, room: Room, scope: str):
"""Run race and handle settlement + cleanup."""
task = await race_engine.start_race(room)
# Send start message
horse_list = "\n".join(f" {h.name} (主人: {h.owner_id})" for h in room.horses.values())
async def _send_to_scope(bot: Bot, scope: str, message: str):
"""Send message to group or private chat based on scope."""
try:
await bot.send_msg(
message_type="group" if scope.startswith("group_") else "private",
group_id=int(scope.split("_", 1)[1]) if scope.startswith("group_") else None,
user_id=int(scope.split("_", 1)[1]) if scope.startswith("test_") else None,
message=f"比赛开始!参赛马匹:\n{horse_list}",
message=message,
)
except Exception:
pass
# Wait for race to finish
async def run_race_with_settlement(bot: Bot, room: Room, scope: str):
"""Run race with live progress updates and settlement."""
room.state = RoomState.RUNNING
# Send start message with horse list
horse_list = "\n".join(f" {h.name}" for h in room.horses.values())
await _send_to_scope(bot, scope, f"比赛开始!\n{horse_list}")
# Race loop with progress updates
try:
await task
while room.state == RoomState.RUNNING:
await asyncio.sleep(config.RACE_TICK_INTERVAL)
finished = race_engine.tick(room)
progress = race_engine.format_progress(room)
await _send_to_scope(bot, scope, progress)
if finished:
champion = race_engine.determine_champion(finished)
room.champion_name = champion.name
room.state = RoomState.FINISHED
break
except asyncio.CancelledError:
room.state = RoomState.INTERRUPTED
# Refund all bets on interruption
for bet in room.bets:
await points_service.refund_bet_points(bet.user_id, bet.amount, "比赛中断退还")
return
# Race finished - settle
# Settle
await settle_race(room)
# Build result message
odds = calculate_odds(room)
champion = room.horses.get(room.champion_name)
result_lines = [
f"比赛结束!冠军:{room.champion_name} 🏆",
f"比赛结束!冠军:{room.champion_name}",
f"马主 {champion.owner_id if champion else '?'} 获得 {config.CHAMPION_REWARD} 积分",
]
winning_bets = [b for b in room.bets if b.horse_name == room.champion_name]
@@ -138,17 +153,9 @@ async def run_race_with_settlement(bot: Bot, room: Room, scope: str):
result_lines.append("下注中奖:")
for b in winning_bets:
payout = int(b.amount * odds.get(b.horse_name, config.MIN_ODDS))
result_lines.append(f" {b.user_id} 下注 {b.amount} 获得 {payout}")
result_lines.append(f" {b.user_id} 下注 {b.amount} -> 获得 {payout}")
try:
await bot.send_msg(
message_type="group" if scope.startswith("group_") else "private",
group_id=int(scope.split("_", 1)[1]) if scope.startswith("group_") else None,
user_id=int(scope.split("_", 1)[1]) if scope.startswith("test_") else None,
message="\n".join(result_lines),
)
except Exception:
pass
await _send_to_scope(bot, scope, "\n".join(result_lines))
# Cleanup
race_engine.stop_race(scope)
@@ -391,7 +398,8 @@ async def handle_start(bot: Bot, event: Event):
await start_cmd.finish("比赛开始!")
# Run race in background (outside command handler)
asyncio.create_task(run_race_with_settlement(bot, room, scope))
task = asyncio.create_task(run_race_with_settlement(bot, room, scope))
race_engine.register_task(scope, task)
help_cmd = on_command("赛马帮助", priority=5)