diff --git a/packages/hydrooj/package.json b/packages/hydrooj/package.json index f6e80169..82b189b0 100644 --- a/packages/hydrooj/package.json +++ b/packages/hydrooj/package.json @@ -1,6 +1,6 @@ { "name": "hydrooj", - "version": "2.28.44", + "version": "2.28.45", "bin": "bin/hydrooj.js", "main": "dist/loader.js", "typings": "dist/loader.d.ts", @@ -12,7 +12,7 @@ }, "preferUnplugged": true, "dependencies": { - "@hydrooj/utils": "workspace:*", + "@hydrooj/utils": "workspace:packages/utils", "adm-zip": "^0.5.5", "ansi_up": "^5.0.1", "cac": "^6.7.3", diff --git a/packages/hydrooj/src/handler/contest.ts b/packages/hydrooj/src/handler/contest.ts index 65c6a667..2d571588 100644 --- a/packages/hydrooj/src/handler/contest.ts +++ b/packages/hydrooj/src/handler/contest.ts @@ -295,7 +295,8 @@ export class ContestProblemHandler extends Handler { // Navigate to current additional file download // e.g. ![img](a.jpg) will navigate to ![img](./pid/file/a.jpg) this.response.body.pdoc.content = this.response.body.pdoc.content - .replace(/\(file:\/\//g, `(./${args[2]}/file/`); + .replace(/\(file:\/\//g, `(./${args[2]}/file/`) + .replace(/="file:\/\//g, `="./${args[2]}/file/`); } } @@ -344,6 +345,9 @@ export class ContestDetailProblemSubmitHandler extends ContestProblemHandler { if (this.response.body.pdoc.config?.langs && !this.response.body.pdoc.config.langs.includes(lang)) { throw new BadRequestError('Language not allowed.'); } + if (this.domain.langs && !this.domain.langs.includes(lang)) { + throw new BadRequestError('Language not allowed'); + } await this.limitRate('add_record', 60, 10); const rid = await record.add(domainId, pid, this.user._id, lang, code, true, pretest ? input : { type: document.TYPE_CONTEST, diff --git a/packages/hydrooj/src/handler/homework.ts b/packages/hydrooj/src/handler/homework.ts index 53271dec..3e760c90 100644 --- a/packages/hydrooj/src/handler/homework.ts +++ b/packages/hydrooj/src/handler/homework.ts @@ -168,7 +168,8 @@ class HomeworkDetailProblemHandler extends Handler { // Navigate to current additional file download // e.g. ![img](a.jpg) will navigate to ![img](./pid/file/a.jpg) this.response.body.pdoc.content = this.response.body.pdoc.content - .replace(/\(file:\/\//g, `(./${pid}/file/`); + .replace(/\(file:\/\//g, `(./${pid}/file/`) + .reaplce(/="file:\/\//g, `="./${pid}/file/`); } } @@ -219,6 +220,9 @@ class HomeworkDetailProblemSubmitHandler extends HomeworkDetailProblemHandler { if (this.response.body.pdoc.config?.langs && !this.response.body.pdoc.config.langs.includes(lang)) { throw new BadRequestError('Language not allowed.'); } + if (this.domain.langs && !this.domain.langs.includes(lang)) { + throw new BadRequestError('Language not allowed'); + } await this.limitRate('add_record', 60, 5); const rid = await record.add(domainId, pid, this.user._id, lang, code, true, pretest ? input : { type: document.TYPE_HOMEWORK, diff --git a/packages/hydrooj/src/handler/problem.ts b/packages/hydrooj/src/handler/problem.ts index 854a7299..79557a44 100644 --- a/packages/hydrooj/src/handler/problem.ts +++ b/packages/hydrooj/src/handler/problem.ts @@ -212,7 +212,8 @@ export class ProblemDetailHandler extends ProblemHandler { // e.g. ![img](a.jpg) will navigate to ![img](./pid/file/a.jpg) if (!this.request.json) { this.response.body.pdoc.content = this.response.body.pdoc.content - .replace(/\(file:\/\//g, `(./${this.pdoc.docId}/file/`); + .replace(/\(file:\/\//g, `(./${this.pdoc.docId}/file/`) + .replace(/="file:\/\//g, `="./${this.pdoc.docId}/file/`); } if (this.psdoc) { this.response.body.rdoc = await record.get(this.domainId, this.psdoc.rid); @@ -269,6 +270,9 @@ export class ProblemSubmitHandler extends ProblemDetailHandler { if (this.response.body.pdoc.config?.langs && !this.response.body.pdoc.config.langs.includes(lang)) { throw new BadRequestError('Language not allowed.'); } + if (this.domain.langs && !this.domain.langs.includes(lang)) { + throw new BadRequestError('Language not allowed'); + } await this.limitRate('add_record', 60, 5); const rid = await record.add(domainId, this.pdoc.docId, this.user._id, lang, code, true, pretest ? input : undefined); const rdoc = await record.get(domainId, rid); diff --git a/packages/hydrooj/src/interface.ts b/packages/hydrooj/src/interface.ts index 61039d42..18ac4283 100644 --- a/packages/hydrooj/src/interface.ts +++ b/packages/hydrooj/src/interface.ts @@ -136,15 +136,19 @@ export enum SubtaskType { } export interface SubtaskConfig { - time?: number, - memory?: number, - score?: number, - type?: SubtaskType, - cases?: TestCaseConfig[], + time?: number; + memory?: number; + score?: number; + if?: number[]; + id?: number; + type?: SubtaskType; + cases?: TestCaseConfig[]; } export interface ProblemConfigFile { type?: ProblemType; + subType?: string; + target?: string; score?: number; time?: string; memory?: string; @@ -168,6 +172,8 @@ export interface ProblemConfig { timeMin: number; langs?: string[]; type: string; + subType?: string; + target?: string; } export interface PlainContentNode { diff --git a/packages/hydrooj/src/lib/content.ts b/packages/hydrooj/src/lib/content.ts index f47f8d7f..ef23f0f7 100644 --- a/packages/hydrooj/src/lib/content.ts +++ b/packages/hydrooj/src/lib/content.ts @@ -26,15 +26,20 @@ export function buildContent(source: ProblemSource | ContentNode[], type: 'markd node.type !== 'Plain' ? `## ${node.sectionTitle}` : '', ...node.type === 'Sample' ? [ + '', `\`\`\`input${++cnt}`, node.payload[0], '```', + '', `\`\`\`output${cnt}`, node.payload[1], '```', + '', ] : [], + '', node.text, + '', ].join('\n')).join('\n'); } return type === 'html' diff --git a/packages/hydrooj/src/lib/testdataConfig.ts b/packages/hydrooj/src/lib/testdataConfig.ts index 969d231c..d0f49f41 100644 --- a/packages/hydrooj/src/lib/testdataConfig.ts +++ b/packages/hydrooj/src/lib/testdataConfig.ts @@ -16,6 +16,8 @@ export async function parseConfig(config: string | ProblemConfigFile = {}) { timeMax: 0, type: cfg.type || 'default', }; + if (cfg.subType) result.subType = cfg.subType; + if (cfg.target) result.target = cfg.target; if (cfg.subtasks.length) { for (const subtask of cfg.subtasks) { result.memoryMax = Math.max(result.memoryMax, subtask.memory); diff --git a/packages/hydrooj/src/model/problem.ts b/packages/hydrooj/src/model/problem.ts index efc7e44b..77f145d5 100644 --- a/packages/hydrooj/src/model/problem.ts +++ b/packages/hydrooj/src/model/problem.ts @@ -39,7 +39,7 @@ export class ProblemModel { domainId: 'system', docType: document.TYPE_PROBLEM, docId: 0, - pid: null, + pid: '', owner: 1, title: '*', content: '', diff --git a/packages/hydrooj/src/model/record.ts b/packages/hydrooj/src/model/record.ts index ba70e7aa..5a9a561e 100644 --- a/packages/hydrooj/src/model/record.ts +++ b/packages/hydrooj/src/model/record.ts @@ -9,7 +9,7 @@ import { STATUS } from './builtin'; import task from './task'; import problem from './problem'; import { - RecordDoc, ContestInfo, ProblemConfigFile, ExternalProblemId, + RecordDoc, ContestInfo, ProblemConfigFile, ExternalProblemId, ProblemConfig, } from '../interface'; import { ArgMethod, buildProjection, Time } from '../utils'; import { MaybeArray } from '../typeutils'; @@ -62,11 +62,25 @@ class RecordModel { static async judge(domainId: string, rid: ObjectID, priority = 0, config: ProblemConfigFile = {}) { const rdoc = await RecordModel.get(domainId, rid); let data = []; + delete rdoc._id; if (rdoc.pid) { const pdoc = await problem.get(rdoc.pdomain, rdoc.pid); data = pdoc.data; + if (typeof pdoc.config === 'string') throw new Error(); // Just for typings. This won't happen. + if (pdoc.config.type === 'remote_judge') { + return await task.add({ + ...rdoc, + priority, + type: 'remotejudge', + subType: pdoc.config.subType, + target: pdoc.config.target, + rid, + domainId, + config, + data, + }); + } } - delete rdoc._id; await task.add({ ...rdoc, priority, diff --git a/packages/hydrooj/src/model/setting.ts b/packages/hydrooj/src/model/setting.ts index 25e9c5b9..2584cedd 100644 --- a/packages/hydrooj/src/model/setting.ts +++ b/packages/hydrooj/src/model/setting.ts @@ -140,6 +140,7 @@ DomainSetting( Setting('setting_domain', 'avatar', '', 'text', 'avatar', 'Will be used as the domain icon.'), Setting('setting_domain', 'share', '', 'text', 'Share problem with domain (* for any)'), Setting('setting_domain', 'bulletin', '', 'markdown', 'Bulletin'), + Setting('setting_domain', 'langs', '', 'text', 'Allowed langs', null), Setting('setting_storage', 'host', '', 'text', 'Custom host', null, FLAG_HIDDEN | FLAG_DISABLED), ); diff --git a/packages/hydrooj/src/service/server.ts b/packages/hydrooj/src/service/server.ts index 102de8f2..50056552 100644 --- a/packages/hydrooj/src/service/server.ts +++ b/packages/hydrooj/src/service/server.ts @@ -503,6 +503,7 @@ export class Handler extends HandlerCommon { throw new NotFoundError(domainId); } this.UiContext.domainId = this.domainId; + this.UiContext.domain = this.domain; this.user = await user.getById(domainId, this.session.uid, this.session.scope); if (!this.user) { this.session.uid = 0;