Files

107 lines
3.3 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

## Technical Design
### 1. SQLite → aiosqlite
\\\python
# room_store.py
import aiosqlite
class RoomStore:
async def _get_conn(self) -> aiosqlite.Connection:
db_path = Path(self.config.DB_PATH)
db_path.parent.mkdir(parents=True, exist_ok=True)
conn = await aiosqlite.connect(str(db_path))
conn.row_factory = aiosqlite.Row
await conn.execute('''CREATE TABLE IF NOT EXISTS race_history (...)''')
await conn.commit()
return conn
async def get_last_horse_name(self, user_id: str) -> Optional[str]:
conn = await self._get_conn()
try:
cursor = await conn.execute("SELECT horse_name FROM ...", (user_id,))
row = await cursor.fetchone()
return row[0] if row else None
finally:
await conn.close()
\\\
> 每次操作独立连接和关闭保持与原逻辑一致,仅将同步调用替换为 async。
### 2. 积分重试加延时 + 区分失败原因
\\\python
# points_service.py
async def spend_bet_points(self, user_id: str, amount: int, reason: str = "赛马下注"):
success, balance = await points_api.spend_points(user_id, amount, "horse_race", reason)
if success:
return True, balance
# 余额不足不再重试
if balance < amount:
return False, balance
# 网络/其他失败短暂等待后重试一次
await asyncio.sleep(1.0)
success, balance = await points_api.spend_points(user_id, amount, "horse_race", reason)
return success, balance
\\\
### 3. 消息发送加日志
\\\python
# commands.py
import logging
logger = logging("group_horse_racing")
async def _send_to_scope(bot: Bot, scope: str, message: ...):
try:
if scope.startswith("group_"):
await bot.send_group_msg(...)
elif scope.startswith("test_"):
await bot.send_private_msg(...)
except Exception:
logger.warning(f"发送消息到 {scope} 失败", exc_info=True)
\\\
### 4. 赔率快照(结算时锁内固定)
在比赛结束结算时将赔率在 Room Lock 内计算后传入结算函数保证赔率与下注分布一致
\\\python
# 在 start_race 的 lock 内计算赔率快照
odds_snapshot = {}
for horse_name, horse in room.horses.items():
odds_snapshot[horse_name] = room.calculate_odds(horse_name) # 锁内计算
# 传入结算函数使用快照赔率
await _settle_race(bot, event, room, config, odds_snapshot)
\\\
### 5. 补存积分变化
\\\python
# room_store.py - save_race_result
await conn.execute(
"INSERT INTO race_history (...point_changes, point_change_summaries) VALUES (..., ?, ?)",
(...,
json.dumps(result.point_changes),
json.dumps(result.point_change_summaries))
)
\\\
需在 CREATE TABLE 中新增两个 TEXT 字段使用 \IF NOT EXISTS\ 保证兼容
### 6. 测试数据隔离
\\\python
# test_commands.py
from .commands import get_scope, check_access, race_engine, _rooms as prod_rooms
from .room_store import RoomStore as _RealRoomStore
# 测试命令用独立 store
_test_store = _RealRoomStore(config) # 或用内存 store
\\\
> 不再共享生产 room_store 实例,测试操作独立数据。
### 7. 马名去重统一
dict key 统一用 normalized namecasefold或在注册时统一用原始名但比较用 casefold