|
| 1 | +# 循环赛方案:调现有 API 接口 |
| 2 | + |
| 3 | +## 你已有的基础设施 |
| 4 | + |
| 5 | +`competition.ts` 第 19-497 行 `/start-all` 已经做完了一切: |
| 6 | + |
| 7 | +- 从 Hasura 拉取全部队伍和代码分配 |
| 8 | +- 从 COS 下载代码到服务器本地 |
| 9 | +- 生成所有两两配对(第 303-341 行) |
| 10 | +- 创建 `contest_room` + `contest_room_team` 数据库记录 |
| 11 | +- 推入 Docker 队列(Docker 容器由 cron 自动创建和调度) |
| 12 | + |
| 13 | +**你什么都不用写,只需要发请求。** |
| 14 | + |
| 15 | +## 唯一的问题 |
| 16 | + |
| 17 | +GameServer.cs 的 Mode 1(COMPETITION)下,`SendGameResult()` 被注释掉了(第 436 行),游戏结束后的得分**没有发回给 API**,所以 `/finish-one` 收不到分数,`contest_room_team.score` 永远是空的。 |
| 18 | + |
| 19 | +## 改动清单 |
| 20 | + |
| 21 | +### 1. GameServer.cs(已修复) |
| 22 | + |
| 23 | +`D:\THUthu\THUAI9\logic\Server\GameServer.cs` 第 424 行: |
| 24 | + |
| 25 | +```csharp |
| 26 | +else if (options.Mode == 1) |
| 27 | +{ |
| 28 | + bool gameCrashed = false; |
| 29 | + SendGameResult(rawMatchScores, gameCrashed); // ← 新:直接发原始得分 |
| 30 | + endGameSem.Release(); |
| 31 | +} |
| 32 | +``` |
| 33 | + |
| 34 | +### 2. 重建 Server Docker 镜像 |
| 35 | + |
| 36 | +```bash |
| 37 | +cd THUAI9 |
| 38 | +dotnet build logic/Server/Server.csproj -c Release |
| 39 | +docker build -t eesast/thuai9_run_server:latest \ |
| 40 | + -f dependency/Dockerfile/Dockerfile_run_server . |
| 41 | +``` |
| 42 | + |
| 43 | +### 3. API 新增两个路由 |
| 44 | + |
| 45 | +在 `api/src/routes/competition.ts` 加两个接口: |
| 46 | + |
| 47 | +**a) `POST /competition/ranking`** — 拿排名 |
| 48 | + |
| 49 | +调 `ContHasFunc.get_round_ranking(round_id)`,从 `contest_room_team` 聚合每个队伍在所有房间的 score,求和降序排列。 |
| 50 | + |
| 51 | +**b) `POST /competition/tournament-status`** — 看进度 |
| 52 | + |
| 53 | +返回 `{ total, finished, crashed, waiting, running }`,知道还剩几场没打完。 |
| 54 | + |
| 55 | +在 `api/src/hasura/contest.ts` 加两个对应的 GraphQL 查询函数。 |
| 56 | + |
| 57 | +## 你只需要做的事 |
| 58 | + |
| 59 | +```bash |
| 60 | +API="https://你的API地址" |
| 61 | +TOKEN="你的JWT" |
| 62 | +ROUND_ID="xxx-xxx-xxx" |
| 63 | + |
| 64 | +# 1. 发起循环赛 |
| 65 | +curl -X POST "$API/competition/start-all" \ |
| 66 | + -H "Authorization: Bearer $TOKEN" \ |
| 67 | + -H "Content-Type: application/json" \ |
| 68 | + -d "{\"round_id\": \"$ROUND_ID\"}" |
| 69 | + |
| 70 | +# 2. 轮询等全部打完 |
| 71 | +while true; do |
| 72 | + curl -X POST "$API/competition/tournament-status" \ |
| 73 | + -H "Authorization: Bearer $TOKEN" \ |
| 74 | + -H "Content-Type: application/json" \ |
| 75 | + -d "{\"round_id\": \"$ROUND_ID\"}" |
| 76 | + sleep 60 |
| 77 | +done |
| 78 | + |
| 79 | +# 3. 拿最终排名 |
| 80 | +curl -X POST "$API/competition/ranking" \ |
| 81 | + -H "Authorization: Bearer $TOKEN" \ |
| 82 | + -H "Content-Type: application/json" \ |
| 83 | + -d "{\"round_id\": \"$ROUND_ID\"}" |
| 84 | +``` |
| 85 | + |
| 86 | +这三步可以包成一个简单脚本,比如 `run_tournament.sh`,放在 `THUAI9/tournament/` 下。 |
| 87 | + |
| 88 | +## 数据流(完整链路) |
| 89 | + |
| 90 | +``` |
| 91 | +你的脚本 |
| 92 | + │ |
| 93 | + └─ POST /competition/start-all ──────────────────────────────────┐ |
| 94 | + │ │ |
| 95 | + ├─ 查询 Hasura:队伍、代码、编译状态 │ |
| 96 | + ├─ 过滤:只取编译完成的队伍 │ |
| 97 | + ├─ 从 COS 下载代码到服务器本地 │ |
| 98 | + ├─ 生成两两配对 │ |
| 99 | + ├─ 为每对创建 contest_room + contest_room_team 记录 │ |
| 100 | + └─ 推入 docker_queue │ |
| 101 | + │ |
| 102 | + docker_queue (cron, 每30秒) │ |
| 103 | + │ │ |
| 104 | + ├─ 分配端口 │ |
| 105 | + ├─ docker run server ← MODE=COMPETITION, FINISH_URL=... │ |
| 106 | + ├─ docker run clientA ← 挂载队伍A代码 │ |
| 107 | + ├─ docker run clientB ← 挂载队伍B代码 │ |
| 108 | + └─ 等待 server 退出 │ |
| 109 | + │ |
| 110 | + 游戏结束 (GameServer.OnGameEnd, Mode 1) │ |
| 111 | + │ │ |
| 112 | + ├─ GetScore() → [原始分A, 原始分B] │ |
| 113 | + └─ SendGameResult() → HTTP POST /competition/finish-one │ |
| 114 | + │ │ |
| 115 | + └─ update_room_team_score() → contest_room_team.score │ |
| 116 | + │ |
| 117 | + 你的脚本 │ |
| 118 | + │ │ |
| 119 | + └─ POST /competition/ranking │ |
| 120 | + │ │ |
| 121 | + └─ 聚合所有 room 的 score → 排名 │ |
| 122 | +``` |
| 123 | + |
| 124 | +## 改动总览 |
| 125 | + |
| 126 | +| 文件 | 改动 | 行数 | |
| 127 | +|------|------|------| |
| 128 | +| `THUAI9/logic/Server/GameServer.cs` | Mode 1 启用 SendGameResult | 1 行 | |
| 129 | +| `api/src/hasura/contest.ts` | 新增 `get_round_ranking()` + `get_round_room_status_summary()` | ~50 行 | |
| 130 | +| `api/src/routes/competition.ts` | 新增 `/ranking` + `/tournament-status` 路由 | ~60 行 | |
| 131 | +| `THUAI9/tournament/run_tournament.sh` | 调接口的脚本(可选) | ~30 行 | |
| 132 | + |
| 133 | +**不需要新建 Python 项目,不需要操作 Docker,不需要碰数据库。** |
0 commit comments