judge: use case.score & normalizeSubtask API

This commit is contained in:
undefined authored and panda committed 2022-05-10 01:55:34 +08:00
1 parent 310189bc4d
commit 539a1c44ce
14 files changed
+231 -201

No files matched your search

@@ -38,14 +38,14 @@ const subtasksKey = [
const casesKey = ['time', 'memory', 'input', 'output'];
function configYamlFormat(config: ProblemConfigFile) {
export function configYamlFormat(config: ProblemConfigFile) {
const formatConfig: ProblemConfigFile = {};
configKey.forEach((key) => {
if (config[key] !== undefined) {
if (key === 'subType' && ['single', 'multi'].includes(config[key]) && config.type !== 'submit_answer') return;
if (key === 'checker_type' && config.type !== 'default') return;
if (key === 'checker'
&& (['default', 'strict'].includes(formatConfig.checker_type) || formatConfig.checker_type === undefined)) return;
&& (['default', 'strict'].includes(formatConfig.checker_type) || !formatConfig.checker_type)) return;
if (key === 'interactor' && config.type !== 'interactive') return;
if (key === 'subtasks') {
formatConfig[key] = [];
@@ -62,7 +62,7 @@ function configYamlFormat(config: ProblemConfigFile) {
formatConfig[key] = [];
config[key].forEach((caseItem) => {
const formatCase: TestCaseConfig = {
time: 1000, memory: 256, input: '', output: '',
time: '1000ms', memory: '256MB', input: '', output: '',
};
casesKey.forEach((caseKey) => {
if (caseItem[caseKey] !== undefined) formatCase[caseKey] = caseItem[caseKey];
@@ -5,7 +5,7 @@ import { useSelector, useDispatch } from 'react-redux';
import { SubtaskConfig } from 'hydrooj/src/interface';
import { parseTimeMS, parseMemoryMB } from '@hydrooj/utils/lib/common';
import CustomSelectAutoComplete from '../autocomplete/components/CustomSelectAutoComplete';
import { FormItem, ManagedInput } from './BasicForm';
import { FormItem } from './BasicForm';
import { RootState } from './reducer';
import { CasesTable } from './TestCasesTable';
@@ -71,7 +71,7 @@ export function SubtasksTable({ index }) {
{['id', 'score'].map((key) => (
<td key={key}>
<input
value={subtask[key] || ''}
value={subtask[key] ?? ''}
onChange={dispatcher(key)}
type="number"
className="textbox"
@@ -80,7 +80,7 @@ export function SubtasksTable({ index }) {
))}
<td>
<select
value={subtask.type || ''}
value={subtask.type ?? 'min'}
onChange={dispatcher('type')}
className="select"
>
@@ -116,20 +116,48 @@ export function SubtasksTable({ index }) {
);
}
function GlobalTaskConfig() {
const time = useSelector((state: RootState) => state.config.time);
const memory = useSelector((state: RootState) => state.config.memory);
const dispatch = useDispatch();
const dispatcher = (key: string, suffix = '') => (ev: React.ChangeEvent<HTMLInputElement | HTMLSelectElement> | number) => {
let value = typeof ev !== 'object' ? ev : ev.currentTarget?.value;
if (value === 0) value = '';
if (value && suffix) value += suffix;
dispatch({ type: 'CONFIG_FORM_UPDATE', key, value });
};
return (
<>
<FormItem columns={6} label="Time">
<NumericInput
rightElement={<Tag minimal>ms</Tag>}
value={time ? parseTimeMS(time).toString() : ''}
placeholder={parseTimeMS('1000ms').toString()}
onValueChange={dispatcher('time', 'ms')}
buttonPosition="none"
fill
/>
</FormItem>
<FormItem columns={6} label="Memory">
<NumericInput
rightElement={<Tag minimal>MB</Tag>}
value={memory ? parseMemoryMB(memory).toString() : ''}
placeholder={parseMemoryMB('256m').toString()}
onValueChange={dispatcher('memory', 'MB')}
buttonPosition="none"
fill
/>
</FormItem>
</>
);
}
export function TaskConfig() {
const len = useSelector((state: RootState) => state.config.subtasks?.length);
return (
<FormItem columns={12} label="Task Settings">
<div className="row">
<FormItem columns={4} label="Time">
<ManagedInput placeholder="Time" formKey="time" />
</FormItem>
<FormItem columns={4} label="Memory">
<ManagedInput placeholder="Memory" formKey="memory" />
</FormItem>
<FormItem columns={4} label="Score">
<ManagedInput placeholder="Score" formKey="score" />
</FormItem>
<GlobalTaskConfig />
<FormItem columns={12} label="TestCases" disableLabel>
{len && [...Array(len).keys()].map((i) => <SubtasksTable index={i} key={i} />)}
</FormItem>
@@ -1,6 +1,7 @@
import yaml from 'js-yaml';
import type { ProblemConfigFile } from 'hydrooj/src/interface';
import { cloneDeep } from 'lodash';
import { parseMemoryMB, parseTimeMS } from '@hydrooj/utils/lib/common';
type State = ProblemConfigFile & { __loaded: boolean };
@@ -25,23 +26,20 @@ export default function reducer(state = { type: 'default', __loaded: false } as
}
case 'CONFIG_AUTOCASES_UPDATE': {
const next = { ...state };
const autocases = action.value;
if (autocases.subtasks.length === 0) next.subtasks = [];
const { subtasks } = action;
for (const subtask of subtasks) {
if (subtask.time === parseTimeMS(state.time || '1s')) delete subtask.time;
if (subtask.memory === parseMemoryMB(state.memory || '256m')) delete subtask.memory;
if (subtask.time) subtask.time += 'ms';
if (subtask.memory) subtask.memory += 'MB';
}
if (subtasks.length === 0) next.subtasks = [];
else {
next.subtasks = autocases.subtasks.map((subtask) => (
next.subtasks = subtasks.map((subtask) => (
{ ...subtask, ...{ cases: subtask.cases.map((i) => ({ input: i.input, output: i.output })) } }));
}
return next;
}
case 'CONFIG_SUBTASKS_SWITCH': {
const next = { ...state };
next.subtasks = next.cases.map((k, v) => ({
id: v, time: k.time, memory: k.memory, cases: [{ input: k.input, output: k.output }],
}));
if (!next.subtasks.length) next.subtasks.push({ id: 0 });
delete next.cases;
return next;
}
case 'CONFIG_SUBTASK_UPDATE': {
const subtasks = cloneDeep(state.subtasks);
const subsubtasks = cloneDeep(state.subtasks[action.id]);