原来试运行走另一台 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
@@ -13,10 +13,21 @@ import TrialErrorNote from "./TrialErrorNote.vue"
|
||||
*/
|
||||
|
||||
const submissionStore = useSubmissionStore()
|
||||
const { customInput, customOutput, customResult, customRunning } = submissionStore.trial
|
||||
const {
|
||||
customInput,
|
||||
customOutput,
|
||||
customResult,
|
||||
customNote,
|
||||
customRuntimeError,
|
||||
customCode,
|
||||
customRunning,
|
||||
} = submissionStore.trial
|
||||
const { problem } = storeToRefs(useProblemStore())
|
||||
const codeStore = useCodeStore()
|
||||
const theme = useThemeVars()
|
||||
const route = useRoute()
|
||||
// 比赛里出错只给按结果码的那一句,不说第几行、为什么(和「运行例子」一样)
|
||||
const inContest = computed(() => !!route.params.contestID)
|
||||
|
||||
function fillSample(input: string) {
|
||||
customInput.value = input
|
||||
@@ -61,6 +72,10 @@ function fillSample(input: string) {
|
||||
:result="customResult"
|
||||
:output="customOutput"
|
||||
:language="codeStore.code.language"
|
||||
:note="customNote"
|
||||
:runtime-error="customRuntimeError"
|
||||
:code="customCode"
|
||||
:plain="inContest"
|
||||
/>
|
||||
<pre v-else class="output" :class="{ empty: !customOutput }">{{
|
||||
customResult === null ? "" : customOutput || "(什么都没有输出)"
|
||||
|
||||
@@ -51,9 +51,9 @@ const { isDesktop } = useBreakpoints()
|
||||
const theme = useThemeVars()
|
||||
|
||||
/**
|
||||
* 「运行例子」:用题目里的例子试跑(Judge0),结果在左栏「结果」页签。顶替原来题面里
|
||||
* 「运行例子」:用题目里的例子试跑(本站判题机),结果在左栏「结果」页签。顶替原来题面里
|
||||
* 每个例子旁的「测试」按钮 —— 那个在左栏、离编辑器远,只给通过 / 不通过、2 秒后复位。
|
||||
* Judge0 跑不了 SQL,流程图也没得跑;没有例子的题不给。
|
||||
* SQL 不走判题机,流程图也没得跑;没有例子的题不给。
|
||||
*/
|
||||
const submissionStore = useSubmissionStore()
|
||||
const { samplesRunning } = submissionStore.trial
|
||||
|
||||
@@ -17,7 +17,7 @@ const submissionStore = useSubmissionStore()
|
||||
const { samplesRunning } = submissionStore.trial
|
||||
const { problem } = storeToRefs(useProblemStore())
|
||||
|
||||
// 和工具栏同一个条件:Judge0 跑不了 SQL,流程图没得跑,没有例子的题不给
|
||||
// 和工具栏同一个条件:SQL 不走判题机、流程图没得跑,没有例子的题不给
|
||||
const canRunSamples = computed(
|
||||
() =>
|
||||
!!problem.value?.samples.length &&
|
||||
|
||||
@@ -80,7 +80,7 @@ const codeSegments = computed<{ value: Segment; label: string; time: string }[]>
|
||||
/** 正在画流程图:结果就是 AI 的点评,没有例子可跑 */
|
||||
const drawing = computed(() => codeStore.code.language === "Flowchart")
|
||||
|
||||
// 试跑走 Judge0,它跑不了 SQL;流程图也没得跑。这两种只留「提交结果」
|
||||
// 试跑走判题机,SQL 题不走那里;流程图也没得跑。这两种只留「提交结果」
|
||||
const canTrial = computed(() => {
|
||||
const languages = problem.value?.languages ?? []
|
||||
return !languages.includes("SQL")
|
||||
|
||||
@@ -20,6 +20,39 @@ const failedCount = computed(
|
||||
() => sampleRuns.value.filter((run) => run.result !== SubmissionStatus.accepted).length,
|
||||
)
|
||||
|
||||
/**
|
||||
* 一个例子都没跑起来:编译 / 语法没过,或者试跑服务本身没跑成(排队满了、判题机连不上)。
|
||||
* 这时不能说「N 个例子没对上」—— 程序一行都没跑,每个例子也都是同一个原因,芯片不摆
|
||||
*/
|
||||
const header = computed(() => {
|
||||
const runs = sampleRuns.value
|
||||
const first = runs[0]
|
||||
if (first && runs.every((run) => run.result === SubmissionStatus.compile_error)) {
|
||||
return {
|
||||
kind: "warning" as const,
|
||||
title:
|
||||
samplesCode.value?.language === "Python"
|
||||
? "试跑:代码有语法错误,一个例子都没跑"
|
||||
: "试跑:编译没通过,一个例子都没跑",
|
||||
chips: false,
|
||||
}
|
||||
}
|
||||
if (first?.note && runs.every((run) => run.note === first.note)) {
|
||||
// 输出太多是程序自己的问题(多半死循环),其余带 note 的都是没跑成
|
||||
const ran = first.result === SubmissionStatus.runtime_error
|
||||
return {
|
||||
kind: ran ? ("error" as const) : ("warning" as const),
|
||||
title: ran ? "试跑:程序一直在输出,停不下来" : "试跑没跑成",
|
||||
chips: false,
|
||||
}
|
||||
}
|
||||
return {
|
||||
kind: failedCount.value ? ("error" as const) : ("success" as const),
|
||||
title: failedCount.value ? `试跑:${failedCount.value} 个例子没对上` : "试跑:例子都对上了",
|
||||
chips: true,
|
||||
}
|
||||
})
|
||||
|
||||
/** 看的是哪一个例子:默认第一个没对上的 */
|
||||
const selected = ref(0)
|
||||
watch(sampleRuns, (runs) => {
|
||||
@@ -43,12 +76,8 @@ const current = computed(() => sampleRuns.value[selected.value] ?? null)
|
||||
|
||||
<n-flex v-else vertical :size="12">
|
||||
<!-- 设计稿「运行例子:例子 2 没对上(不算提交)」:标题、「不算提交」、各例子的芯片在一行 -->
|
||||
<ResultHeader
|
||||
:kind="failedCount ? 'error' : 'success'"
|
||||
:title="failedCount ? `试跑:${failedCount} 个例子没对上` : '试跑:例子都对上了'"
|
||||
sub="(不算提交)"
|
||||
>
|
||||
<template #extra>
|
||||
<ResultHeader :kind="header.kind" :title="header.title" sub="(不算提交)">
|
||||
<template v-if="header.chips" #extra>
|
||||
<div class="runs">
|
||||
<button
|
||||
v-for="run in sampleRuns"
|
||||
@@ -134,6 +163,10 @@ const current = computed(() => sampleRuns.value[selected.value] ?? null)
|
||||
:result="current.result"
|
||||
:output="current.output"
|
||||
:language="samplesCode?.language ?? ''"
|
||||
:note="current.note"
|
||||
:runtime-error="current.runtimeError"
|
||||
:code="samplesCode?.value ?? ''"
|
||||
:plain="inContest"
|
||||
/>
|
||||
</template>
|
||||
|
||||
|
||||
@@ -1,38 +1,79 @@
|
||||
<script setup lang="ts">
|
||||
import { SubmissionStatus } from "utils/constants"
|
||||
import type { StatisticInfo } from "@oj2/contract"
|
||||
import PythonErrorExplain from "./PythonErrorExplain.vue"
|
||||
import RuntimeErrorExplain from "./RuntimeErrorExplain.vue"
|
||||
|
||||
/**
|
||||
* 试跑(Judge0)没跑完时给学生看的中文说明。Judge0 回来的是英文原文(Traceback、
|
||||
* gcc 的报错),学生读不懂,原文收进折叠区。
|
||||
* 试跑没跑完时给学生看的中文说明。判题机回来的是英文原文(Traceback、gcc 的报错),
|
||||
* 学生读不懂,原文收进折叠区。Python 的语法错误是判题机上 CPython 的原文,和提交判出来的
|
||||
* 一样,直接交给 PythonErrorExplain(中文说明 + 编辑器里标出位置 + 一键换中文标点)。
|
||||
*/
|
||||
const props = defineProps<{
|
||||
result: SubmissionStatus
|
||||
output: string
|
||||
language: string
|
||||
/** 调用方给的说明(没跑成的原因、输出太多),有它就不用下面按结果码挑的那句 */
|
||||
note?: string
|
||||
/** 运行时错误的诊断(后端和提交同一个解析),有它就说清楚第几行、为什么 */
|
||||
runtimeError?: NonNullable<StatisticInfo["runtime_error"]> | null
|
||||
/** 跑的那份代码,摆出出错的那一行 */
|
||||
code?: string
|
||||
/**
|
||||
* 比赛里:不给具体到哪一行、什么原因的说明(设计文档第 8 节「运行例子只给对 / 没对上和
|
||||
* 原样输出」;提交那边比赛里也只给判题状态),只留按结果码的那一句
|
||||
*/
|
||||
plain?: boolean
|
||||
}>()
|
||||
|
||||
/** 运行时错误、而且诊断出了东西:用和提交一样的说明卡片(第几行 + 中文原因 + 编辑器标红) */
|
||||
const runtimeExplain = computed(
|
||||
() =>
|
||||
!props.note &&
|
||||
!props.plain &&
|
||||
props.result === SubmissionStatus.runtime_error &&
|
||||
!!props.runtimeError,
|
||||
)
|
||||
|
||||
const pythonSyntaxError = computed(
|
||||
() =>
|
||||
!props.note &&
|
||||
props.result === SubmissionStatus.compile_error &&
|
||||
props.language === "Python" &&
|
||||
!!props.output,
|
||||
)
|
||||
|
||||
const message = computed(() => {
|
||||
if (props.note) return props.note
|
||||
switch (props.result) {
|
||||
case SubmissionStatus.compile_error:
|
||||
return props.language === "Python"
|
||||
? "代码有语法错误,程序一行都没跑。最常见的是用了中文标点(,:()“”)。按「提交」会先检查一遍,告诉你错在哪一行,中文标点能一键换成英文。"
|
||||
? "代码有语法错误,程序一行都没跑。最常见的是用了中文标点(,:()“”)。"
|
||||
: "代码没能编译通过,写法有错误。看看是不是漏了分号、括号没配对、变量没声明。"
|
||||
case SubmissionStatus.runtime_error:
|
||||
return "程序运行到一半出错,停下来了。检查一下输入是怎么读的、下标有没有越界、除数是不是 0。"
|
||||
case SubmissionStatus.cpu_time_limit_exceeded:
|
||||
case SubmissionStatus.real_time_limit_exceeded:
|
||||
return "运行超时了:程序跑了太久还没结束。看看是不是有死循环,或者在等一个例子里没有的输入。"
|
||||
return "运行超时了:程序跑了太久还没结束。看看是不是有死循环(条件一直成立、循环变量忘了改),或者在等一个例子里没有的输入(多写了一个 input)。"
|
||||
case SubmissionStatus.memory_limit_exceeded:
|
||||
return "程序占的内存太多了。通常是列表、数组开得太大,或者在循环里不停地往里加东西、停不下来。"
|
||||
default:
|
||||
return "试跑的服务暂时连不上,稍后再试一次。"
|
||||
}
|
||||
})
|
||||
|
||||
/** 判题机的临时目录名(`/judger/run/<32 位随机串>/`)对学生没有意义,只剩文件名 */
|
||||
const rawOutput = computed(() => props.output.replace(/\/judger\/run\/[^/"]+\//g, ""))
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<n-flex vertical :size="8">
|
||||
<n-alert type="error" :show-icon="false">{{ message }}</n-alert>
|
||||
<n-collapse v-if="output">
|
||||
<PythonErrorExplain v-if="pythonSyntaxError" :err-info="output" />
|
||||
<n-flex v-else vertical :size="8">
|
||||
<RuntimeErrorExplain v-if="runtimeExplain" :info="runtimeError!" :code="code ?? ''" />
|
||||
<n-alert v-else type="error" :show-icon="false">{{ message }}</n-alert>
|
||||
<n-collapse v-if="rawOutput">
|
||||
<n-collapse-item title="原始输出(英文)" name="raw">
|
||||
<pre class="raw">{{ output }}</pre>
|
||||
<pre class="raw">{{ rawOutput }}</pre>
|
||||
</n-collapse-item>
|
||||
</n-collapse>
|
||||
</n-flex>
|
||||
|
||||
@@ -1,51 +1,96 @@
|
||||
import { createTestSubmission } from "utils/judge"
|
||||
import type { StatisticInfo, TrialRunResponse } from "@oj2/contract"
|
||||
import { errorMessage } from "utils/api"
|
||||
import { SubmissionStatus } from "utils/constants"
|
||||
import { isRunnableLanguage, trialRun } from "utils/judge"
|
||||
import type { Code } from "utils/types"
|
||||
|
||||
/**
|
||||
* 试跑:「运行例子」和「自己输入」。走 Judge0(utils/judge.ts),不经过判题机、不算提交。
|
||||
* 试跑:「运行例子」和「自己输入」。走本站判题机(utils/judge.ts → POST /trial-runs),
|
||||
* 不算提交。和提交是同一台判题机、同一套编译命令、这道题的时间内存限制和代码模板,
|
||||
* 所以例子上跑出来什么样,提交在这几个例子上就是什么样。
|
||||
*
|
||||
* 编译器版本和判题机不一样(Judge0 的 C 是 GCC 9,判题机是 gcc-14 加宽松参数),
|
||||
* 所以这里的结果偶尔会和提交不一致 —— 这是拍板过的取舍(设计文档第 3 节决定 3)。
|
||||
* 结果码就是判题机那套(SubmissionStatus),直接交给 WrongAnswerExplain 和 JUDGE_STATUS。
|
||||
* 对不对也是判题机比的(去掉末尾空白再比,和提交一样),这边不再自己比。
|
||||
*/
|
||||
|
||||
/** Judge0 的状态码(见 Judge0 的 /statuses)。同步调用(wait=true)只会拿到终态 */
|
||||
const JUDGE0_ACCEPTED = 3
|
||||
const JUDGE0_TIME_LIMIT = 5
|
||||
const JUDGE0_COMPILE_ERROR = 6
|
||||
const isJudge0RuntimeError = (status: number) => status >= 7 && status <= 12
|
||||
|
||||
/**
|
||||
* Python 的语法错误。Judge0 的 Python 没有编译这一步,SyntaxError 回来的是运行时错误
|
||||
* (status 11),得看回溯的最后一行才认得出来
|
||||
*/
|
||||
const PYTHON_SYNTAX_ERROR = /^(SyntaxError|IndentationError|TabError): /m
|
||||
|
||||
/**
|
||||
* 把 Judge0 的状态换成判题机那套码,好直接交给 WrongAnswerExplain 和 JUDGE_STATUS。
|
||||
* 跑完、只是输出对不上的,按答案错误算。Python 的语法错误按编译失败算:
|
||||
* 学生最常犯的中文冒号、中文括号,原来在这里被说成「程序运行到一半出错……下标有没有越界」
|
||||
*/
|
||||
export function trialStatus(status: number | null, passed: boolean, output: string) {
|
||||
if (status === JUDGE0_ACCEPTED) {
|
||||
return passed ? SubmissionStatus.accepted : SubmissionStatus.wrong_answer
|
||||
}
|
||||
if (status === JUDGE0_TIME_LIMIT) return SubmissionStatus.real_time_limit_exceeded
|
||||
if (status === JUDGE0_COMPILE_ERROR) return SubmissionStatus.compile_error
|
||||
if (status !== null && isJudge0RuntimeError(status)) {
|
||||
return PYTHON_SYNTAX_ERROR.test(output)
|
||||
? SubmissionStatus.compile_error
|
||||
: SubmissionStatus.runtime_error
|
||||
}
|
||||
return SubmissionStatus.system_error
|
||||
/** 试跑的是哪道题:按这道题的限制和模板跑 */
|
||||
export interface TrialTarget {
|
||||
problemId: number
|
||||
contestId: number | null
|
||||
}
|
||||
|
||||
/** 一组跑下来的结果 */
|
||||
interface TrialOutcome {
|
||||
result: SubmissionStatus
|
||||
output: string
|
||||
/** 没跑成、或者要换一种说法时给学生看的中文,有它就不用 TrialErrorNote 的默认说明 */
|
||||
note?: string
|
||||
/** 运行时错误的诊断(第几行、什么异常),和提交的同一套,交给 RuntimeErrorExplain */
|
||||
runtimeError?: NonNullable<StatisticInfo["runtime_error"]>
|
||||
}
|
||||
|
||||
const TOO_MUCH_OUTPUT =
|
||||
"程序输出太多了,一直停不下来:多半是循环没有结束的条件(条件一直成立、循环变量忘了改),在不停地打印。"
|
||||
|
||||
/**
|
||||
* 判题机比的是去掉末尾空白之后的输出(JudgeServer 的 stripped_output_md5),
|
||||
* 这里两边都去。原来题目页的「测试」按钮只 trim 了运行输出,样例输出末尾带个
|
||||
* 空格或换行,就永远显示「不通过」。
|
||||
* 把一次试跑的回包摊成每组一条。编译没过就每组都是编译失败、带同一份报错;
|
||||
* 输出太多的时候判题机回包被掐断了,分不出是哪一组,每组都挂上同一句说明。
|
||||
*/
|
||||
const sameOutput = (output: string, expected: string) => output.trimEnd() === expected.trimEnd()
|
||||
function outcomes(response: TrialRunResponse, count: number): TrialOutcome[] {
|
||||
if (response.status === "compile-error") {
|
||||
return Array.from({ length: count }, () => ({
|
||||
result: SubmissionStatus.compile_error,
|
||||
output: response.message,
|
||||
}))
|
||||
}
|
||||
if (response.status === "too-much-output") {
|
||||
return Array.from({ length: count }, () => ({
|
||||
result: SubmissionStatus.runtime_error,
|
||||
output: "",
|
||||
note: TOO_MUCH_OUTPUT,
|
||||
}))
|
||||
}
|
||||
// 跑完了(对或错)只去掉末尾空白(print 带的那个换行),判题机比对时也不看它;
|
||||
// 开头的空格是输出的一部分(打印菱形、三角形),不能动
|
||||
return response.cases.map((item) => {
|
||||
const result = item.result as SubmissionStatus
|
||||
const finished =
|
||||
result === SubmissionStatus.accepted || result === SubmissionStatus.wrong_answer
|
||||
return {
|
||||
result,
|
||||
output: finished ? item.output.trimEnd() : item.output,
|
||||
...(item.runtimeError ? { runtimeError: item.runtimeError } : {}),
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
async function runCases(
|
||||
code: Code,
|
||||
target: TrialTarget,
|
||||
cases: { input: string; output?: string }[],
|
||||
): Promise<TrialOutcome[]> {
|
||||
if (!isRunnableLanguage(code.language)) {
|
||||
return cases.map(() => ({
|
||||
result: SubmissionStatus.system_error,
|
||||
output: "",
|
||||
note: `${code.language} 不能试运行`,
|
||||
}))
|
||||
}
|
||||
try {
|
||||
const response = await trialRun({
|
||||
problemId: target.problemId,
|
||||
contestId: target.contestId ?? undefined,
|
||||
language: code.language,
|
||||
code: code.value,
|
||||
cases,
|
||||
})
|
||||
return outcomes(response, cases.length)
|
||||
} catch (error) {
|
||||
// 后端的文案是给学生看的(「上一次还没跑完」「试运行的人太多了」)
|
||||
const note = errorMessage(error, "试跑的服务暂时连不上,稍后再试一次。")
|
||||
return cases.map(() => ({ result: SubmissionStatus.system_error, output: "", note }))
|
||||
}
|
||||
}
|
||||
|
||||
export interface SampleRun {
|
||||
/** 第几个例子,0 起 */
|
||||
@@ -53,8 +98,9 @@ export interface SampleRun {
|
||||
input: string
|
||||
expected: string
|
||||
output: string
|
||||
/** 换算成判题机那套码之后的结果,见 trialStatus */
|
||||
result: SubmissionStatus
|
||||
note?: string
|
||||
runtimeError?: TrialOutcome["runtimeError"]
|
||||
}
|
||||
|
||||
export function useTrialRun() {
|
||||
@@ -68,6 +114,10 @@ export function useTrialRun() {
|
||||
const customInput = ref("")
|
||||
const customOutput = ref("")
|
||||
const customResult = ref<SubmissionStatus | null>(null)
|
||||
const customNote = ref("")
|
||||
const customRuntimeError = ref<TrialOutcome["runtimeError"] | null>(null)
|
||||
/** 跑「自己输入」时用的那份代码:出错那一行要从它里面摆出来,编辑器里可能已经改了 */
|
||||
const customCode = ref("")
|
||||
const customRunning = ref(false)
|
||||
|
||||
/**
|
||||
@@ -77,44 +127,37 @@ export function useTrialRun() {
|
||||
let samplesGeneration = 0
|
||||
let customGeneration = 0
|
||||
|
||||
async function runOne(code: Code, input: string) {
|
||||
try {
|
||||
return await createTestSubmission(code, input)
|
||||
} catch {
|
||||
return { status: null, output: "" }
|
||||
}
|
||||
}
|
||||
|
||||
async function runSamples(code: Code, samples: { input: string; output: string }[]) {
|
||||
async function runSamples(
|
||||
code: Code,
|
||||
target: TrialTarget,
|
||||
samples: { input: string; output: string }[],
|
||||
) {
|
||||
const mine = ++samplesGeneration
|
||||
samplesRunning.value = true
|
||||
// 例子一般两三个,一起发
|
||||
const outputs = await Promise.all(samples.map((sample) => runOne(code, sample.input)))
|
||||
const runs = await runCases(code, target, samples)
|
||||
if (mine !== samplesGeneration) return
|
||||
sampleRuns.value = samples.map((sample, index) => {
|
||||
const run = outputs[index]!
|
||||
const passed = run.status === JUDGE0_ACCEPTED && sameOutput(run.output, sample.output)
|
||||
return {
|
||||
index,
|
||||
input: sample.input,
|
||||
expected: sample.output,
|
||||
output: run.output,
|
||||
result: trialStatus(run.status, passed, run.output),
|
||||
}
|
||||
})
|
||||
sampleRuns.value = samples.map((sample, index) => ({
|
||||
index,
|
||||
input: sample.input,
|
||||
expected: sample.output,
|
||||
...runs[index]!,
|
||||
}))
|
||||
samplesRunAt.value = new Date().toISOString()
|
||||
samplesCode.value = code
|
||||
samplesRunning.value = false
|
||||
}
|
||||
|
||||
async function runCustom(code: Code) {
|
||||
async function runCustom(code: Code, target: TrialTarget) {
|
||||
const mine = ++customGeneration
|
||||
customRunning.value = true
|
||||
const run = await runOne(code, customInput.value)
|
||||
// 自己输入的没有标准答案,不给 output:跑完没出错就算「对」
|
||||
const [run] = await runCases(code, target, [{ input: customInput.value }])
|
||||
if (mine !== customGeneration) return
|
||||
customOutput.value = run.output
|
||||
// 自己输入的没有标准答案,跑完就算「对」,只看有没有出错
|
||||
customResult.value = trialStatus(run.status, true, run.output)
|
||||
customOutput.value = run!.output
|
||||
customResult.value = run!.result
|
||||
customNote.value = run!.note ?? ""
|
||||
customRuntimeError.value = run!.runtimeError ?? null
|
||||
customCode.value = code.value
|
||||
customRunning.value = false
|
||||
}
|
||||
|
||||
@@ -129,6 +172,9 @@ export function useTrialRun() {
|
||||
customInput.value = ""
|
||||
customOutput.value = ""
|
||||
customResult.value = null
|
||||
customNote.value = ""
|
||||
customRuntimeError.value = null
|
||||
customCode.value = ""
|
||||
customRunning.value = false
|
||||
}
|
||||
|
||||
@@ -140,6 +186,9 @@ export function useTrialRun() {
|
||||
customInput,
|
||||
customOutput,
|
||||
customResult,
|
||||
customNote,
|
||||
customRuntimeError,
|
||||
customCode,
|
||||
customRunning,
|
||||
runSamples,
|
||||
runCustom,
|
||||
|
||||
@@ -46,18 +46,24 @@ export const useSubmissionStore = defineStore("submission", () => {
|
||||
resultSeq.value++
|
||||
}
|
||||
|
||||
/** 用题目里的例子试跑(Judge0),不算提交 */
|
||||
/** 用题目里的例子试跑(本站判题机),不算提交 */
|
||||
function runSamples() {
|
||||
const problem = problemStore.problem
|
||||
if (!problem?.samples.length) return
|
||||
revealResult("samples")
|
||||
trial.runSamples({ ...codeStore.code }, problem.samples)
|
||||
trial.runSamples(
|
||||
{ ...codeStore.code },
|
||||
{ problemId: problem.id, contestId: problem.contestId },
|
||||
problem.samples,
|
||||
)
|
||||
}
|
||||
|
||||
/** 用「自己输入」框里的数据跑一次 */
|
||||
function runCustom() {
|
||||
const problem = problemStore.problem
|
||||
if (!problem) return
|
||||
revealResult("custom")
|
||||
trial.runCustom({ ...codeStore.code })
|
||||
trial.runCustom({ ...codeStore.code }, { problemId: problem.id, contestId: problem.contestId })
|
||||
}
|
||||
const isFormatting = ref(false)
|
||||
const isSubmittingRequest = ref(false)
|
||||
|
||||
Reference in new issue
Block a user