diff --git a/packages/hydrooj/src/model/problem.ts b/packages/hydrooj/src/model/problem.ts index 9235f63dc..27345b1cd 100644 --- a/packages/hydrooj/src/model/problem.ts +++ b/packages/hydrooj/src/model/problem.ts @@ -8,7 +8,7 @@ import yaml from 'js-yaml'; import { pick } from 'lodash'; import { Filter, ObjectId } from 'mongodb'; import type { Readable } from 'stream'; -import { ProblemConfigFile } from '@hydrooj/common'; +import { ProblemConfigFile, ProblemType } from '@hydrooj/common'; import { Logger, size, streamToBuffer } from '@hydrooj/utils/lib/utils'; import { Context } from '../context'; import { FileUploadError, ProblemNotFoundError, ValidationError } from '../error'; @@ -41,6 +41,7 @@ function sortable(source: string, namespaces: Record) { } function findOverrideContent(dir: string, base: string) { + if (!fs.existsSync(dir)) return null; let files = fs.readdirSync(dir); if (files.includes(`${base}.md`)) return fs.readFileSync(path.join(dir, `${base}.md`), 'utf8'); if (files.includes(`${base}.pdf`)) return `@[PDF](file://${base}.pdf)`; @@ -478,7 +479,11 @@ export class ProblemModel { throw new ValidationError('file', null, 'Invalid file'); } const files = await fs.readdir(tmpdir, { withFileTypes: true }); - problems = files.filter((f) => f.isDirectory()).map((i) => i.name); + if (files.find((f) => f.name === 'problem.yaml')) { + problems = ['.']; // special case for ICPC problem package + } else { + problems = files.filter((f) => f.isDirectory()).map((i) => i.name); + } } catch (e) { if (options.delSource) await fs.remove(tmpdir); } @@ -549,6 +554,7 @@ export class ProblemModel { if ((pdoc as any).limits) { config.time = (pdoc as any).limits.time_limit; config.memory = (pdoc as any).limits.memory; + configChanged = true; } const docId = overridePid ? (await ProblemModel.edit(domainId, overridePid, { @@ -577,6 +583,22 @@ export class ProblemModel { : null)?.(domainId, docId, file, path.join(loc, file)); } } + for (const [f, loc] of await getFiles('output_validators')) { + if (f.isFile()) continue; + const sub = await fs.readdir(loc); + for (const file of sub) { + if (file === 'testlib.h') continue; + await ProblemModel.addTestdata(domainId, docId, file, path.join(loc, file)); + if (file === 'checker') { + config.checker_type = 'testlib'; + config.checker = file; + } else if (file === 'interactor') { + config.type = ProblemType.Interactive; + config.interactor = file; + } + configChanged = true; + } + } for (const [f, loc] of await getFiles('additional_file', 'attachments', 'statement', 'problem_statement')) { if (!f.isFile()) continue; await ProblemModel.addAdditionalFile(domainId, docId, f.name, loc);