Code-TestX 是一个面向编程学习与算法竞赛的在线评测(OJ)平台。它提供了从题目练习、代码提交、自动评测到竞赛管理的完整闭环,旨在帮助开发者系统性地提升编程能力。
核心理念:让编程学习像游戏闯关一样有趣,让算法竞赛像实战演练一样真实。
在当今技术快速发展的时代,编程能力已成为核心竞争力之一。然而,许多学习者在提升编程技能的过程中面临以下痛点:
- × 缺乏系统性的练习平台
- × 无法获得即时的代码反馈
- × 缺少真实的竞赛环境
- × 学习进度难以追踪
Code-TestX 正是为解决这些问题而生。它不仅仅是一个刷题平台,更是一个集学习、训练、竞赛于一体的综合性编程生态系统。
| 场景 | 描述 |
|---|---|
| 个人学习 | 按难度梯度刷题,AI 助手实时答疑 |
| 高校教学 | 布置编程作业,自动评测学生代码 |
| 竞赛训练 | 模拟真实竞赛环境,多阶段晋级 |
| 企业招聘 | 技术笔试平台,支持多语言代码考核 |
| 社区运营 | 排行榜激励,消息通知,用户互动 |
-
多级难度体系:1-7 级难度梯度,从入门到竞赛全覆盖
- 1⭐ 简单:基础语法练习
- 2⭐ 中等:数据结构入门
- 3⭐ 困难:算法思维训练
- 4⭐ 专家:复杂问题求解
- 5⭐ 地狱:高难度挑战
- 6⭐ 特殊:人工评测题(如复杂模拟、开放性题目)
- 7⭐ 竞赛:仅用于竞赛阶段
-
题目元数据:标题、描述、输入/输出说明、样例、时间/内存限制
-
测试数据版本控制:支持 V2 JSON 格式,可热更新测试数据
| 语言 | 编译器/解释器 | 版本要求 |
|---|---|---|
| C | GCC | 支持 C11 标准 |
| C++ | G++ | 支持 C++17 标准 |
| Python | CPython | 3.8+ |
| Java | OpenJDK | 11+ |
| PHP | PHP | 7.4+ |
| JavaScript | Node.js | 14+ |
- 基于 Ace Editor,提供专业级编辑体验
- 语法高亮、自动补全、代码折叠
- 字号调节、主题切换(Dracula 暗色主题)
- 多文件命名(自动匹配语言后缀)
提交代码 → 编译检查 → 执行测试 → 逐点校验 → 汇总结果
↓ ↓ ↓ ↓ ↓
<1s <3s <5s <2s <1s
- 即时响应:通常在 5-10 秒内完成评测
- 逐点详情:每个测试点的执行时间、内存消耗、判定结果
- 错误诊断:编译错误、运行时错误、超时/超内存等详细信息
- 部分得分:支持子任务部分得分,精确到 0.01 分
- 自动记录:通过的题目、得分、耗时、内存
- 统计数据:总通过数、总得分、最高分、擅长难度
- 难度分布图:可视化展示各难度通过情况
- 提交历史:完整的提交记录,含代码快照
- 综合评分算法:
其中难度系数:简单=10,中等=20,困难=35,专家=50,地狱=70
总分 = 通过数 × 5 + Σ(难度系数) + 代码质量分 - 代码质量分:基于内存和时间消耗计算(越低越好)
- TOP 50 展示:含金银铜牌标识
这是 Code-TestX 最核心的模块
| 后端 | 适用平台 | 特点 |
|---|---|---|
| isolate | Linux | IOI 官方沙箱,最安全,支持 cgroup 内存控制 |
| posix | Linux/macOS | setrlimit 资源限制,无需额外安装 |
| windows | Windows | Job 对象 + tasklist 采样监控 |
引擎会自动探测并选择最优后端,优先级:isolate > posix > windows
{
"version": 2,
"defaults": {
"time_limit_ms": 2000,
"memory_limit_kb": 262144,
"output_limit_kb": 8192,
"checker": { "type": "token" }
},
"policy": {
"scoring": "partial",
"reveal": "summary",
"stop_on_first_failure": false,
"include_sample": true
},
"groups": [
{
"id": "subtask1",
"name": "小数据",
"points": 30,
"mode": "sum",
"depends_on": []
}
],
"cases": [
{
"id": "case-1",
"group": "subtask1",
"points": 10,
"in": "1 2",
"out": "3",
"visibility": "public"
}
]
}| 类型 | 描述 | 适用场景 |
|---|---|---|
exact |
逐字节精确比较 | 严格输出匹配 |
trim |
去除首尾空白后比较 | 忽略多余空行 |
token |
按空白符分词比较(默认) | 大多数题目 |
lines |
逐行比较 | 多行输出 |
unordered_lines |
行集合比较(忽略顺序) | 输出行顺序无关 |
float |
浮点数比较(绝对/相对误差) | 数值计算题 |
range |
输出值在指定范围内 | 范围校验题 |
regex |
正则表达式匹配整段输出 | 格式校验 |
fields |
按列(字段)分别校验 | 表格输出 |
script |
特殊判题脚本(Python/Node/PHP) | 复杂逻辑校验 |
自动检测并拦截以下危险模式:
| 语言 | 拦截项 |
|---|---|
| PHP | exec, shell_exec, system, eval, assert, curl_exec, fsockopen, file_put_contents, mysqli_connect |
| Python | os.system, subprocess, eval, exec, __import__, socket, open, shutil |
| JavaScript | require('child_process'), fetch, fs.unlink, eval, new Function |
| C/C++ | system, popen, fork, socket, ptrace, asm, dlopen |
| Java | Runtime.getRuntime(), ProcessBuilder, Class.forName, System.exit |
- 支持无限阶段(海选 → 初赛 → 复赛 → 决赛)
- 每阶段独立时间窗口
- 阶段状态:预备 → 报名中 → 进行中 → 已结束
- 报名时从竞赛题库(难度 7)随机分配 2-3 题
- 每位参赛者题目组合不同
- 任务进度实时追踪(JSON 存储
fptm字段)
- 完成当前阶段所有任务 → 自动晋级
- 上一阶段未通过 → 无法报名下一阶段
- 管理员可手动调整选手状态
- 报名列表(含状态:待审核/已通过/已淘汰)
- 支持选手退赛(同时清理阶段报名记录)
基于天工 AI API 构建的编程问答助手:
-
技术特性:
- Server-Sent Events (SSE) 流式响应
- 支持 Markdown 渲染(含代码高亮)
- 支持 LaTeX 数学公式(KaTeX 渲染)
- 智能推荐相关问题(suggestion)
-
配置方式: 管理员后台配置 SecretID/SecretKey
| 类型 | 描述 | 发送方式 |
|---|---|---|
| 全体公告 | 发送给所有用户 | user_for = '0' |
| 个人消息 | 发送给指定用户 | user_for = '用户ID|用户ID' |
| 系统通知 | 评测结果通知 | 自动触发 |
- CRUD 操作:创建、查看、修改、删除
- 批量导入:支持 JSON Array / JSONL / CSV / Markdown 表格四种格式
- 测试数据编辑器:可视化编辑 V2 JSON 测试数据
- 字段说明:
dv:输出范围校验(如-2>9)dvx:按元素范围校验(如[-3>9,-1>7])
- 特殊题(难度 6)代码人工审核
- 操作:通过(自动记录通过状态)或 不通过(删除记录)
- 结果通过消息中心通知用户
- 竞赛 CRUD(标题、描述、分类、时间、状态)
- 阶段管理(名称、描述、序号、时间、状态)
- 报名列表查看与删除
- 支持 Select2 多选用户
- 支持全体用户或指定用户发送
| 组件 | 技术 | 说明 |
|---|---|---|
| 语言 | PHP 7.4+ | 原生开发,无框架依赖 |
| 数据库 | MySQL 5.7+ | InnoDB/MyISAM 混合引擎 |
| 沙箱 | isolate / POSIX / Windows | 三后端自适应 |
| 安全 | 静态代码扫描 + CSRF Token | 双重防护 |
| 缓存 | 无 | 可通过文件缓存扩展 |
| 组件 | 技术 | 说明 |
|---|---|---|
| 样式 | Tailwind CSS 3.4 | 原子化 CSS 框架 |
| 交互 | 原生 JavaScript | 无框架依赖 |
| 编辑器 | Ace Editor | 专业代码编辑器 |
| 图表 | Chart.js | 统计可视化 |
| Markdown | marked.js + KaTeX | 富文本渲染 |
| UI 组件 | LayUI (弹窗/表单) | 轻量级 UI 库 |
| 图标 | Font Awesome 4.7 | 图标库 |
┌─────────────────────────────────────────────────────────────────────────────┐
│ 用户端 (Frontend) │
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
│ │ 题库浏览 │ │ 代码提交 │ │ 竞赛报名 │ │ 排行榜 │ │ AI助手 │ │
│ └──────────┘ └──────────┘ └──────────┘ └──────────┘ └──────────┘ │
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
│ │ 消息中心 │ │ 刷题记录 │ │ 个人中心 │ │ 竞赛详情 │ │
│ └──────────┘ └──────────┘ └──────────┘ └──────────┘ │
└─────────────────────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────────────────┐
│ HTTP API 层 (Endpoint) │
│ ┌─────────────────────────────────────────────────────────────────┐ │
│ │ code-runner.php │ code-runnerx.php │ code-check.php │ │
│ │ (普通评测) │ (竞赛评测) │ (人工评测申请) │ │
│ └─────────────────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────────────────┐
│ TOJ-V2 评测引擎 (Engine) │
│ ┌─────────────────────────────────────────────────────────────────┐ │
│ │ Judge.php (评测主流程) │ │
│ │ 编译 → 加载测试套件 → 调度执行 → 结果汇总 │ │
│ └─────────────────────────────────────────────────────────────────┘ │
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │
│ │ TestSuite │ │ Checker │ │ Sandbox │ │ Guard │ │
│ │ (测试加载) │ │ (答案校验) │ │ (沙箱后端) │ │ (安全检查) │ │
│ └─────────────┘ └─────────────┘ └─────────────┘ └─────────────┘ │
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │
│ │ Language │ │ RangeExpr │ │ SpecialJudge│ │
│ │ (语言支持) │ │ (范围解析) │ │ (特殊判题) │ │
│ └─────────────┘ └─────────────┘ └─────────────┘ │
└─────────────────────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────────────────┐
│ 数据层 (Repository + MySQL) │
│ ┌─────────────────────────────────────────────────────────────────┐ │
│ │ user │ coding_problems │ code_submissions │ code_person │ │
│ │ (用户) │ (题目) │ (提交记录) │ (人工评测队列) │ │
│ ├─────────────────────────────────────────────────────────────────┤ │
│ │ problem_pass_users │ competitions │ competition_stages │ │
│ │ (通过记录) │ (竞赛) │ (竞赛阶段) │ │
│ ├─────────────────────────────────────────────────────────────────┤ │
│ │ competition_registrations │ stage_registrations │ site_mail │ │
│ │ (竞赛报名) │ (阶段报名) │ (消息) │ │
│ └─────────────────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────────────────────┐
│ 代码提交请求 │
│ POST /run/code-runner.php │
└─────────────────────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────────────────┐
│ Endpoint::handleJudge() │
│ ├── 验证 Token (CSRF 防护) │
│ ├── 解析请求参数 (code, language, problem_id, user_id) │
│ ├── 代码长度限制检查 (默认 256KB) │
│ └── 语言可用性检查 │
└─────────────────────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────────────────┐
│ Repository 层 │
│ ├── findProblem() - 查询题目信息 │
│ ├── checkRateLimit() - 限流检查 (用户/IP/题目间隔) │
│ └── createSubmission() - 创建提交记录 (状态: PENDING) │
└─────────────────────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────────────────┐
│ Guard::inspect() - 静态安全检查 │
│ ├── 去除注释和字符串字面量 │
│ ├── 匹配危险函数模式 (exec/eval/system/等) │
│ └── 根据策略 (off/warn/block) 决定是否阻断 │
└─────────────────────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────────────────┐
│ Judge::run() - 评测主流程 │
│ │
│ ┌─────────────────────────────────────────────────────────────────┐ │
│ │ 1. 编译阶段 (Language::compile / syntax_check) │ │
│ │ ├── 写入源文件到工作目录 │ │
│ │ ├── 沙箱执行编译命令 (isolate/posix) │ │
│ │ └── 检查编译产物与错误信息 │ │
│ └─────────────────────────────────────────────────────────────────┘ │
│ │ │
│ ▼ │
│ ┌─────────────────────────────────────────────────────────────────┐ │
│ │ 2. 加载测试套件 (TestSuite::load) │ │
│ │ ├── 解析 V2 JSON 测试数据 │ │
│ │ ├── 构建 groups 依赖关系 │ │
│ │ ├── 分配分值 (自动归一化到 100 分) │ │
│ │ └── 加载外置测试数据文件 (.in/.out/.gz) │ │
│ └─────────────────────────────────────────────────────────────────┘ │
│ │ │
│ ▼ │
│ ┌─────────────────────────────────────────────────────────────────┐ │
│ │ 3. 测试点调度执行 (runAllCases) │ │
│ │ ├── 按分组依赖关系排序 │ │
│ │ ├── 并行/串行执行 (受 max_parallel 控制) │ │
│ │ ├── 首错即停 (stop_on_first_failure) │ │
│ │ └── TLE 重测 (recheck_tle_serially) │ │
│ └─────────────────────────────────────────────────────────────────┘ │
│ │ │
│ ▼ │
│ ┌─────────────────────────────────────────────────────────────────┐ │
│ │ 4. 单测试点执行 (runBatch) │ │
│ │ ├── 准备输入文件 (stdin) │ │
│ │ ├── 沙箱运行用户程序 │ │
│ │ ├── 监控资源 (time/memory/output) │ │
│ │ ├── 读取输出文件 (stdout/stderr) │ │
│ │ └── Checker::check() 校验答案 │ │
│ └─────────────────────────────────────────────────────────────────┘ │
│ │ │
│ ▼ │
│ ┌─────────────────────────────────────────────────────────────────┐ │
│ │ 5. 结果汇总 (report) │ │
│ │ ├── 计算总得分 (支持 partial/binary) │ │
│ │ ├── 统计通过数/总测试点 │ │
│ │ ├── 记录峰值时间/内存 │ │
│ │ └── 生成逐测试点详情 │ │
│ └─────────────────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────────────────┐
│ Repository::finishSubmission() │
│ ├── 更新 code_submissions 表 (verdict, score, passed_cases, etc.) │
│ └── 如果 AC → markPassed() 更新 problem_pass_users 和题目通过数 │
└─────────────────────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────────────────┐
│ 返回 JSON 结果给前端 │
│ { │
│ "success": true, │
│ "verdict": "AC", │
│ "score": 100.00, │
│ "results": [...] │
│ } │
└─────────────────────────────────────────────────────────────────────────────┘
| 组件 | 版本 | 说明 |
|---|---|---|
| PHP | 7.4+ | 需启用 mysqli、json、gd、mbstring 扩展 |
| MySQL | 5.7+ | 支持 InnoDB 外键约束 |
| Web Server | Nginx / Apache | 需支持 URL 重写 |
| isolate (可选) | 最新 | Linux 下推荐安装,提供最高安全级别 |
1.访问站点/install/目录(安装完一定要记得删除这个目录) 2.见下
# 1. 克隆仓库
git clone https://github.com/xhgzs1314/code-testx.git
cd code-testx
# 2. 导入数据库
mysql -u root -p < inl.sql
# 3. 配置数据库连接
cp config.example.php config.php
vim config.php
# 填写以下配置:
# $db_host = 'localhost';
# $db_user = 'your_username';
# $db_pass = 'your_password';
# $db_name = 'code_testx';
# 4. 设置目录权限
chmod -R 755 data/
chmod -R 755 tmp/
chmod -R 755 run/
# 5. (可选) 配置 isolate 沙箱
apt-get install libcap-dev
git clone https://github.com/ioi/isolate.git
cd isolate && make && make install
# 6. 配置 Web 服务器 (见下方)| 角色 | 用户名 | 密码 | 说明 |
|---|---|---|---|
| 普通用户 | user |
123456 |
可刷题、竞赛、查看排行榜 |
| 管理员 | admin |
123456 |
后台管理入口 |
| 系统账号 | u_n6Tehu |
随机生成 | 示例用户(可删除) |
server {
listen 80;
server_name code-testx.yourdomain.com;
root /var/www/code-testx;
index index.php;
# 主入口
location / {
try_files $uri $uri/ /index.php?$query_string;
}
# PHP 处理
location ~ \.php$ {
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param PATH_INFO $fastcgi_path_info;
include fastcgi_params;
}
# 静态资源缓存
location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff|woff2|ttf|eot)$ {
expires 1y;
add_header Cache-Control "public, immutable";
}
# 禁止访问敏感文件
location ~ /\. {
deny all;
}
location ~ (config\.php|inl\.sql|\.md|\.yml) {
deny all;
}
# 评测引擎入口 (必须可访问)
location /run/ {
try_files $uri $uri/ /run/code-runner.php?$query_string;
}
}<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
# 主入口
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ index.php [QSA,L]
# 禁止访问敏感文件
<FilesMatch "^(config\.php|inl\.sql|\.md|\.yml)$">
Order Deny,Allow
Deny from all
</FilesMatch>
</IfModule># 检查 isolate 是否可用
isolate --version
# 如果安装成功,引擎会自动检测并使用
# 默认 box_id 为 0,可多实例并行系统默认使用 POSIX 后端,通过 setrlimit 限制资源。无需额外配置,但安全性低于 isolate。
使用 Windows Job 对象 + tasklist 采样监控。适用于开发环境或 Windows 服务器。
-
PHP OPcache:启用 OPcache 加速
opcache.enable=1 opcache.memory_consumption=128 opcache.max_accelerated_files=4000
-
MySQL 优化:
- 为
code_submissions表添加索引(已在inl.sql中定义) - 定期清理过期的提交记录
- 为
-
并发评测:
- 调整
max_parallel参数(默认自动检测 CPU 核心数) - 确保沙箱后端支持并行(isolate 支持多 box_id)
- 调整
-
CDN 加速:
- 静态资源可使用 CDN 加速
- 修改
ast/目录下的资源引用
- 请求方式:
POST - Content-Type:
application/json - 响应格式:
application/json
| HTTP 状态码 | 含义 |
|---|---|
| 200 | 成功(含编译错误) |
| 400 | 请求参数错误 |
| 401 | Token 无效 |
| 404 | 题目不存在 |
| 413 | 代码长度超限 |
| 429 | 提交频率过快 |
| 500 | 服务器内部错误 |
| 503 | 服务不可用 |
端点:POST /run/code-runner.php
请求体:
{
"code": "#include <iostream>\nusing namespace std;\n\nint main() {\n int a, b;\n cin >> a >> b;\n cout << a + b << endl;\n return 0;\n}",
"language": "cpp",
"problem_id": 1001,
"user_id": "u_n6Tehu",
"token": "xxxxx"
}响应(成功):
{
"success": true,
"all_passed": true,
"verdict": "AC",
"verdict_label": "通过",
"score": 100.00,
"scoring": "partial",
"passed_cases": 4,
"total_cases": 4,
"max_time_ms": 600,
"max_memory_kb": 10104,
"time_limit_ms": 1000,
"memory_limit_kb": 262144,
"compile": {
"ok": true,
"message": "",
"time_ms": 150.5
},
"results": [
{
"case": 1,
"passed": true,
"accuracy": "100.00%",
"verdict": "AC",
"verdict_label": "通过",
"time_ms": 235.08,
"memory_kb": 9628,
"points": 20,
"earned": 20
}
],
"groups": [
{
"id": "sample",
"name": "样例",
"mode": "sum",
"points": 20,
"earned": 20,
"passed": 1,
"total": 1
}
],
"language": "cpp",
"judge_backend": "isolate"
}响应(编译错误):
{
"success": false,
"error": "编译错误:\nmain.cpp: In function 'int main()':\nmain.cpp:5:5: error: 'cout' was not declared in this scope",
"verdict": "CE",
"compile": {
"ok": false,
"message": "..."
}
}端点:POST /run/code-runnerx.php
请求体与普通模式相同。通过后会自动标记阶段任务完成。
响应:
{
"success": true,
"all_passed": true,
"verdict": "AC",
"stage_updated": true,
// ... 其他字段同 code-runner.php
}端点:POST /run/code-check.php
请求体:
{
"code": "def solve():\n pass",
"language": "python",
"problem_id": 6001,
"user_id": "u_n6Tehu",
"token": "xxxxx"
}响应(成功):
{
"success": true,
"message": "提交成功,请等待人工评审"
}响应(重复提交):
{
"success": false,
"error": "你已经提交过答案了",
"status": 409
}当触发限流时,返回 429 Too Many Requests:
{
"success": false,
"error": "同一题目的提交间隔需大于 5 秒",
"retry_after": 3
}┌─────────────────┐ ┌─────────────────────┐ ┌──────────────────┐
│ user │ │ coding_problems │ │ code_submissions │
├─────────────────┤ ├─────────────────────┤ ├──────────────────┤
│ id (PK) │────▶│ id (PK) │◀────│ problem_id (FK) │
│ username │ │ title │ │ user_id (FK) │
│ password │ │ description │ │ code │
│ uname │ │ difficulty │ │ language │
│ bdmail │ │ solution_count │ │ verdict │
└─────────────────┘ │ test_cases (JSON) │ │ score │
│ │ time_limit_ms │ │ passed_cases │
│ │ memory_limit_kb │ │ max_time_ms │
│ └─────────────────────┘ │ max_memory_kb │
│ │ │ created_at │
│ │ └──────────────────┘
│ │ │
▼ ▼ ▼
┌─────────────────┐ ┌─────────────────────┐ ┌──────────────────┐
│problem_pass_users│ │ competition │ │ code_person │
├─────────────────┤ ├─────────────────────┤ ├──────────────────┤
│ id (PK) │ │ id (PK) │ │ id (PK) │
│ problem_id (FK) │ │ title │ │ wtm (problem_id) │
│ user_id (FK) │ │ description │ │ userid │
│ pass_time │ │ overall_start_time │ │ codes │
│ ram │ │ overall_end_time │ │ status │
│ utime │ │ status │ │ score │
│ language │ └─────────────────────┘ └──────────────────┘
│ best_score │ │
└─────────────────┘ │
▼
┌─────────────────────┐
│ competition_stages │
├─────────────────────┤
│ id (PK) │
│ competition_id (FK) │
│ name │
│ order_num │
│ start_time │
│ end_time │
│ status │
└─────────────────────┘
│
▼
┌─────────────────────┐
│stage_registrations │
├─────────────────────┤
│ id (PK) │
│ stage_id (FK) │
│ user_id │
│ status │
│ fptm (JSON) │ ← 任务分配数据
└─────────────────────┘
| 表名 | 引擎 | 说明 |
|---|---|---|
user |
InnoDB | 用户表,存储账号密码和基本信息 |
coding_problems |
InnoDB | 题目主表,含 V2 JSON 测试数据 |
code_submissions |
InnoDB | 提交记录表,含评测结果详情 |
code_person |
MyISAM | 人工评测队列(特殊题) |
problem_pass_users |
InnoDB | 通过记录表,用于排行榜计算 |
competitions |
MyISAM | 竞赛主表 |
competition_stages |
MyISAM | 竞赛阶段表 |
competition_registrations |
MyISAM | 竞赛报名表 |
stage_registrations |
MyISAM | 阶段报名表,含 fptm 任务分配 |
site_mail |
MyISAM | 消息表(公告和个人消息) |
code-testx/
├── engine/ # TOJ-V2 评测引擎核心
│ ├── bootstrap.php # 引擎装载器
│ ├── Config.php # 全局配置管理
│ ├── Verdict.php # 评测结果常量 + 异常类
│ ├── Http.php # HTTP 请求/响应封装
│ ├── Support.php # 基础设施 (平台探测/文件操作)
│ ├── Sandbox.php # 沙箱抽象层
│ ├── SandboxIsolate.php # isolate 沙箱后端
│ ├── SandboxPosix.php # POSIX setrlimit 后端
│ ├── SandboxWindows.php # Windows Job 后端
│ ├── Language.php # 语言支持注册 (6 种语言)
│ ├── Guard.php # 静态代码安全检查
│ ├── RangeExpr.php # 数值范围表达式解析
│ ├── Checker.php # 答案校验器 (10+ 种)
│ ├── SpecialJudge.php # 特殊判题脚本执行器
│ ├── TestSuite.php # V2 测试数据加载器
│ ├── Judge.php # 评测主流程
│ ├── Repository.php # 数据访问层
│ └── Endpoint.php # HTTP 入口控制器
│
├── run/ # 评测 HTTP 入口
│ ├── code-runner.php # 普通评测入口 (practice)
│ ├── code-runnerx.php # 竞赛评测入口 (contest)
│ └── code-check.php # 人工评测申请入口 (manual)
│
├── users/ # 用户模块
│ └── login/ # 登录/注册页面
│ ├── index.php # 登录/注册页面 (含验证码)
│ ├── log.php # 登录逻辑
│ └── reg.php # 注册逻辑
│
├── cofd/ # 公共依赖库
│ ├── common.php # 数据库连接
│ ├── token.php # CSRF Token 生成/验证
│ └── locokie.php # Cookie 辅助函数
│
├── ast/ # 前端静态资源
│ ├── 3.4.16.js # Tailwind CSS CDN
│ ├── font-awesome/ # Font Awesome 4.7 图标库
│ ├── layui/ # LayUI 组件库
│ ├── css/ # 自定义样式
│ ├── js/ # 自定义 JS
│ └── photo/ # 图片资源
│
├── package/ # NPM 前端库 (本地)
│ ├── ace-builds/ # Ace 编辑器
│ ├── chart.umd.min.js # Chart.js 图表
│ ├── marked.min.js # Markdown 渲染
│ ├── katex.min.js + .css # LaTeX 数学渲染
│ ├── auto-render.min.js # KaTeX 自动渲染
│ ├── mermaid.min.js # Mermaid 流程图
│ ├── github-markdown.min.css # GitHub 风格 Markdown
│ ├── sweetalert2/ # 弹窗组件
│ └── select2.min.js + .css # 多选下拉框
│
├── admin/ # 后台管理模块
│ ├── set.php # 后台布局 + 侧边栏
│ ├── index.php # 后台首页 (引擎文档展示)
│ ├── login.php # 后台登录页
│ ├── logout.php # 后台登出
│ ├── keylist.php # 题库列表 (查看/删除)
│ ├── keyupdate.php # 单题修改
│ ├── keypush.php # 新建题目 (表单)
│ ├── keypush2.php # 批量导入题目 (JSON/JSONL/CSV/Markdown)
│ ├── keyplus.php # 人工评测管理
│ ├── compelist.php # 竞赛列表管理
│ ├── callgglist2.php # 阶段管理
│ ├── callgglist3.php # 阶段报名列表
│ ├── callgglist4.php # 竞赛报名列表
│ ├── dl.php # 公告管理
│ ├── robot_tiangong.php # AI 密钥配置
│ ├── cdxl.php # 个人信息修改
│ ├── gapwp.php # 密码修改
│ ├── shop.php # 商品管理 (预留)
│ ├── ssearch.php # 用户搜索 API (Select2)
│ ├── call/ # 后台处理脚本
│ │ ├── calldlgg.php # 添加公告
│ │ ├── calldlgg2.php # 添加竞赛
│ │ ├── calldlgg3.php # 添加阶段
│ │ ├── callggdell.php # 删除公告
│ │ ├── callggdell2.php # 删除竞赛
│ │ ├── callggdell3.php # 删除阶段
│ │ ├── callggdell4.php # 删除阶段报名
│ │ ├── callggdell5.php # 删除竞赛报名
│ │ ├── callsh.php # 人工评测审核 (通过/不通过)
│ │ ├── callpost.php # 修改公告表单
│ │ ├── callpostdel.php # 删除题目
│ │ ├── callxggglist.php # 修改公告
│ │ ├── callxggglist2.php # 修改竞赛
│ │ ├── callxggglist3.php # 修改阶段
│ │ ├── callyui.php # 更新公告
│ │ ├── callyui2.php # 更新竞赛
│ │ ├── callyui3.php # 更新阶段
│ │ ├── callpass.php # 修改密码处理
│ │ ├── callbo.php # 修改个人信息处理
│ │ ├── calllog.php # 后台登录处理
│ │ ├── newtm.php # 新建题目处理 (API)
│ │ └── keyupdate_do.php # 修改题目处理
│ └── xuplwzxy/ # 个人信息存储
│ └── xydoc.php # 昵称/QQ/签名数据
│
├── competition/ # 竞赛模块 (子路由)
│ ├── prepare/ # 竞赛报名处理
│ │ └── index.php # 报名逻辑 (含阶段晋级检查)
│ ├── oning/ # 进入竞赛
│ │ └── index.php # 展示任务列表 + 进度
│ └── quit/ # 退赛处理
│ └── index.php # 退赛逻辑
│
├── index.php # 用户端主页 (框架页 + 侧边栏)
├── dashboard.php # 题库列表 (含筛选/分页/搜索)
├── codereads.php # 题目详情 + 代码提交 (Ace 编辑器)
├── competition.php # 竞赛报名列表
├── competition_mine.php # 我的竞赛详情
├── haspassed.php # 刷题记录 (含统计图表)
├── submission_history.php # 单题提交历史
├── submission_detail.php # 单次提交详情
├── notice.php # 消息中心 (全体/个人)
├── phb.php # 排行榜
├── airobot.php # AI 智能助手 (SSE 流式)
├── set.php # 登录拦截 (检查 Cookie)
├── inl.sql # 完整数据库结构
├── config.example.php # 数据库配置示例
├── engine.md # 评测引擎文档
└── README.md # 项目说明
A: 检查系统是否安装了对应语言的解释器/编译器:
# Python
python3 --version
# C++
g++ --version
# Java
javac -version
java -version
# Node.js
node --version
# PHP
php --versionA:
# 安装 isolate
git clone https://github.com/ioi/isolate.git
cd isolate
make
sudo make install
# 验证
isolate --version
# 引擎会自动检测并使用A: 检查以下几点:
- 数据库连接是否正常
run/目录是否有执行权限- PHP 错误日志是否有报错
- 检查
code_submissions表是否有新记录
A: 使用后台的 keypush2.php 页面,支持四种格式:
- JSON Array:
[{...}, {...}] - JSONL:每行一个 JSON 对象
- CSV:第一行为表头
- Markdown 表格:标准 Markdown 表格格式
A:
- 登录后台 (
/admin/login.php) - 进入「智能助手-天工AI」
- 填写 SecretID 和 SecretKey
- 保存配置
A: 特殊题需要人工评测:
- 用户在题目页点击「申请人工评测」
- 代码进入
code_person队列 - 管理员在后台
keyplus.php查看 - 点击「通过」或「不通过」
- 结果通过消息中心通知用户
A: 编辑 engine/judge.config.php(如不存在则创建):
<?php
return [
'rate_limit' => [
'enabled' => true,
'per_user_window_s' => 60, // 60 秒窗口
'per_user_max' => 8, // 最多 8 次
'per_problem_min_gap_s' => 5, // 同题间隔 5 秒
'per_ip_window_s' => 60,
'per_ip_max' => 30,
],
];A: 必需的扩展:
mysqli- 数据库连接json- JSON 解析gd- 验证码生成mbstring- 多字节字符串处理
请使用 GitHub Issues 报告 Bug,并包含:
- 环境信息:PHP 版本、MySQL 版本、操作系统
- 复现步骤:详细的操作步骤
- 期望行为:你期望发生什么
- 实际行为:实际发生了什么
- 日志/截图:相关的错误日志或截图
如果你有好的想法,欢迎提交 Issue 或 Pull Request。建议包含:
- 功能描述:这个功能是做什么的
- 使用场景:在什么情况下会用到
- 实现思路:你建议如何实现
本项目采用 MIT License 开源许可证。
| 项目 |
|---|
| IOI isolate |
| Ace Editor |
| Tailwind CSS |
| Chart.js |
| marked.js |
| KaTeX |
| LayUI |
| Font Awesome |