diff --git a/docs/平台总体设计.md b/docs/平台总体设计.md new file mode 100644 index 0000000..f96bfb5 --- /dev/null +++ b/docs/平台总体设计.md @@ -0,0 +1,174 @@ +# 平台总体设计(草案) + +> 目标:面向初学者的 OI/CSP 学习知识库 + 日常练习 + 模拟竞赛系统,并提供在线 C++ 编写/编译/调试能力。前后端分离:Next.js + C++(Drogon) + SQLite。 + +## 1. 术语与核心对象 + +- **用户(User)**:注册/登录;拥有积分、等级、学习进度。 +- **题目(Problem)**:题面、标签、难度、来源(如 CSP/NOIP/自建)。 +- **提交(Submission)**:用户对题目的一次代码提交(含编译/运行结果、耗时、内存、得分)。 +- **练习(Practice)**:非比赛场景的做题记录(可以直接通过 submissions 体现)。 +- **错题本(WrongBook)**:用户在练习/比赛中未通过的题目集合 + 错因备注。 +- **比赛(Contest)**:模拟 CSP/NOIP 的比赛;包含题目列表、开始/结束、计分规则。 +- **排名(Leaderboard)**:全站积分排行、比赛排行。 +- **知识库(KnowledgeBase)**:学习文章/笔记/专题目录;可关联题目。 + +## 2. 技术架构 + +### 2.1 前端 + +- Next.js(App Router) + TypeScript + Tailwind +- 负责:题库/题面、编辑器页面、提交列表、错题本、排行、比赛大厅、知识库阅读 + +### 2.2 后端 + +- Drogon (HTTP + JSON) +- SQLite(单文件数据库,便于部署) +- 模块分层(建议): + - `controller/`:HTTP 路由 + - `service/`:业务逻辑 + - `repo/`:DB 访问(SQL + 映射) + - `domain/`:实体与枚举 + - `judge/`:编译与判题执行器(后续) + +### 2.3 在线编译/运行(安全边界) + +- MVP:后端在临时目录中调用 `g++` 编译,并用子进程运行,使用 `ulimit`/超时 kill 做基础限制。 +- 生产建议:判题/运行必须放在容器或隔离工具(如 nsjail/isolate)中;否则存在逃逸风险。 + +## 3. 数据库设计(SQLite) + +### 3.1 表清单 + +1) `users` +- `id` INTEGER PK +- `username` TEXT UNIQUE +- `password_hash` TEXT +- `created_at` INTEGER +- `rating` INTEGER DEFAULT 0 (综合积分) + +2) `problems` +- `id` INTEGER PK +- `slug` TEXT UNIQUE +- `title` TEXT +- `statement_md` TEXT +- `difficulty` INTEGER +- `source` TEXT +- `created_at` INTEGER + +3) `problem_tags` +- `problem_id` INTEGER +- `tag` TEXT +- PK(`problem_id`,`tag`) + +4) `submissions` +- `id` INTEGER PK +- `user_id` INTEGER +- `problem_id` INTEGER +- `language` TEXT (先支持 cpp) +- `code` TEXT +- `status` TEXT (Pending/Compiling/Running/AC/WA/TLE/MLE/RE/CE) +- `score` INTEGER +- `time_ms` INTEGER +- `memory_kb` INTEGER +- `created_at` INTEGER + +5) `wrong_book` +- `user_id` INTEGER +- `problem_id` INTEGER +- `last_submission_id` INTEGER +- `note` TEXT +- `updated_at` INTEGER +- PK(`user_id`,`problem_id`) + +6) `contests` +- `id` INTEGER PK +- `title` TEXT +- `starts_at` INTEGER +- `ends_at` INTEGER +- `rule_json` TEXT (计分规则/罚时规则) + +7) `contest_problems` +- `contest_id` INTEGER +- `problem_id` INTEGER +- `idx` INTEGER +- PK(`contest_id`,`problem_id`) + +8) `contest_registrations` +- `contest_id` INTEGER +- `user_id` INTEGER +- `registered_at` INTEGER +- PK(`contest_id`,`user_id`) + +9) `kb_articles` +- `id` INTEGER PK +- `slug` TEXT UNIQUE +- `title` TEXT +- `content_md` TEXT +- `created_at` INTEGER + +10) `kb_article_links` +- `article_id` INTEGER +- `problem_id` INTEGER +- PK(`article_id`,`problem_id`) + +### 3.2 积分/排行 + +- 全站排行:按 `users.rating` 降序。 +- rating 更新策略(MVP): + - 练习 AC:+difficulty * 常数 + - 比赛:按名次发放奖励分(rule_json 可配置) + +> 该策略后续可替换为 ELO/Codeforces 风格。 + +## 4. HTTP API 设计(v1草案) + +统一前缀:`/api/v1` + +### 4.1 Auth +- `POST /auth/register` {username,password} +- `POST /auth/login` {username,password} -> {token} +- 鉴权:`Authorization: Bearer `(MVP 可用 HMAC JWT) + +### 4.2 Problems +- `GET /problems?tag=&difficulty=&q=&page=` +- `GET /problems/:id` + +### 4.3 Submissions +- `POST /problems/:id/submit` {language,code} +- `GET /submissions?user_id=&problem_id=&page=` +- `GET /submissions/:id` + +### 4.4 WrongBook +- `GET /me/wrong-book` +- `PATCH /me/wrong-book/:problemId` {note} +- `DELETE /me/wrong-book/:problemId` + +### 4.5 Contests +- `GET /contests` +- `GET /contests/:id` +- `POST /contests/:id/register` +- `GET /contests/:id/leaderboard` + +### 4.6 Leaderboard +- `GET /leaderboard/global` + +### 4.7 Knowledge Base +- `GET /kb/articles` +- `GET /kb/articles/:slug` + +## 5. 测试策略(TDD) + +- `repo` 层:用内存 SQLite(`:memory:`)+ 迁移脚本,做 CRUD 单测。 +- `service` 层:对积分、错题本更新等写业务单测。 +- `controller` 层:Drogon 自带测试/或以 HTTP 集成测试(启动测试服务器,发请求断言 JSON)。 + +## 6. 下一步落地顺序(MVP) + +1) 用户注册/登录(token) +2) 题库(只读)+ 提交记录入库 +3) 在线编译(仅编译 + 返回CE/OK),再扩展到运行 +4) 错题本(由 WA/未通过自动写入) +5) 积分与全站排行 +6) 比赛(创建/报名/排行榜) +7) 知识库文章与题目关联