import { Card, NumericInput, Tag } from '@blueprintjs/core'; import { parseMemoryMB, parseTimeMS } from '@hydrooj/utils/lib/common'; import type { SubtaskConfig } from 'hydrooj/src/interface'; import { isEqual, pick } from 'lodash'; import React from 'react'; import { useDispatch, useSelector } from 'react-redux'; import i18n from 'vj/utils/i18n'; import CustomSelectAutoComplete from '../autocomplete/components/CustomSelectAutoComplete'; import { FormItem } from './BasicForm'; import { RootState } from './reducer'; import { CasesTable } from './TestCasesTable'; const eq = (a: SubtaskConfig, b: SubtaskConfig) => isEqual(a, b); export function SubtasksIds({ index }) { const ids = useSelector((state: RootState) => state.config.subtasks.map((i) => (i ? i.id : undefined)).filter((i) => i !== undefined).join(',')); const subtaskIf = useSelector((state: RootState) => state.config.subtasks[index].if); const dispatch = useDispatch(); return ( if i.length)} selectedKeys={subtaskIf?.map(String) || []} onChange={(val) => dispatch({ type: 'CONFIG_SUBTASK_UPDATE', id: index, key: 'if', value: val.split(','), })} multi /> ); } export function SubtasksTable({ index }) { const keys = ['id', 'type', 'score', 'time', 'memory']; const subtask = useSelector((state: RootState) => pick(state.config.subtasks[index], keys), eq); const defaultTime = useSelector((state: RootState) => state.config.time); const defaultMemory = useSelector((state: RootState) => state.config.memory); const dispatch = useDispatch(); const dispatcher = (key: string, suffix = '') => (ev: React.ChangeEvent | number) => { let value = typeof ev !== 'object' ? ev : ev.currentTarget?.value; if (value === 0) value = ''; if (value && suffix) value += suffix; dispatch({ type: 'CONFIG_SUBTASK_UPDATE', id: index, key, value, }); }; if (!subtask || Object.keys(subtask).length === 0) { return ( Subtasks #{index + 1}

{i18n('Failed to parse subtask.')}

); } return ( Subtasks #{index + 1} dispatch({ type: 'CONFIG_SUBTASK_UPDATE', id: index, key: 'add' })}> dispatch({ type: 'CONFIG_SUBTASK_UPDATE', id: index, key: 'delete' })} > {['id', 'score'].map((key) => ( ))}
# Score Type Time Memory
ms} value={subtask.time ? parseTimeMS(subtask.time, false).toString() : ''} placeholder={parseTimeMS(defaultTime || '1000ms', false).toString()} onValueChange={dispatcher('time', 'ms')} buttonPosition="none" fill /> MB} value={subtask.memory ? parseMemoryMB(subtask.memory, false).toString() : ''} placeholder={parseMemoryMB(defaultMemory || '256m', false).toString()} onValueChange={dispatcher('memory', 'MB')} buttonPosition="none" fill />
); } 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 | 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 ( <> ms} value={time ? parseTimeMS(time, false).toString() : ''} placeholder={parseTimeMS('1000ms').toString()} onValueChange={dispatcher('time', 'ms')} buttonPosition="none" fill /> MB} value={memory ? parseMemoryMB(memory, false).toString() : ''} placeholder={parseMemoryMB('256m').toString()} onValueChange={dispatcher('memory', 'MB')} buttonPosition="none" fill /> ); } export function TaskConfig() { const len = useSelector((state: RootState) => state.config.subtasks?.length); const dispatch = useDispatch(); return (
{len > 0 ? [...Array(len).keys()].map((i) => ) : ( <> Subtasks # dispatch({ type: 'CONFIG_SUBTASK_UPDATE', id: 0, key: 'add' })}> )}
); }