Deploy / deploy (push) Canceled after 0s
原来试运行走另一台 Judge0:C 是 GCC 9、编译参数也不一样,Python 的语法错误回来的是运行错误, 没有题目的时间内存限制和代码模板,例子上的结果常和提交对不上。现在走本站判题机 (POST /trial-runs),同一套编译命令、这道题的限制和模板,对不对也由判题机比。 - 不落库、不算提交、不进判题队列:api 进程里自己排队,全站同时 TRIAL_CONCURRENCY 批 (服务器 2、机房 4),每人最多两批,排满或等超过 30 秒就请学生过一会儿再点 - 死循环不停打印时判题机回包会很大,超过 16MB 就掐断,告诉学生输出太多、停不下来 - Python 语法错误用和提交一样的说明:第几行、中文标点标红、一键换成英文 - 运行时错误和提交用同一个解析,说清楚第几行、为什么(下标越界、int() 转换失败、段错误……); 比赛里照旧只给按结果码的那一句 - 语法没过、服务没跑成时,标题不再说「N 个例子没对上」 - 后台「生成测试点」一并迁过来,编译警告不会再写进 .out;Judge0 的地址和调用全部删掉 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
70 lines
3.6 KiB
TypeScript
70 lines
3.6 KiB
TypeScript
import { z } from "zod"
|
||
|
||
/**
|
||
* 判题沙箱认得的语言。**这是全仓唯一的语言集合定义处。**
|
||
*
|
||
* 键名必须与 `apps/api/src/judge/languages.ts` 的 `languageConfigs` 一致 ——
|
||
* 沙箱的编译/运行命令按这些键查表,查不到就是 `Unsupported judge language`。
|
||
* 后端那边是 `Record<string, …>`(判题机要按名字取配置,不能窄化成联合),
|
||
* 所以这个联合是**手写**的,改 languages.ts 时两边一起改。
|
||
*
|
||
* **这里列的是历史上出现过的值,不等于现在能提交的语言。** 现在判题沙箱只认
|
||
* `C` / `C++` / `Python`(`languages.ts` 里就这三块),前端的语言复选框也只给这三个
|
||
* 加 SQL。`Java`(44 条) / `Golang`(15) / `JavaScript`(3) 是历史值:判题机没有它们的
|
||
* 编译配置、镜像里也没有工具链了,但生产库里有这些提交记录,提交列表要能渲染出来,
|
||
* 所以键必须留着。
|
||
*
|
||
* Java / JavaScript / Golang 是 2026-09 随判题镜像升级一起下掉的,理由见
|
||
* `apps/api/src/judge/languages.ts` 顶部。
|
||
*
|
||
* `Python2` / `Python3` 这两个旧值**已经不在这里了** —— 0019 迁移把库里的
|
||
* 104530 条提交、937 道题、1235 个用户的成就指标全并成了 `Python`。万一还有旧值
|
||
* 从别处冒出来(旧客户端的 localStorage、迁移之前排进队列的任务),走下面的
|
||
* `normalizeLanguage()`,别直接 parse。
|
||
*/
|
||
export const judgeLanguageSchema = z.enum(["C", "C++", "Python", "Java", "JavaScript", "Golang"])
|
||
|
||
/**
|
||
* 题目可以挂的语言 = 沙箱语言 + 两种非沙箱题型。
|
||
*
|
||
* - `SQL` 走 `judge/sql/` 那条独立链路(子进程 + sql.js),不经过沙箱;
|
||
* - `Flowchart` 走 AI 评分(flowchart/run.ts),也不经过沙箱。
|
||
*
|
||
* **两者都是真实可选、真实有历史数据的**,不是预留值:生产库 961 道题里有
|
||
* 9 道 SQL 题、124191 条提交里有 91 条 SQL。前端原来手抄的语言联合漏了 SQL,
|
||
* 于是那 91 条提交的 `language` 在类型上是 `undefined` —— 这就是两份真相
|
||
* 各自演进的代价,现在并成一份。
|
||
*/
|
||
export const problemLanguageSchema = z.enum([...judgeLanguageSchema.options, "SQL", "Flowchart"])
|
||
|
||
/**
|
||
* 判题沙箱**现在**跑得了的语言,就是 `apps/api/src/judge/languages.ts` 里那三块。
|
||
* 试运行(`POST /trial-runs`)只收这几个:历史语言交上来只会在判题机那边报系统错误。
|
||
*/
|
||
export const runnableLanguageSchema = judgeLanguageSchema.extract(["C", "C++", "Python"])
|
||
|
||
export type JudgeLanguage = z.infer<typeof judgeLanguageSchema>
|
||
export type RunnableLanguage = z.infer<typeof runnableLanguageSchema>
|
||
export type ProblemLanguage = z.infer<typeof problemLanguageSchema>
|
||
|
||
/**
|
||
* 旧语言名 → 现在的值。**库里已经没有旧值了**(0019 迁移清干净并核对过),
|
||
* 这张表挡的是数据之外的三条路:
|
||
*
|
||
* 1. 学生浏览器 localStorage 里存着上次选的 `Python3`(上线那一刻还在那儿);
|
||
* 2. 迁移之前就排进 BullMQ 的判题任务;
|
||
* 3. 万一要回滚 —— 旧版后端读 `Python` 会查不到配置,所以**回滚必须连数据一起回**,
|
||
* 别只滚代码。
|
||
*/
|
||
const LANGUAGE_ALIASES: Record<string, ProblemLanguage> = {
|
||
Python2: "Python",
|
||
Python3: "Python",
|
||
}
|
||
|
||
/** 把可能是旧值的语言名归一化;认不出来返回 null,由调用方决定怎么兜底。 */
|
||
export function normalizeLanguage(value: unknown): ProblemLanguage | null {
|
||
if (typeof value !== "string") return null
|
||
const parsed = problemLanguageSchema.safeParse(LANGUAGE_ALIASES[value] ?? value)
|
||
return parsed.success ? parsed.data : null
|
||
}
|