原来试运行走另一台 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>
This commit is contained in:
1 parent
8834536135
commit
eb32676de4
27 files changed
+691
-169
No files matched your search
+14
-46
@@ -1,50 +1,18 @@
|
||||
import axios from "axios"
|
||||
import { base64DecodeUtf8, base64EncodeUtf8 } from "./functions"
|
||||
import type { Code, LANGUAGE } from "./types"
|
||||
import type { RunnableLanguage, TrialRunRequest, TrialRunResponse } from "@oj2/contract"
|
||||
import api from "./api"
|
||||
import type { LANGUAGE } from "./types"
|
||||
|
||||
const http = axios.create({ baseURL: import.meta.env.PUBLIC_JUDGE0_URL })
|
||||
|
||||
// Judge0 的语言 id。Flowchart 和 SQL 不在其中 —— 前者根本不是可执行代码,
|
||||
// 后者由本站自己的 SQL 沙箱判,都走不到 Judge0。
|
||||
const JUDGE0_LANGUAGE_ID: Partial<Record<LANGUAGE, number>> = {
|
||||
C: 50,
|
||||
"C++": 54,
|
||||
Java: 62,
|
||||
Golang: 60,
|
||||
JavaScript: 63,
|
||||
Python: 71,
|
||||
/**
|
||||
* 试运行:走本站判题机(`POST /trial-runs`,见 apps/api/src/judge/trial.ts),不算提交。
|
||||
* 和提交是同一台判题机、同一套编译命令,例子上跑出来的结果和提交一个口径。
|
||||
*
|
||||
* 原来走的是另一台 Judge0(C 是 GCC 9、参数也不同),2026-09 换掉了。
|
||||
*/
|
||||
export function trialRun(payload: TrialRunRequest) {
|
||||
return api.post<TrialRunResponse>("trial-runs", payload)
|
||||
}
|
||||
|
||||
export async function createTestSubmission(code: Code, input: string) {
|
||||
const encodedCode = base64EncodeUtf8(code.value)
|
||||
const id = JUDGE0_LANGUAGE_ID[code.language]
|
||||
if (id === undefined) {
|
||||
return { status: null, output: `${code.language} 不支持在线试运行` }
|
||||
}
|
||||
let compilerOptions = ""
|
||||
if (id === 50) compilerOptions = "-lm" // 解决 GCC 的链接问题
|
||||
const payload = {
|
||||
source_code: encodedCode,
|
||||
language_id: id,
|
||||
stdin: base64EncodeUtf8(input),
|
||||
redirect_stderr_to_stdout: true,
|
||||
compiler_options: compilerOptions,
|
||||
}
|
||||
const response = await http.post("/submissions", payload, {
|
||||
params: { base64_encoded: true, wait: true },
|
||||
})
|
||||
const data = response.data
|
||||
const status: number | null = data.status?.id ?? null
|
||||
const stdout = base64DecodeUtf8(data.stdout)
|
||||
// 跑通了(3 = Accepted)就只要程序自己的输出,而且只去掉末尾的空白:
|
||||
// - C 有警告(隐式声明 sqrt、用了 gets)时 Judge0 跑通了也带回 compile_output,拼进来
|
||||
// 就成了「你的输出」的一部分,例子永远对不上;后台生成测试点时还会写进 .out
|
||||
// - 开头的空格是输出的一部分(打印菱形、三角形),原来整体 trim() 会把它削掉,
|
||||
// 对的代码被判成「只是空格不一样」
|
||||
if (status === 3) return { status, output: stdout.trimEnd() }
|
||||
// 没跑通:报错原文给人看,两段拼起来
|
||||
return {
|
||||
status,
|
||||
output: [base64DecodeUtf8(data.compile_output), stdout].join("\n").trim(),
|
||||
}
|
||||
/** 判题机跑得了的语言。Flowchart、SQL 不是可执行代码 / 不走判题机,历史语言镜像里已经没有了 */
|
||||
export function isRunnableLanguage(language: LANGUAGE): language is RunnableLanguage {
|
||||
return language === "C" || language === "C++" || language === "Python"
|
||||
}
|
||||
Reference in new issue
Block a user