mirror of
https://gitcode.com/gh_mirrors/hy/Hydro.git
synced 2026-10-20 01:38:19 +08:00
core: remote judge api
This commit is contained in:
1 parent
939584ec5e
commit
680e3ccd32
11 files changed
+54
-13
No files matched your search
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "hydrooj",
|
"name": "hydrooj",
|
||||||
"version": "2.28.44",
|
"version": "2.28.45",
|
||||||
"bin": "bin/hydrooj.js",
|
"bin": "bin/hydrooj.js",
|
||||||
"main": "dist/loader.js",
|
"main": "dist/loader.js",
|
||||||
"typings": "dist/loader.d.ts",
|
"typings": "dist/loader.d.ts",
|
||||||
@@ -12,7 +12,7 @@
|
|||||||
},
|
},
|
||||||
"preferUnplugged": true,
|
"preferUnplugged": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@hydrooj/utils": "workspace:*",
|
"@hydrooj/utils": "workspace:packages/utils",
|
||||||
"adm-zip": "^0.5.5",
|
"adm-zip": "^0.5.5",
|
||||||
"ansi_up": "^5.0.1",
|
"ansi_up": "^5.0.1",
|
||||||
"cac": "^6.7.3",
|
"cac": "^6.7.3",
|
||||||
|
|||||||
@@ -295,7 +295,8 @@ export class ContestProblemHandler extends Handler {
|
|||||||
// Navigate to current additional file download
|
// Navigate to current additional file download
|
||||||
// e.g.  will navigate to 
|
// e.g.  will navigate to 
|
||||||
this.response.body.pdoc.content = this.response.body.pdoc.content
|
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)) {
|
if (this.response.body.pdoc.config?.langs && !this.response.body.pdoc.config.langs.includes(lang)) {
|
||||||
throw new BadRequestError('Language not allowed.');
|
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);
|
await this.limitRate('add_record', 60, 10);
|
||||||
const rid = await record.add(domainId, pid, this.user._id, lang, code, true, pretest ? input : {
|
const rid = await record.add(domainId, pid, this.user._id, lang, code, true, pretest ? input : {
|
||||||
type: document.TYPE_CONTEST,
|
type: document.TYPE_CONTEST,
|
||||||
|
|||||||
@@ -168,7 +168,8 @@ class HomeworkDetailProblemHandler extends Handler {
|
|||||||
// Navigate to current additional file download
|
// Navigate to current additional file download
|
||||||
// e.g.  will navigate to 
|
// e.g.  will navigate to 
|
||||||
this.response.body.pdoc.content = this.response.body.pdoc.content
|
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)) {
|
if (this.response.body.pdoc.config?.langs && !this.response.body.pdoc.config.langs.includes(lang)) {
|
||||||
throw new BadRequestError('Language not allowed.');
|
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);
|
await this.limitRate('add_record', 60, 5);
|
||||||
const rid = await record.add(domainId, pid, this.user._id, lang, code, true, pretest ? input : {
|
const rid = await record.add(domainId, pid, this.user._id, lang, code, true, pretest ? input : {
|
||||||
type: document.TYPE_HOMEWORK,
|
type: document.TYPE_HOMEWORK,
|
||||||
|
|||||||
@@ -212,7 +212,8 @@ export class ProblemDetailHandler extends ProblemHandler {
|
|||||||
// e.g.  will navigate to 
|
// e.g.  will navigate to 
|
||||||
if (!this.request.json) {
|
if (!this.request.json) {
|
||||||
this.response.body.pdoc.content = this.response.body.pdoc.content
|
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) {
|
if (this.psdoc) {
|
||||||
this.response.body.rdoc = await record.get(this.domainId, this.psdoc.rid);
|
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)) {
|
if (this.response.body.pdoc.config?.langs && !this.response.body.pdoc.config.langs.includes(lang)) {
|
||||||
throw new BadRequestError('Language not allowed.');
|
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);
|
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 rid = await record.add(domainId, this.pdoc.docId, this.user._id, lang, code, true, pretest ? input : undefined);
|
||||||
const rdoc = await record.get(domainId, rid);
|
const rdoc = await record.get(domainId, rid);
|
||||||
|
|||||||
@@ -136,15 +136,19 @@ export enum SubtaskType {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export interface SubtaskConfig {
|
export interface SubtaskConfig {
|
||||||
time?: number,
|
time?: number;
|
||||||
memory?: number,
|
memory?: number;
|
||||||
score?: number,
|
score?: number;
|
||||||
type?: SubtaskType,
|
if?: number[];
|
||||||
cases?: TestCaseConfig[],
|
id?: number;
|
||||||
|
type?: SubtaskType;
|
||||||
|
cases?: TestCaseConfig[];
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ProblemConfigFile {
|
export interface ProblemConfigFile {
|
||||||
type?: ProblemType;
|
type?: ProblemType;
|
||||||
|
subType?: string;
|
||||||
|
target?: string;
|
||||||
score?: number;
|
score?: number;
|
||||||
time?: string;
|
time?: string;
|
||||||
memory?: string;
|
memory?: string;
|
||||||
@@ -168,6 +172,8 @@ export interface ProblemConfig {
|
|||||||
timeMin: number;
|
timeMin: number;
|
||||||
langs?: string[];
|
langs?: string[];
|
||||||
type: string;
|
type: string;
|
||||||
|
subType?: string;
|
||||||
|
target?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface PlainContentNode {
|
export interface PlainContentNode {
|
||||||
|
|||||||
@@ -26,15 +26,20 @@ export function buildContent(source: ProblemSource | ContentNode[], type: 'markd
|
|||||||
node.type !== 'Plain' ? `## ${node.sectionTitle}` : '',
|
node.type !== 'Plain' ? `## ${node.sectionTitle}` : '',
|
||||||
...node.type === 'Sample'
|
...node.type === 'Sample'
|
||||||
? [
|
? [
|
||||||
|
'',
|
||||||
`\`\`\`input${++cnt}`,
|
`\`\`\`input${++cnt}`,
|
||||||
node.payload[0],
|
node.payload[0],
|
||||||
'```',
|
'```',
|
||||||
|
'',
|
||||||
`\`\`\`output${cnt}`,
|
`\`\`\`output${cnt}`,
|
||||||
node.payload[1],
|
node.payload[1],
|
||||||
'```',
|
'```',
|
||||||
|
'',
|
||||||
]
|
]
|
||||||
: [],
|
: [],
|
||||||
|
'',
|
||||||
node.text,
|
node.text,
|
||||||
|
'',
|
||||||
].join('\n')).join('\n');
|
].join('\n')).join('\n');
|
||||||
}
|
}
|
||||||
return type === 'html'
|
return type === 'html'
|
||||||
|
|||||||
@@ -16,6 +16,8 @@ export async function parseConfig(config: string | ProblemConfigFile = {}) {
|
|||||||
timeMax: 0,
|
timeMax: 0,
|
||||||
type: cfg.type || 'default',
|
type: cfg.type || 'default',
|
||||||
};
|
};
|
||||||
|
if (cfg.subType) result.subType = cfg.subType;
|
||||||
|
if (cfg.target) result.target = cfg.target;
|
||||||
if (cfg.subtasks.length) {
|
if (cfg.subtasks.length) {
|
||||||
for (const subtask of cfg.subtasks) {
|
for (const subtask of cfg.subtasks) {
|
||||||
result.memoryMax = Math.max(result.memoryMax, subtask.memory);
|
result.memoryMax = Math.max(result.memoryMax, subtask.memory);
|
||||||
|
|||||||
@@ -39,7 +39,7 @@ export class ProblemModel {
|
|||||||
domainId: 'system',
|
domainId: 'system',
|
||||||
docType: document.TYPE_PROBLEM,
|
docType: document.TYPE_PROBLEM,
|
||||||
docId: 0,
|
docId: 0,
|
||||||
pid: null,
|
pid: '',
|
||||||
owner: 1,
|
owner: 1,
|
||||||
title: '*',
|
title: '*',
|
||||||
content: '',
|
content: '',
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ import { STATUS } from './builtin';
|
|||||||
import task from './task';
|
import task from './task';
|
||||||
import problem from './problem';
|
import problem from './problem';
|
||||||
import {
|
import {
|
||||||
RecordDoc, ContestInfo, ProblemConfigFile, ExternalProblemId,
|
RecordDoc, ContestInfo, ProblemConfigFile, ExternalProblemId, ProblemConfig,
|
||||||
} from '../interface';
|
} from '../interface';
|
||||||
import { ArgMethod, buildProjection, Time } from '../utils';
|
import { ArgMethod, buildProjection, Time } from '../utils';
|
||||||
import { MaybeArray } from '../typeutils';
|
import { MaybeArray } from '../typeutils';
|
||||||
@@ -62,11 +62,25 @@ class RecordModel {
|
|||||||
static async judge(domainId: string, rid: ObjectID, priority = 0, config: ProblemConfigFile = {}) {
|
static async judge(domainId: string, rid: ObjectID, priority = 0, config: ProblemConfigFile = {}) {
|
||||||
const rdoc = await RecordModel.get(domainId, rid);
|
const rdoc = await RecordModel.get(domainId, rid);
|
||||||
let data = [];
|
let data = [];
|
||||||
|
delete rdoc._id;
|
||||||
if (rdoc.pid) {
|
if (rdoc.pid) {
|
||||||
const pdoc = await problem.get(rdoc.pdomain, rdoc.pid);
|
const pdoc = await problem.get(rdoc.pdomain, rdoc.pid);
|
||||||
data = pdoc.data;
|
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({
|
await task.add({
|
||||||
...rdoc,
|
...rdoc,
|
||||||
priority,
|
priority,
|
||||||
|
|||||||
@@ -140,6 +140,7 @@ DomainSetting(
|
|||||||
Setting('setting_domain', 'avatar', '', 'text', 'avatar', 'Will be used as the domain icon.'),
|
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', 'share', '', 'text', 'Share problem with domain (* for any)'),
|
||||||
Setting('setting_domain', 'bulletin', '', 'markdown', 'Bulletin'),
|
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),
|
Setting('setting_storage', 'host', '', 'text', 'Custom host', null, FLAG_HIDDEN | FLAG_DISABLED),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
@@ -503,6 +503,7 @@ export class Handler extends HandlerCommon {
|
|||||||
throw new NotFoundError(domainId);
|
throw new NotFoundError(domainId);
|
||||||
}
|
}
|
||||||
this.UiContext.domainId = this.domainId;
|
this.UiContext.domainId = this.domainId;
|
||||||
|
this.UiContext.domain = this.domain;
|
||||||
this.user = await user.getById(domainId, this.session.uid, this.session.scope);
|
this.user = await user.getById(domainId, this.session.uid, this.session.scope);
|
||||||
if (!this.user) {
|
if (!this.user) {
|
||||||
this.session.uid = 0;
|
this.session.uid = 0;
|
||||||
|
|||||||
Reference in new issue
Block a user