judge: add multi-pass problem support (#1167)

This commit is contained in:
panda authored and GitHub committed 2026-06-06 18:28:33 +08:00
1 parent 01771a43e5
commit 809d1ac6ad
11 files changed
+166 -33

No files matched your search

@@ -79,7 +79,8 @@ const problemConfigSchema: JSONSchema7 = {
},
interactor: { $ref: '#/definitions/compilableFile' },
manager: { $ref: '#/definitions/compilableFile' },
num_processes: { type: 'number', minimum: 1, maximum: 5 },
num_processes: { type: 'integer', maximum: 5, minimum: 1 },
multi_pass: { type: 'integer', maximum: 20, minimum: 2 },
validator: { $ref: '#/definitions/compilableFile' },
user_extra_files: { type: 'array', items: { type: 'string' } },
judge_extra_files: { type: 'array', items: { type: 'string' } },
@@ -29,9 +29,9 @@ interface Props {
const configKey = [
'type', 'subType', 'target', 'score', 'time',
'memory', 'filename', 'checker_type', 'checker', 'interactor',
'manager', 'num_processes', 'validator', 'user_extra_files', 'judge_extra_files',
'detail', 'outputs', 'redirect', 'cases', 'subtasks',
'langs', 'key', 'time_limit_rate', 'memory_limit_rate',
'manager', 'num_processes', 'multi_pass', 'validator', 'user_extra_files',
'judge_extra_files', 'detail', 'outputs', 'redirect', 'cases',
'subtasks', 'langs', 'key', 'time_limit_rate', 'memory_limit_rate',
];
const subtasksKey = [
@@ -50,6 +50,7 @@ export function configYamlFormat(config: ProblemConfigFile) {
if (key === 'checker'
&& (['default', 'strict'].includes(formatConfig.checker_type) || !formatConfig.checker_type)) return;
if (key === 'interactor' && config.type !== 'interactive') return;
if (key === 'multi_pass' && (!Number.isInteger(config.multi_pass) || config.multi_pass <= 1 || config.multi_pass > 20)) return;
if (key === 'subtasks') {
formatConfig[key] = [];
config[key].forEach((subtask) => {
@@ -1,6 +1,6 @@
import { Card, Text, TextInput } from '@mantine/core';
import { Card, Switch, Text, TextInput } from '@mantine/core';
import { isEqual } from 'lodash';
import React from 'react';
import React, { useState } from 'react';
import { useDispatch, useSelector } from 'react-redux';
import { i18n } from 'vj/utils';
import FileSelectAutoComplete from '../autocomplete/components/FileSelectAutoComplete';
@@ -13,10 +13,10 @@ function FileIOConfig() {
const filename = useSelector((state: RootState) => state.config.filename);
const dispatch = useDispatch();
return (
<FormItem columns={12} label="FileIOConfig" disableLabel>
<FormItem columns={6} label="FileIOConfig" disableLabel>
<Card withBorder style={{ padding: 10, overflow: 'visible' }}>
<div className="row">
<FormItem columns={6} label="FileIO">
<FormItem columns={12} label="FileIO">
<TextInput
rightSection={<Text size="sm">.in/.out</Text>}
rightSectionWidth={100}
@@ -34,6 +34,42 @@ function FileIOConfig() {
);
}
function MultiPassConfig() {
const multiPass = useSelector((state: RootState) => state.config.multi_pass);
const dispatch = useDispatch();
const [enabled, setEnabled] = useState(multiPass > 1);
return (
<FormItem columns={6} label="Multi-pass" disableLabel>
<Card withBorder style={{ padding: 10, overflow: 'visible' }}>
<div className="row">
<FormItem columns={6} label="Multi Pass">
<Switch
styles={{ body: { display: 'flex', height: '36px', alignItems: 'center' } }}
checked={enabled}
label={i18n('Enabled')}
onChange={() => {
setEnabled(!enabled);
dispatch({ type: 'CONFIG_FORM_UPDATE', key: 'multi_pass', value: enabled ? 0 : 2 });
}}
/>
</FormItem>
{enabled && (
<FormItem columns={6} label={i18n('Max Passes')}>
<TextInput
type="number"
min={2}
max={10}
value={multiPass}
onChange={(ev) => dispatch({ type: 'CONFIG_FORM_UPDATE', key: 'multi_pass', value: +ev.currentTarget.value })}
/>
</FormItem>
)}
</div>
</Card>
</FormItem>
);
}
function ExtraFilesConfig() {
const Files = useSelector((state: RootState) => state.testdata);
const userExtraFiles = useSelector((state: RootState) => state.config.user_extra_files || [], isEqual);
@@ -92,6 +128,7 @@ export default function ProblemConfigForm() {
<div className="row problem-config-form">
<ProblemType />
{Type === 'default' && <FileIOConfig />}
{['default', 'interactive'].includes(Type) && <MultiPassConfig />}
{!['submit_answer', 'objective'].includes(Type) && (
<>
<ExtraFilesConfig />
+2 -1
View File
@@ -422,7 +422,6 @@ Forgot Password and/or Username: 忘记密码和/或用户名
Forgot password or username?: 忘记密码或者用户名?
Formula blocks: 公式区块
Freeze scoreboard with N minutes remaining: 在赛事剩余N分钟时封榜
Keep scoreboard hidden even after contest ends: 即使比赛结束后也保持成绩表隐藏
fs_upload: 上传文件
Gender Visibility: 性别可见性
Gender: 性别
@@ -523,6 +522,7 @@ Judged By: 评测机
Judging Queue: 评测队列
just now: 刚刚
Keep current expiration: 保持当前过期设置
Keep scoreboard hidden even after contest ends: 即使比赛结束后也保持成绩表隐藏
Langs Config: 语言设置
langs: 语言
Language: 语言
@@ -572,6 +572,7 @@ Mark Green: 标绿
Mark Red: 标红
Mark user as joined using admin privilege: 使用管理员权限将用户标记为已加入
Mark Yellow: 标黄
Max Passes: 最大轮次
Memory Cost: 内存占用
Memory Info: 内存信息
Memory: 内存