# Group Horse Racing 插件

群赛马插件 - 一个支持群组内多人参与的赛马游戏，集成积分系统和下注功能。

## 功能概述

这是一个完整的群组赛马游戏系统，支持以下核心功能：

- **马匹报名**：用户可以报名参加赛马比赛
- **下注系统**：支持用户对任意参赛马匹进行下注（含自己的马）
- **自动比赛**：基于随机算法的赛马进程模拟
- **积分集成**：与 danding_points 积分系统无缝集成
- **自动撤回**：支持配置消息自动撤回时间
- **多房间支持**：支持群组和私聊两种模式

## 命令列表

### 基础命令

| 命令 | 说明 | 示例 |
|------|------|------|
| `/赛马报名 <马匹名>` | 报名参加赛马比赛。若不输入则复用上次马名或使用昵称 | `/赛马报名 绝地赤兔` |
| `/赛马取消报名` | 取消报名并退还下注（限开始前） | `/赛马取消报名` |
| `/赛马下注 <序号|马名> <金额>` | 为马匹下注 | `/赛马下注 01 100` |
| `/赛马取消下注` | 取消本人所有下注并退还积分（限开始前） | `/赛马取消下注` |
| `/赛马赔率` | 查看当前赔率和下注池 | `/赛马赔率` |
| `/赛马列表` | 查看当前报名马匹列表 | `/赛马列表` |
| `/赛马开赛` | 开始比赛（需参赛者或管理员，至少2匹马） | `/赛马开赛` |
| `/赛马帮助` | 显示帮助信息 | `/赛马帮助` |

## 配置说明

### 环境变量

所有配置项都可通过环境变量设置，前缀为 `GROUP_HORSE_RACING_`

```python
# 测试模式
GROUP_HORSE_RACING_TEST_MODE=false

# 测试用户ID集合
GROUP_HORSE_RACING_TESTERS=[]

# 测试群组ID集合
GROUP_HORSE_RACING_TEST_GROUPS=[]

# 允许的群组ID集合
GROUP_HORSE_RACING_ALLOWED_GROUPS=[]
```

### 游戏配置

| 配置项 | 默认值 | 说明 |
|--------|--------|------|
| `PARTICIPANT_REWARD` | 20 | 参赛者奖励积分 |
| `CHAMPION_REWARD` | 150 | 冠军奖励积分 |
| `MIN_BET` | 10 | 最小下注积分 |
| `MIN_ODDS` | 1.2 | 最小赔率 |
| `RACE_DISTANCE` | 100 | 比赛距离 |
| `RACE_TICK_INTERVAL` | 5 | 比赛更新间隔（秒） |

### 消息撤回配置

可配置不同类型消息的自动撤回时间（秒，0表示不撤回）：

```python
MESSAGE_RECALL = {
    "race_update": 30,        # 比赛更新消息
    "registration": 180,      # 报名确认消息
    "bet_confirm": 180,       # 下注确认消息
    "cancel_confirm": 60,     # 取消确认消息
    "error": 60,              # 错误消息
    "race_result": 0,         # 比赛结果（不撤回）
    "leaderboard": 0,         # 排行榜（不撤回）
    "help": 0,                # 帮助信息（不撤回）
    "odds_display": 0,        # 赔率显示（不撤回）
}
```

### 数据库配置

```python
RACE_DB_FILE = "data/group_horse_racing/race.db"
```

## 核心模块

### models.py

定义了游戏中的数据模型：

- **RoomState**：房间状态枚举（WAITING、RUNNING、FINISHED、INTERRUPTED）
- **HorseState**：马匹状态枚举（READY、RACING、FINISHED）
- **Horse**：马匹数据类，包含所有者ID、名称、位置、状态
- **Bet**：下注数据类，包含用户ID、马匹名称、下注金额
- **Room**：房间数据类，管理马匹、下注、比赛状态
- **RaceResult**：比赛结果数据类，记录比赛统计信息

### race_engine.py

比赛引擎，负责比赛逻辑：

- **start_race()**：启动比赛循环
- **_race_loop()**：主比赛循环，每个tick更新马匹位置
- **_determine_champion()**：确定冠军（处理平局情况）

比赛采用高斯分布随机算法，每个tick马匹随机前进一定距离。

### points_service.py

积分服务，与 danding_points 插件集成：

- **spend_bet_points()**：扣除下注积分（支持重试）
- **refund_bet_points()**：退还下注积分
- **payout_winnings()**：支付中奖积分
- **reward_participant()**：奖励参赛者
- **reward_champion()**：奖励冠军
- **get_balance()**：获取用户余额

### message_service.py

消息服务，处理消息发送和自动撤回：

- **send_with_recall()**：发送消息并根据配置自动撤回
- **_schedule_recall()**：异步调度消息撤回
- **clear_pending_recalls()**：清除待撤回消息任务

### room_store.py

房间存储，管理比赛房间的生命周期：

- 支持并发访问控制（使用asyncio.Lock）
- 房间持久化存储
- 房间清理和过期处理

### commands.py

命令处理器，实现所有用户命令：

- **handle_register()**：处理报名命令
- **handle_cancel()**：处理取消报名命令
- **handle_bet()**：处理下注命令
- **handle_cancel_bet()**：处理取消下注命令
- **handle_odds()**：处理赔率显示命令
- **handle_race_list()**：处理马匹列表命令
- **handle_start()**：处理开赛命令（仅参赛者或管理员可操作）
- **handle_help()**：处理帮助命令

## 使用流程

### 基本游戏流程

1. **报名阶段**
   - 用户执行 `/赛马报名` 命令
   - 系统检查权限和房间容量（最多8匹马）
   - 成功报名

2. **下注阶段**
   - 用户可对参赛马匹进行下注
   - 下注金额需满足最小下注要求
   - 下注积分从用户账户扣除
   - 可以给自己的马下注

3. **比赛阶段**
   - 房主执行 `/赛马开赛` 命令
   - 系统启动比赛引擎
   - 每个tick更新马匹位置
   - 首先到达终点的马匹为冠军

4. **结算阶段**
   - 冠军获得冠军奖励
   - 中奖用户获得下注奖金（下注金额 × 赔率）
   - 比赛结果保存到数据库

## 权限控制

插件支持两种权限模式：

### 测试模式（TEST_MODE=true）

- 仅允许 `TEST_GROUPS` 中的群组使用
- 仅允许 `TESTERS` 中的用户在私聊中使用

### 正常模式（TEST_MODE=false）

- 仅允许 `ALLOWED_GROUPS` 中的群组使用
- 私聊中禁用

## 依赖关系

- **必需**：`danding_bot.plugins.danding_points` - 积分系统插件

## 数据存储

比赛数据存储在SQLite数据库中：

- 位置：`data/group_horse_racing/race.db`
- 存储内容：比赛历史、结果统计、用户数据

## 并发控制

- 使用 `asyncio.Lock` 保证房间操作的线程安全
- 支持多个房间同时进行比赛
- 每个房间有独立的锁和异步任务

## 错误处理

- 权限检查：无权限时返回错误提示
- 房间检查：房间不存在或已满时返回错误
- 参赛人数检查：少于2匹马时无法开赛
- 积分检查：积分不足时下注失败

## 测试

项目包含 `test_commands.py` 用于测试各项功能。

## 扩展建议

- 支持更多赛马属性（速度、耐力等）
- 实现赔率动态计算
- 添加排行榜功能
- 支持马匹升级系统
- 实现更复杂的下注规则
