mirror of
https://gitcode.com/gh_mirrors/hy/Hydro.git
synced 2026-10-19 09:38:19 +08:00
ui: problemconfig: support new CompilableSource
This commit is contained in:
1 parent
4a33816a37
commit
5c9cecc197
17 files changed
+252
-228
No files matched your search
@@ -1,6 +1,7 @@
|
||||
import React from 'react';
|
||||
import { useDispatch, useSelector } from 'react-redux';
|
||||
import { i18n } from 'vj/utils';
|
||||
import CustomSelectAutoComplete from '../autocomplete/components/CustomSelectAutoComplete';
|
||||
import FileSelectAutoComplete from '../autocomplete/components/FileSelectAutoComplete';
|
||||
import type { RootState } from './reducer/index';
|
||||
|
||||
@@ -21,6 +22,7 @@ export function FormItem({
|
||||
type KeyType<K, T = string | number> = {
|
||||
[Q in keyof K]: K[Q] extends T ? Q : never;
|
||||
}[keyof K];
|
||||
type FileSelectKey = 'checker' | 'interactor' | 'manager';
|
||||
|
||||
export function ManagedInput({ placeholder, formKey }: { placeholder?: string, formKey: KeyType<RootState['config']> }) {
|
||||
const value = useSelector((state: RootState) => state.config[formKey]);
|
||||
@@ -54,16 +56,42 @@ export function ManagedSelect({ options, formKey }: { options: string[], formKey
|
||||
);
|
||||
}
|
||||
|
||||
export function SingleFileSelect({ formKey }: { formKey: KeyType<RootState['config']> }) {
|
||||
const prefixes = new Set(Object.keys(window.LANGS).filter((i) => i.includes('.')).map((i) => i.split('.')[0]));
|
||||
const data = Object.keys(window.LANGS).filter((i) => !prefixes.has(i))
|
||||
.map((i) => ({ name: `${i.includes('.') ? `${window.LANGS[i.split('.')[0]].display || ''}/` : ''}${window.LANGS[i].display}`, _id: i }));
|
||||
data.unshift({ name: 'Auto', _id: 'auto' });
|
||||
|
||||
export function SingleFileSelect({ formKey, withLang = false, label = 'Checker' }: { formKey: FileSelectKey, withLang?: boolean, label?: string }) {
|
||||
const value = useSelector((state: RootState) => state.config[formKey]);
|
||||
const Files = useSelector((state: RootState) => state.testdata);
|
||||
const dispatch = useDispatch();
|
||||
return (
|
||||
<FileSelectAutoComplete
|
||||
width="100%"
|
||||
data={Files}
|
||||
selectedKeys={[value]}
|
||||
onChange={(val) => dispatch({ type: 'CONFIG_FORM_UPDATE', key: formKey, value: val })}
|
||||
/>
|
||||
);
|
||||
const selectedFile = typeof value === 'string' ? value : value?.file || '';
|
||||
const selectedLang = typeof value === 'string' ? 'auto' : value?.lang || 'auto';
|
||||
const update = (file: string, lang: string) => {
|
||||
if (file === selectedFile && lang === selectedLang) return;
|
||||
if (withLang) dispatch({ type: 'CONFIG_FORM_UPDATE', key: formKey, value: file ? { file, lang } : null });
|
||||
else dispatch({ type: 'CONFIG_FORM_UPDATE', key: formKey, value: file });
|
||||
};
|
||||
return withLang ? (<>
|
||||
<FormItem columns={5} label={label}>
|
||||
<FileSelectAutoComplete
|
||||
width="100%"
|
||||
data={Files}
|
||||
selectedKeys={[selectedFile]}
|
||||
onChange={(val) => update(val, selectedLang)}
|
||||
/>
|
||||
</FormItem>
|
||||
<FormItem columns={3} label="Language">
|
||||
<CustomSelectAutoComplete
|
||||
data={data}
|
||||
selectedKeys={[selectedLang]}
|
||||
onChange={(val) => update(selectedFile, val)}
|
||||
/>
|
||||
</FormItem>
|
||||
</>) : (<FileSelectAutoComplete
|
||||
width="100%"
|
||||
data={Files}
|
||||
selectedKeys={[selectedFile]}
|
||||
onChange={(val) => update(val, selectedLang)}
|
||||
/>);
|
||||
}
|
||||
@@ -20,7 +20,8 @@ export default function ProblemType() {
|
||||
const dispatcher = (base) => (value) => dispatch({ ...base, value });
|
||||
useEffect(() => {
|
||||
if (category || !checker) return;
|
||||
if (checker.includes('.')) setCategory('custom');
|
||||
const name = typeof checker === 'string' ? checker : checker.file;
|
||||
if (name.includes('.')) setCategory('custom');
|
||||
else setCategory('preset');
|
||||
}, [checker]);
|
||||
return (
|
||||
@@ -75,7 +76,7 @@ export default function ProblemType() {
|
||||
title="testlib"
|
||||
panel={(
|
||||
<div className="row">
|
||||
<FormItem columns={6} label="Type">
|
||||
<FormItem columns={4} label="Type">
|
||||
<select
|
||||
value={category}
|
||||
onChange={(ev) => {
|
||||
@@ -89,9 +90,9 @@ export default function ProblemType() {
|
||||
</select>
|
||||
</FormItem>
|
||||
{category === 'preset'
|
||||
? <FormItem columns={6} label="Checker">
|
||||
? <FormItem columns={8} label="Checker">
|
||||
<select
|
||||
value={checker}
|
||||
value={typeof checker === 'string' ? checker : checker.file}
|
||||
onChange={(ev) => dispatch({ type: 'CONFIG_FORM_UPDATE', key: 'checker', value: ev.currentTarget.value })}
|
||||
className="select"
|
||||
>
|
||||
@@ -100,9 +101,7 @@ export default function ProblemType() {
|
||||
))}
|
||||
</select>
|
||||
</FormItem>
|
||||
: <FormItem columns={6} label="Checker">
|
||||
<SingleFileSelect formKey="checker" />
|
||||
</FormItem>}
|
||||
: <SingleFileSelect formKey="checker" label="Checker" withLang />}
|
||||
</div>
|
||||
)}
|
||||
/>
|
||||
@@ -111,12 +110,10 @@ export default function ProblemType() {
|
||||
title="other"
|
||||
panel={(
|
||||
<div className="row">
|
||||
<FormItem columns={6} label="Interface">
|
||||
<FormItem columns={4} label="Interface">
|
||||
<ManagedSelect options={['syzoj', 'hustoj', 'qduoj', 'lemon']} formKey="checker_type" />
|
||||
</FormItem>
|
||||
<FormItem columns={6} label="Checker">
|
||||
<SingleFileSelect formKey="checker" />
|
||||
</FormItem>
|
||||
<SingleFileSelect formKey="checker" label="Checker" withLang />
|
||||
</div>
|
||||
)}
|
||||
/>
|
||||
@@ -128,9 +125,7 @@ export default function ProblemType() {
|
||||
title={i18n('problem_type.interactive')}
|
||||
panel={(
|
||||
<div className="row">
|
||||
<FormItem columns={6} label="Interactor">
|
||||
<SingleFileSelect formKey="interactor" />
|
||||
</FormItem>
|
||||
<SingleFileSelect formKey="interactor" label="Interactor" withLang />
|
||||
</div>
|
||||
)}
|
||||
/>
|
||||
@@ -139,10 +134,8 @@ export default function ProblemType() {
|
||||
title={i18n('problem_type.communication')}
|
||||
panel={(
|
||||
<div className="row">
|
||||
<FormItem columns={6} label="Manager">
|
||||
<SingleFileSelect formKey="manager" />
|
||||
</FormItem>
|
||||
<FormItem columns={6} label="Number of Processes">
|
||||
<SingleFileSelect formKey="manager" label="Manager" withLang />
|
||||
<FormItem columns={4} label="Number of Processes">
|
||||
<input
|
||||
defaultValue={numProcesses || 2}
|
||||
placeholder="2"
|
||||
|
||||
@@ -51,7 +51,7 @@ export default function reducer(state = {
|
||||
const next = { ...state, [action.key]: action.value };
|
||||
if (action.key === 'score' && action.value) next.score = +next.score;
|
||||
if (action.key === 'checker_type' && action.value === 'other') next.checker_type = 'syzoj';
|
||||
if (!action.value || (typeof action.value === 'object' && !action.value.join(''))) delete next[action.key];
|
||||
if (!action.value || (action.value instanceof Array && !action.value.join(''))) delete next[action.key];
|
||||
return next;
|
||||
}
|
||||
case 'CONFIG_CODE_UPDATE': {
|
||||
|
||||
Reference in new issue
Block a user