# Algorithm Competition Assistant **Sublime Text 上更「能打」的算法竞赛测评插件** —— 一个测试点卡片 + 彩色 verdict + 逐行 diff 详情 + 真实内存/超时判定的完整闭环。 > **基于什么开发**:本插件是 **[FastOlympicCoding](https://github.com/Jatana/FastOlympicCoding)**(Jatana)的深度二次开发版本, > 参考 VSCode 的 **[cph-ng](https://github.com/langningchen/cph-ng)** 重做了判题结果显示(彩色 verdict、详情面板、逐行 diff), > 并借鉴 **[FastOlympicCodingHook](https://github.com/DrSchwad/FastOlympicCodingHook)** 集成了 [Competitive Companion](https://github.com/jmerle/competitive-companion) 浏览器插件支持。 --- ## English **Algorithm Competition Assistant** is a competitive-programming test runner for **Sublime Text 4** (build 4095+). It is a rework of [FastOlympicCoding](https://github.com/Jatana/FastOlympicCoding) (Jatana), with the verdict display rebuilt after VSCode's [cph-ng](https://github.com/langningchen/cph-ng), and [Competitive Companion](https://github.com/jmerle/competitive-companion) support inspired by [FastOlympicCodingHook](https://github.com/DrSchwad/FastOlympicCodingHook). - Run the samples of the file you are editing and get a per-test verdict (AC / WA / TLE / MLE / RE / PE / CE) as coloured cards in a panel next to the code. - **Real memory limit**: the peak memory of the child process is sampled per platform (Windows `GetProcessMemoryInfo`, Linux `/proc//status`, macOS `libproc`), so MLE is an actual verdict instead of an unused setting. A watchdog kills the whole process tree on a timeout. - Detail tab with input / expected / actual / stderr and a line-by-line diff; configurable float tolerance and output size cap; compile cache; multi-file builds (`extra_sources`, `include_dirs`). - Import test data from `.in`/`.out` pairs, a folder, the clipboard, or the **Competitive Companion** browser extension (built-in persistent listener, port 12345 by default). - **Stress test** against a generator and a reference solution; a counterexample is saved as a test. - Chinese / English UI (`language` setting). **Getting started**: open a source file, then use `Ctrl+Shift+P` → `cph` (every command is in the command palette) or the `View → Algorithm Competition Assistant` menu. The default `run_settings` cover C++ (`g++`, `-std=c++17 -O2`), Python, Java, C, Rust, Go, Pascal and JavaScript (Node.js) — edit them under `Preferences → Package Settings → Algorithm Competition Assistant → Settings` to match your toolchain (the compiler has to be on `PATH`; the *Check environment (doctor)* command reports anything that is missing). `-O2` matters: without optimisation a local run is orders of magnitude slower than the judge, so a correct program gets reported as TLE. **Key bindings**: the bindings live in this package's own `Default ().sublime-keymap`, so they load with the package and are released again when you disable or uninstall it — nothing is ever written into your personal keymap. Set `"enable_keybindings": false` to release the keys without editing any keymap. `Example (Windows|Linux|OSX).sublime-keymap` holds the same entries as a copy-paste reference if you want to change one. **Context menu**: entries only appear for the file types listed in `run_settings`; set `"context_menu": false` to hide them completely. Nothing is added to other menus. --- ## 相比原版 FastOlympicCoding,多了什么 | 能力 | FastOlympicCoding | Algorithm Competition Assistant | | --- | --- | --- | | 彩色 verdict 徽章(AC/WA/TLE/MLE/RE/PE/CE…) | ❌ 只有纯文本 | ✅ 类 cph-ng 的徽章样式 | | **真实内存判定(MLE)** | ❌ 内存是死配置 | ✅ 跨平台采样进程峰值内存,超限真判 MLE | | **超时硬杀(TLE)** | ❌ 死循环杀不掉 | ✅ 看门狗到点终止整个进程树 | | **运行错误定位(RE 位置)** | ❌ | ✅ 从程序输出解析 `文件:行号`(Python 回溯 / Java 栈 / `-fsanitize` 诊断) | | 详情视图 + **逐行 diff** | ❌ | ✅ 独立标签页,可选中可复制 | | **编译缓存** | ❌ 每次都重编 | ✅ 源文件/命令未变则跳过编译 | | 只重跑失败 / 跑完全部 / 强制重编 | ❌ | ✅ 三个命令 + 快捷键 | | **浮点容差**(`float_tolerance`) | ❌ | ✅ 浮点题不再因 `0.1+0.2 != 0.3` 误判 | | 输出体积上限(防卡死) | ❌ | ✅ `max_output_bytes` | | 多文件编译(`extra_sources` / `include_dirs`) | ❌ | ✅ | | 环境自检 doctor | ❌ | ✅ 一条命令排查 + 可粘贴的 Markdown 报告 | | 纯键盘操作(选测试点→操作) | ❌ | ✅ `Ctrl+Alt+M` | | 对拍反例自动入库 | ❌ | ✅ | | Competitive Companion 持久监听 | ⚠️ 需 Hook | ✅ 内建、可反复点击 | | 中英文双语界面 | ❌ | ✅ | | 测试面板自适应宽度 | ❌ | ✅ 卡片放不下时自动加宽 | 工程上还有:**Python 3.3 兼容**(Sublime 插件宿主)、四平台 CI(Linux 3.8/3.12 + Windows + macOS)、**80+ 项回归测试**。 --- ## 主要功能 ### 1. 类 cph-ng 的测评结果显示 每个测试点显示: - **彩色 verdict 徽章**:`AC`(绿)、`WA`(红)、`TLE`(黄)、`MLE`(紫)、`RE`(蓝)、`PE`(粉)、`CE`(黄)等 - **运行时间**:毫秒级,超过 5 秒自动换算成秒 - **内存占用**:MB / GB(**跨平台真实采样进程峰值内存**:Windows 用 `GetProcessMemoryInfo`、Linux 读 `/proc//status` 的 `VmHWM`、macOS 用 `libproc.proc_pid_rusage`),超限会真的判 `MLE` - **超时硬杀**:超过时间限制会被自动终止并判 `TLE`,不会出现死循环杀不掉;手动停止的测试显示 `SK` - **运行错误定位**:程序崩溃(`RE`)时,若输出里有位置信息(Python 回溯、Java 栈、`-fsanitize` 诊断),卡片详情会显示 `运行错误 (RE) 位置: main.py:12`,状态栏同时提示 - **三个按钮**:`编辑`、`运行`、`详情` > **C++ 想拿到 RE 行号?** 普通的段错误不带行号。把编译命令加上 > `-fsanitize=address,undefined -g -fno-omit-frame-pointer`(在 `run_settings` 里自定义 > `compile_cmd`),崩溃时就会输出 `main.cpp:12:5: runtime error: ...`,插件会自动解析出行号。 ### 2. 详情视图(detail)+ 逐行 diff 点击 `详情` 打开一个真实的编辑器标签页(`xxx - test N detail`),文字**可选中、可复制**: - **预期输出** / **实际输出** / **错误输出 (stderr)** - **Diff**:预期与实际**逐行对比**(忽略行末空格与末尾换行),只列出有差异的行 - 顶部显示 verdict + 运行时间 + 内存占用 运行结束后再次点击 `详情` 会自动刷新。 ### 3. 正确/错误答案快捷标记 运行结束后输出下方出现 `accept` / `decline`:`accept` 把当前输出记为正确答案,`decline` 记为错误答案。 ### 4. 集成 Competitive Companion 浏览器插件 1. 在 Sublime Text 中打开要做题的代码文件 2. 右键选择 `Algorithm Competition Assistant: Listen to Competitive Companion` 3. 浏览器打开题目页,点 Competitive Companion 扩展的绿色 `+` 4. 样例与时间/内存限制自动发送到 Sublime Text、存进测试文件并自动运行 监听器是**持久**的(cph-ng 风格):启动一次后可**反复点击**发送不同题目,不会端口冲突或报 "Can't restore session";在另一个文件上再次执行该命令 = 切换监听目标;`Stop Competitive Companion listener` 随时停止。 **注意**:需要在 Competitive Companion 扩展的端口列表里加入 `12345`(可用设置项 `companion_port` 修改)。 ### 5. 国际化 (i18n) 默认中文,可切换: - **菜单**:`Tools` → `Algorithm Competition Assistant` → `Switch language (中/EN)` - **命令面板**:`Algorithm Competition Assistant: Switch to English` / `切换为中文` - **右键菜单**:`Switch language (中/EN)` - **设置**:`"language": "en"` 或 `"zh"` ### 6. 运行模式与效率 - **编译缓存**:源文件(含多文件依赖)与编译命令没变时跳过编译;需要时 `Ctrl+Alt+Shift+R` 强制重编 - **只重跑失败 / 跑完全部**:`Ctrl+Alt+R` 只重跑没 AC 的点,`Ctrl+Alt+Shift+B` 跑完全部(默认第一个失败即停,可用 `stop_on_first_failure` 改) - **浮点容差**:设置 `float_tolerance`(如 `1e-6`),数字型输出按相对/绝对误差比较 - **输出上限**:`max_output_bytes`(默认 8MB)防止疯狂输出卡死编辑器,超出部分会被截断并给出提示 - **多文件编译**:`run_settings` 里用 `extra_sources`(glob)与 `include_dirs`,编译命令中用 `{extra_sources}` / `{include_dirs}` 占位符 - **面板汇总行**:底部显示 `4/5 通过 · 首个失败 test 3 · 总用时 1.24s` - **自定义判定器(SPJ)**:`run_settings` 里填 `checker` 即可用 testlib 风格的 checker(三个文件参数 + 退出码判定),多解题不再只能靠 token 比较 - **交互题**:填 `interactor` 即按 testlib 约定接线,选手程序与 interactor 双向对话,退出码即判决 - **Subtask 分组**:`subtasks` 里分组,组内全 AC 才拿分,汇总行显示部分分 - **Benchmark / 机器校准 / 练习统计 / 比赛计时 / 抓题与题面预览 / 保存自动运行**:命令面板里搜 `Algorithm Competition Assistant:` 都能找到 - **错误位置可点击**:RE 的 `文件:行:号` 和编译器的每条诊断都会渲染成链接,点一下直接跳到源码那一行(已经打开的标签会被复用,不会新开一个) - **Debug / Release 一键切换**(`Ctrl+Alt+G`):Debug 去掉优化并加 `-g -fsanitize=address,undefined`,崩溃时能给出精确行号;Release 保证 `-O2` 并去掉 sanitizer,计时与评测机可比。按文件记忆,**不写你的设置文件**;当前模式显示在运行面板状态栏 - **并行运行**(`Ctrl+Alt+Shift+P`):每个测试点一个独立进程、`parallel_workers`(默认 4)个 worker 同时跑。串行时 5 个点里有 2 个 TLE 要等 2×时限,并行约 1/4 - **环境自检**:`Ctrl+Alt+D` 检查编译器是否在 PATH、端口占用、测试路径可写、资源可加载,并给出一段可粘贴到 issue 的 Markdown 报告 - **纯键盘流**:`Ctrl+Alt+M` 选测试点 → 运行 / 详情 / 编辑 / 接受 / 拒绝 / 删除 - **对拍反例入库**:对拍发现反例自动保存为正式测试点(可用 `stress_save_counterexample` 关闭) - **统一合并策略**:导入文件 / 剪贴板 / 浏览器 / 对拍反例四条路径共用「按输入去重、答案只补不覆盖」,重发样例不会顶掉你手动标记的答案 ### 7. 测试面板自适应宽度 右侧运行面板默认只占窗口 32%;卡片按钮放不下时,插件会在每次刷新后自动加宽,直到最宽的卡片能一行放下: - **只在需要时加宽**,从不自动收窄 - **上限为半个窗口**(可配置) ```json { "auto_fit_panel_width": true, "max_panel_width_ratio": 0.5 } ``` ## 安装 1. 克隆或下载本仓库 2. 把 `Algorithm Competition Assistant` 文件夹复制到 Sublime Text 的 `Packages` 目录 3. 重启 Sublime Text ## 使用方法 1. 打开 C++ 源文件 2. 按 `Ctrl+Alt+B`(Mac:`Cmd+Alt+B`)启动测评 3. 右侧打开测试运行窗口,可输入/编辑测试数据 4. 测评结束后每个测试点显示 verdict 徽章 5. 点 `详情` 看带逐行 diff 的详情页;点 `编辑` 打开输入(`test N -edit`)与标准答案(`test N -answer`)两个标签页,在答案页填好预期输出后 `save` 即可自动重新评判 > **关于默认运行命令**:默认 `run_cmd` 用正斜杠路径,Windows / Linux / macOS 通用。想换成自己的写法,把 `run_settings` 复制到 User 设置里覆盖即可。 ## 已知限制 - **macOS 内存占用**是单进程实时采样(`libproc.proc_pid_rusage`)的峰值,不是内核严格意义上的峰值 RSS,可能比 Activity Monitor 略低;已不再使用 `RUSAGE_CHILDREN`(所有子进程累计峰值)那种错误口径。 - **裸段错误(C++)不带行号**:RE 位置只在程序输出包含位置信息时才有(Python 回溯 / Java 栈 / `-fsanitize` 诊断);纯 C++ 段错误需要自行加 `-fsanitize` 编译。 - **`sync_output`(逐字符同步输出)默认关闭**:开启后一个字符刷新一次视图,只适合交互式程序。 - **stderr(`cerr` 调试输出)只显示在详情视图里**,不再挂在卡片上(卡片会变得又挤又长)。 - **"还没粘贴样例"的时间不计时**:新建测试点后如果输入还是空的,程序虽然已经启动, 但运行计时与 TLE 看门狗都在等你输入——从你粘贴/输入的第一个字符、或程序第一次输出开始才算。 因此不会出现"样本还没粘完就已经 TLE"。 - **RE 优先于 TLE**:程序崩溃时看判定退出码(访问越界 / 除零 / 栈溢出 / `abort`)和错误输出里的 崩溃特征(`terminate called after throwing`、`Traceback`、`AddressSanitizer` …), 即使恰好超时被杀也判 RE;普通的 `cerr` 调试输出不会被误判。 - **空样例不会保存**:没有任何输入也没有答案的空白测试点只存在于当前面板(它是用来接收 你粘贴样例的占位),不会写进测试文件。 - **`PE`(Presentation Error)**:只有「token 完全相同但空白/换行不同」才算 PE,默认与 WA 分别显示;若你的 OJ 把 PE 也算通过,把 `regard_pe_as_ac` 设为 `true`。 - 输出超过 `max_output_bytes`(默认 8MB)时超出部分会被丢弃,并插入一行截断提示。 - **抓题没有页面体积上限**:`core/cph_fetch.py` 直接 `response.read()` 把整页一次性读进 内存,不按字节截断——题库整页嵌入、大图多的站点会照单全收,内存占用只跟页面大小成正比。 唯一的闸门是 `fetch(url, timeout=25)` 的 **25 秒**:超时按抓取失败报 `抓取失败:…`(英文环境 是 `fetch failed: ...`),不会给你半页题面。题面本身不做任何长度裁剪,样例、标题、题面正文 有多长就写多长(该模块里唯一的定长函数 `first_lines(text, limit=200)` 目前**没有任何调用方**, 是留给以后做摘要的死代码,所以状态栏与消息里也没有 200 字的截断)。 题面转 Markdown 时会丢掉 `