mirror of
https://gitcode.com/gh_mirrors/hy/Hydro.git
synced 2026-10-17 17:36:08 +08:00
update interface: ProblemConfig
This commit is contained in:
1 parent
92335d8529
commit
57881792f3
15 files changed
+226
-145
No files matched your search
@@ -14,6 +14,7 @@ module.exports = {
|
||||
parser: '@typescript-eslint/parser',
|
||||
plugins: ['@typescript-eslint'],
|
||||
rules: {
|
||||
camelcase: 'off',
|
||||
'@typescript-eslint/no-unused-vars': 'error',
|
||||
'global-require': 'off',
|
||||
'guard-for-in': 'off',
|
||||
|
||||
@@ -304,14 +304,10 @@ class ContestProblemSubmitHandler extends ContestProblemHandler {
|
||||
@param('code', Types.String)
|
||||
async post(domainId: string, tid: ObjectID, lang: string, code: string) {
|
||||
await this.limitRate('add_record', 60, 100);
|
||||
const rid = await record.add(domainId, {
|
||||
pid: this.pdoc.docId,
|
||||
uid: this.user._id,
|
||||
tid: this.tdoc.docId,
|
||||
ttype: document.TYPE_CONTEST,
|
||||
lang,
|
||||
code,
|
||||
}, true);
|
||||
const rid = await record.add(domainId, this.pdoc.docId, this.user._id, lang, code, true, {
|
||||
type: document.TYPE_CONTEST,
|
||||
tid,
|
||||
});
|
||||
const [rdoc] = await Promise.all([
|
||||
record.get(domainId, rid),
|
||||
contest.updateStatus(domainId, this.tdoc.docId, this.user._id, rid, this.pdoc.docId),
|
||||
|
||||
@@ -181,9 +181,10 @@ class HomeworkDetailProblemSubmitHandler extends HomeworkDetailProblemHandler {
|
||||
if (!tsdoc.attend) throw new HomeworkNotAttendedError(tid);
|
||||
if (!contest.isOngoing(this.tdoc)) throw new HomeworkNotLiveError(tid);
|
||||
if (!this.tdoc.pids.includes(pid)) throw new ProblemNotFoundError(domainId, pid);
|
||||
const rid = await record.add(domainId, {
|
||||
pid, lang, code, uid: this.user._id, tid, hidden: true, ttype: document.TYPE_HOMEWORK,
|
||||
}, true);
|
||||
const rid = await record.add(domainId, pid, this.user._id, lang, code, true, {
|
||||
type: document.TYPE_HOMEWORK,
|
||||
tid,
|
||||
});
|
||||
const [rdoc] = await Promise.all([
|
||||
record.get(domainId, rid),
|
||||
contest.updateStatus(domainId, tid, this.user._id,
|
||||
|
||||
+3
-40
@@ -16,11 +16,11 @@ import {
|
||||
async function _postJudge(rdoc: Rdoc) {
|
||||
const accept = rdoc.status === builtin.STATUS.STATUS_ACCEPTED;
|
||||
const tasks = [];
|
||||
if (rdoc.tid) {
|
||||
if (rdoc.contest) {
|
||||
tasks.push(
|
||||
contest.updateStatus(
|
||||
rdoc.domainId, rdoc.tid, rdoc.uid,
|
||||
rdoc._id, rdoc.pid, accept, rdoc.score, rdoc.ttype,
|
||||
rdoc.domainId, rdoc.contest.tid, rdoc.uid,
|
||||
rdoc._id, rdoc.pid, accept, rdoc.score, rdoc.contest.type,
|
||||
),
|
||||
);
|
||||
}
|
||||
@@ -93,42 +93,6 @@ export async function end(body: JudgeResultBody) {
|
||||
bus.publish('record_change', { rdoc }); // trigger a full update
|
||||
}
|
||||
|
||||
class PretestHandler extends Handler {
|
||||
@param('pid', Types.UnsignedInt, true)
|
||||
@param('code', Types.String)
|
||||
@param('lang', Types.String)
|
||||
@param('time', Types.String, true)
|
||||
@param('memory', Types.String, true)
|
||||
@param('input', Types.String, true)
|
||||
async post(
|
||||
domainId: string, pid = 0,
|
||||
code: string, lang: string,
|
||||
time = '1s', memory = '256m', input = '',
|
||||
) {
|
||||
if (pid) {
|
||||
const pdoc = await problem.get(domainId, pid);
|
||||
if (pdoc.config) {
|
||||
const config: any = yaml.safeLoad(pdoc.config);
|
||||
if (config.time) time = config.time;
|
||||
if (config.memory) memory = config.memory;
|
||||
}
|
||||
}
|
||||
const rid = await record.add(domainId, {
|
||||
pid,
|
||||
uid: this.user._id,
|
||||
type: 'run',
|
||||
time: parseTimeMS(time),
|
||||
memory: parseMemoryMB(memory),
|
||||
input,
|
||||
lang,
|
||||
code,
|
||||
hidden: true,
|
||||
}, true);
|
||||
this.response.body = { rid };
|
||||
this.response.redirect = this.url('record_detail', { rid });
|
||||
}
|
||||
}
|
||||
|
||||
class JudgeHandler extends Handler {
|
||||
async get({ check = false }) {
|
||||
if (check) return;
|
||||
@@ -174,7 +138,6 @@ class JudgeConnectionHandler extends ConnectionHandler {
|
||||
}
|
||||
|
||||
export async function apply() {
|
||||
Route('pretest', '/pretest', PretestHandler);
|
||||
Route('judge', '/judge', JudgeHandler, builtin.PRIV.PRIV_JUDGE);
|
||||
Connection('judge_conn', '/judge/conn', JudgeConnectionHandler, builtin.PRIV.PRIV_JUDGE);
|
||||
}
|
||||
|
||||
+3
-10
@@ -89,18 +89,11 @@ class SystemScriptHandler extends SystemHandler {
|
||||
|
||||
@param('id', Types.String)
|
||||
@param('args', Types.String, true)
|
||||
async post(domainId: string, id: string, args = '{}') {
|
||||
async post(domainId: string, id: string, raw = '{}') {
|
||||
if (!global.Hydro.script[id]) throw new ValidationError('id');
|
||||
args = JSON.parse(args);
|
||||
const args = JSON.parse(raw);
|
||||
validate(global.Hydro.script[id].validate, args);
|
||||
const rid = await record.add(domainId, {
|
||||
pid: -1,
|
||||
uid: this.user._id,
|
||||
lang: '-',
|
||||
code: id,
|
||||
status: STATUS.STATUS_JUDGING,
|
||||
hidden: true,
|
||||
}, false);
|
||||
const rid = await record.add(domainId, -1, this.user._id, '-', id, false, { input: 'raw' });
|
||||
judge.next({ domainId, rid, message: `Running script: ${id}` });
|
||||
async function report(data) {
|
||||
judge.next({ domainId, rid, ...data });
|
||||
|
||||
+22
-15
@@ -24,7 +24,9 @@ import {
|
||||
ValidationError,
|
||||
PermissionError,
|
||||
} from '../error';
|
||||
import { Pdoc, User, Rdoc } from '../interface';
|
||||
import {
|
||||
Pdoc, User, Rdoc, ProblemConfig,
|
||||
} from '../interface';
|
||||
|
||||
const parseCategory = (value: string) => {
|
||||
if (!value) return [];
|
||||
@@ -179,12 +181,9 @@ class ProblemDetailHandler extends ProblemHandler {
|
||||
if (this.pdoc.hidden && this.pdoc.owner !== this.user._id) {
|
||||
this.checkPerm(PERM.PERM_VIEW_PROBLEM_HIDDEN);
|
||||
}
|
||||
const config: any = this.pdoc.config ? yaml.safeLoad(this.pdoc.config) : {};
|
||||
this.udoc = await user.getById(domainId, this.pdoc.owner);
|
||||
this.response.body = {
|
||||
pdoc: this.pdoc,
|
||||
time: config.time,
|
||||
memory: config.memory,
|
||||
udoc: this.udoc,
|
||||
title: this.pdoc.title,
|
||||
path: [
|
||||
@@ -255,14 +254,12 @@ class ProblemSubmitHandler extends ProblemDetailHandler {
|
||||
@param('lang', Types.String)
|
||||
@param('code', Types.String)
|
||||
async post(domainId: string, lang: string, code: string) {
|
||||
const rid = await record.add(domainId, {
|
||||
uid: this.user._id, lang, code, pid: this.pdoc.docId,
|
||||
}, true);
|
||||
const rid = await record.add(domainId, this.pdoc.docId, this.user._id, lang, code, true);
|
||||
const [rdoc] = await Promise.all([
|
||||
record.get(domainId, rid),
|
||||
domain.incUserInDomain(domainId, this.user._id, 'nSubmit'),
|
||||
]);
|
||||
bus.publish('record_change', rdoc);
|
||||
bus.publish('record_change', { rdoc });
|
||||
this.response.body = { rid };
|
||||
this.response.redirect = this.url('record_detail', { rid });
|
||||
}
|
||||
@@ -274,11 +271,18 @@ class ProblemPretestHandler extends ProblemDetailHandler {
|
||||
@param('input', Types.String, true)
|
||||
async post(domainId: string, lang: string, code: string, input: string = '') {
|
||||
this.limitRate('add_record', 3600, 100);
|
||||
const rid = await record.add(domainId, {
|
||||
uid: this.user._id, lang, code, pid: this.pdoc.docId, input,
|
||||
}, true);
|
||||
// TODO parseConfig
|
||||
const rid = await record.add(
|
||||
domainId, this.pdoc.docId, this.user._id,
|
||||
lang, code, true,
|
||||
{
|
||||
input,
|
||||
time: 1000,
|
||||
memory: 256,
|
||||
},
|
||||
);
|
||||
const rdoc = await record.get(domainId, rid);
|
||||
bus.publish('record_change', rdoc);
|
||||
bus.publish('record_change', { rdoc });
|
||||
this.response.body = { rid };
|
||||
}
|
||||
}
|
||||
@@ -311,7 +315,8 @@ class ProblemPretestConnectionHandler extends ConnectionHandler {
|
||||
rdoc.testCases = rdoc.testCases.map((c) => ({
|
||||
status: c.status,
|
||||
}));
|
||||
if (rdoc.tid) return;
|
||||
// TODO handle update
|
||||
if (rdoc.contest) return;
|
||||
this.send({ rdoc });
|
||||
}
|
||||
|
||||
@@ -354,9 +359,11 @@ class ProblemSettingsHandler extends ProblemManageHandler {
|
||||
|
||||
@param('pid', Types.String, null, parsePid)
|
||||
@param('yaml', Types.String)
|
||||
async postConfig(domainId: string, pid: string | number, yaml: string) {
|
||||
async postConfig(domainId: string, pid: string | number, cfg: string) {
|
||||
const pdoc = await problem.get(domainId, pid);
|
||||
await problem.edit(domainId, pdoc.docId, { config: yaml });
|
||||
// TODO validate
|
||||
const config = yaml.safeLoad(cfg);
|
||||
await problem.edit(domainId, pdoc.docId, { config });
|
||||
this.back();
|
||||
}
|
||||
|
||||
|
||||
@@ -63,14 +63,13 @@ class RecordDetailHandler extends RecordHandler {
|
||||
async get(domainId: string, rid: ObjectID) {
|
||||
this.response.template = 'record_detail.html';
|
||||
const rdoc = await record.get(domainId, rid);
|
||||
if (rdoc.tid) {
|
||||
const tdoc = await contest.get(domainId, rdoc.tid, rdoc.ttype);
|
||||
if (rdoc.contest) {
|
||||
const tdoc = await contest.get(domainId, rdoc.contest.tid, rdoc.contest.type);
|
||||
if (!this.canShowRecord(tdoc, true)) throw new PermissionError(rid);
|
||||
}
|
||||
if (rdoc.uid !== this.user.uid && !this.user.hasPerm(PERM.PERM_READ_RECORD_CODE)) {
|
||||
rdoc.code = null;
|
||||
}
|
||||
if (rdoc.type !== 'run') rdoc.stdout = rdoc.stderr = '';
|
||||
const [pdoc, udoc] = await Promise.all([
|
||||
problem.get(domainId, rdoc.pid, null),
|
||||
user.getById(domainId, rdoc.uid),
|
||||
@@ -83,8 +82,6 @@ class RecordDetailHandler extends RecordHandler {
|
||||
udoc,
|
||||
rdoc,
|
||||
pdoc,
|
||||
// TODO protect
|
||||
showStatus: true,
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -134,7 +131,7 @@ class RecordMainConnectionHandler extends RecordConnectionHandler {
|
||||
|
||||
async onRecordChange(data) {
|
||||
const rdoc: Rdoc = data.value.rdoc;
|
||||
if (rdoc.tid && rdoc.tid.toString() !== this.tid) return;
|
||||
if (rdoc.contest && rdoc.contest.tid.toString() !== this.tid) return;
|
||||
// eslint-disable-next-line prefer-const
|
||||
let [udoc, pdoc] = await Promise.all([
|
||||
user.getById(this.domainId, rdoc.uid),
|
||||
@@ -149,8 +146,8 @@ class RecordDetailConnectionHandler extends contest.ContestHandlerMixin(Connecti
|
||||
@param('rid', Types.ObjectID)
|
||||
async prepare(domainId: string, rid: ObjectID) {
|
||||
const rdoc = await record.get(domainId, rid);
|
||||
if (rdoc.tid) {
|
||||
const tdoc = await contest.get(domainId, rdoc.tid, -1);
|
||||
if (rdoc.contest) {
|
||||
const tdoc = await contest.get(domainId, rdoc.contest.tid, -1);
|
||||
if (!this.canShowRecord(tdoc)) {
|
||||
this.close();
|
||||
return;
|
||||
|
||||
+75
-8
@@ -62,6 +62,66 @@ export interface ProblemDataSource {
|
||||
// ObjectID for built-in files, ProblemDataSource for other source (RemoteJudge, etc.)
|
||||
export type ProblemData = ObjectID | ProblemDataSource;
|
||||
|
||||
export interface TestCaseConfig {
|
||||
input: string,
|
||||
output: string,
|
||||
time?: number,
|
||||
memory?: number,
|
||||
}
|
||||
|
||||
export enum LocalProblemType {
|
||||
Default = 'default',
|
||||
SubmitAnswer = 'submit_answer',
|
||||
Interactive = 'interactive',
|
||||
}
|
||||
|
||||
export enum RemoteProblemType {
|
||||
RemoteJudge = 'remotejudge',
|
||||
}
|
||||
|
||||
export enum RemoteServerType {
|
||||
vj4 = 'vj4',
|
||||
syzoj = 'syzoj',
|
||||
}
|
||||
|
||||
export enum SubtaskType {
|
||||
min = 'min',
|
||||
max = 'max',
|
||||
sum = 'sum',
|
||||
}
|
||||
|
||||
export interface SubtaskConfig {
|
||||
time?: number,
|
||||
memory?: number,
|
||||
score?: number,
|
||||
type?: SubtaskType,
|
||||
cases?: TestCaseConfig[],
|
||||
}
|
||||
|
||||
export interface LocalProblemConfig {
|
||||
type?: LocalProblemType,
|
||||
score?: number,
|
||||
time?: number,
|
||||
memory?: number,
|
||||
checker_type?: string,
|
||||
checker?: string,
|
||||
interactor?: string,
|
||||
user_extra_files?: string[],
|
||||
judge_extra_files?: string[],
|
||||
cases?: TestCaseConfig[],
|
||||
subtasks?: SubtaskConfig[],
|
||||
}
|
||||
|
||||
export interface RemoteProblemConfig {
|
||||
type?: RemoteProblemType,
|
||||
server_type?: RemoteServerType,
|
||||
url?: string,
|
||||
// TODO handle username&password storage
|
||||
pid?: string,
|
||||
}
|
||||
|
||||
export type ProblemConfig = LocalProblemConfig | RemoteProblemConfig;
|
||||
|
||||
export interface Pdoc {
|
||||
_id: ObjectID,
|
||||
domainId: string,
|
||||
@@ -77,7 +137,7 @@ export interface Pdoc {
|
||||
category: string[],
|
||||
data?: ProblemData,
|
||||
hidden: boolean,
|
||||
config: string,
|
||||
config: ProblemConfig,
|
||||
acMsg?: string,
|
||||
}
|
||||
|
||||
@@ -90,6 +150,17 @@ export interface TestCase {
|
||||
message: string,
|
||||
}
|
||||
|
||||
export interface PretestConfig {
|
||||
time?: number,
|
||||
memory?: number,
|
||||
input: string,
|
||||
}
|
||||
|
||||
export interface ContestInfo {
|
||||
type: number,
|
||||
tid: ObjectID,
|
||||
}
|
||||
|
||||
export interface Rdoc {
|
||||
_id: ObjectID,
|
||||
domainId: string,
|
||||
@@ -107,13 +178,9 @@ export interface Rdoc {
|
||||
judger: string,
|
||||
judgeAt: Date,
|
||||
status: number,
|
||||
type: string,
|
||||
hidden: boolean,
|
||||
input?: string,
|
||||
stdout?: string,
|
||||
stderr?: string,
|
||||
tid?: ObjectID,
|
||||
ttype?: number,
|
||||
config?: PretestConfig,
|
||||
contest?: ContestInfo,
|
||||
}
|
||||
|
||||
export interface ScoreboardNode {
|
||||
@@ -279,7 +346,7 @@ declare global {
|
||||
paginate: typeof import('./lib/paginate').default,
|
||||
rank: typeof import('./lib/rank').default,
|
||||
rating: typeof import('./lib/rating').default,
|
||||
readConfig: typeof import('./lib/readConfig').default,
|
||||
testdataConfig: typeof import('./lib/testdataConfig'),
|
||||
sha1: typeof import('./lib/sha1').default,
|
||||
sysinfo: typeof import('./lib/sysinfo'),
|
||||
template: typeof import('./lib/template'),
|
||||
|
||||
@@ -1,21 +0,0 @@
|
||||
import Zip from 'adm-zip';
|
||||
|
||||
async function readConfig(filePath: string) {
|
||||
const data = new Zip(filePath);
|
||||
const entries = data.getEntries();
|
||||
for (const entry of entries) {
|
||||
if (entry.name.toLowerCase() === 'config.yaml') {
|
||||
return entry.getData().toString();
|
||||
}
|
||||
if (entry.name.toLowerCase() === 'config.ini') {
|
||||
const ini = entry.getData().toString();
|
||||
const conv = global.Hydro.lib['testdata.convert.ini'];
|
||||
return conv(ini);
|
||||
}
|
||||
}
|
||||
return '';
|
||||
}
|
||||
|
||||
global.Hydro.lib.readConfig = readConfig;
|
||||
|
||||
export default readConfig;
|
||||
@@ -0,0 +1,60 @@
|
||||
import Zip from 'adm-zip';
|
||||
import { safeLoad } from 'js-yaml';
|
||||
import { LocalProblemConfig } from '../interface';
|
||||
|
||||
export async function readConfig(filePath: string) {
|
||||
const data = new Zip(filePath);
|
||||
const entries = data.getEntries();
|
||||
for (const entry of entries) {
|
||||
if (entry.name.toLowerCase() === 'config.yaml') {
|
||||
return entry.getData().toString();
|
||||
}
|
||||
if (entry.name.toLowerCase() === 'config.ini') {
|
||||
const ini = entry.getData().toString();
|
||||
const conv = global.Hydro.lib['testdata.convert.ini'];
|
||||
return conv(ini);
|
||||
}
|
||||
}
|
||||
return '';
|
||||
}
|
||||
|
||||
interface ParseResult {
|
||||
count: number,
|
||||
memoryMax: number,
|
||||
memoryMin: number,
|
||||
timeMax: number,
|
||||
timeMin: number,
|
||||
}
|
||||
|
||||
export async function parseConfig(config: string | LocalProblemConfig) {
|
||||
const result: ParseResult = {
|
||||
count: 0,
|
||||
memoryMin: Number.MAX_SAFE_INTEGER,
|
||||
memoryMax: 0,
|
||||
timeMin: Number.MAX_SAFE_INTEGER,
|
||||
timeMax: 0,
|
||||
};
|
||||
let cfg: LocalProblemConfig = {};
|
||||
if (typeof config === 'string') {
|
||||
// TODO should validate here?
|
||||
cfg = safeLoad(config) as LocalProblemConfig;
|
||||
} else cfg = config;
|
||||
if (cfg.cases) {
|
||||
for (const c of cfg.cases) {
|
||||
result.memoryMax = Math.max(result.memoryMax, c.memory);
|
||||
result.memoryMin = Math.min(result.memoryMin, c.memory);
|
||||
result.timeMax = Math.max(result.timeMax, c.time);
|
||||
result.timeMin = Math.min(result.timeMin, c.time);
|
||||
result.count++;
|
||||
}
|
||||
} else if (cfg.subtasks) {
|
||||
for (const subtask of cfg.subtasks) {
|
||||
result.memoryMax = Math.max(result.memoryMax, subtask.memory);
|
||||
result.memoryMin = Math.min(result.memoryMin, subtask.memory);
|
||||
result.timeMax = Math.max(result.timeMax, subtask.time);
|
||||
result.timeMin = Math.min(result.timeMin, subtask.time);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
global.Hydro.lib.testdataConfig = { readConfig, parseConfig };
|
||||
+6
-1
@@ -10,6 +10,8 @@ import fs from 'fs-extra';
|
||||
import { argv } from 'yargs';
|
||||
import AdmZip from 'adm-zip';
|
||||
|
||||
export * from './interface';
|
||||
|
||||
global.Hydro = {
|
||||
stat: { reqCount: 0 },
|
||||
handler: {},
|
||||
@@ -65,7 +67,10 @@ async function entry(config: EntryConfig) {
|
||||
const sargv = [`--entry=${config.entry}`];
|
||||
const p = await fork(sargv);
|
||||
await new Promise((resolve, reject) => {
|
||||
p.on('exit', resolve);
|
||||
p.on('exit', (code, signal) => {
|
||||
if (code === 0) resolve();
|
||||
else reject(signal);
|
||||
});
|
||||
p.on('error', (err: Error) => {
|
||||
p.kill();
|
||||
reject(err);
|
||||
|
||||
+6
-14
@@ -1,17 +1,15 @@
|
||||
import { ObjectID } from 'mongodb';
|
||||
import * as user from './user';
|
||||
import * as problem from './problem';
|
||||
import * as document from './document';
|
||||
import { PERM } from './builtin';
|
||||
import {
|
||||
ValidationError, ContestNotFoundError, ContestAlreadyAttendedError,
|
||||
ContestNotAttendedError, ContestScoreboardHiddenError,
|
||||
} from '../error';
|
||||
import * as document from './document';
|
||||
import { PERM } from './builtin';
|
||||
import {
|
||||
Tdoc, ContestRule, ContestRules,
|
||||
Udict, ScoreboardNode,
|
||||
ContestRule, ContestRules, ScoreboardNode, Tdoc, Udict,
|
||||
} from '../interface';
|
||||
import * as validator from '../lib/validator';
|
||||
import * as misc from '../lib/misc';
|
||||
import ranked from '../lib/rank';
|
||||
|
||||
@@ -21,7 +19,7 @@ const acm: ContestRule = {
|
||||
statusSort: { accept: -1, time: 1 },
|
||||
showScoreboard: () => true,
|
||||
showRecord: (tdoc, now) => now > tdoc.endAt,
|
||||
stat: (tdoc, journal: any[]) => {
|
||||
stat: (tdoc, journal) => {
|
||||
const naccept = {};
|
||||
const effective = {};
|
||||
const detail = [];
|
||||
@@ -156,12 +154,8 @@ const oi: ContestRule = {
|
||||
}
|
||||
return { score, detail };
|
||||
},
|
||||
showScoreboard(tdoc, now) {
|
||||
return now > tdoc.endAt;
|
||||
},
|
||||
showRecord(tdoc, now) {
|
||||
return now > tdoc.endAt;
|
||||
},
|
||||
showScoreboard: (tdoc, now) => now > tdoc.endAt,
|
||||
showRecord: (tdoc, now) => now > tdoc.endAt,
|
||||
scoreboard(isExport, _, tdoc, rankedTsdocs, udict, pdict) {
|
||||
const columns: ScoreboardNode[] = [
|
||||
{ type: 'rank', value: _('Rank') },
|
||||
@@ -364,8 +358,6 @@ export function add(
|
||||
rule: string, beginAt = new Date(), endAt = new Date(), pids = [],
|
||||
rated = false, data = {}, type = document.TYPE_CONTEST,
|
||||
) {
|
||||
validator.checkTitle(title);
|
||||
validator.checkContent(content);
|
||||
if (!this.RULES[rule]) throw new ValidationError('rule');
|
||||
if (beginAt >= endAt) throw new ValidationError('beginAt', 'endAt');
|
||||
Object.assign(data, {
|
||||
|
||||
@@ -5,7 +5,7 @@ import * as document from './document';
|
||||
import * as domain from './domain';
|
||||
import { Pdoc, Pdict, ProblemDataSource } from '../interface';
|
||||
import { ProblemNotFoundError } from '../error';
|
||||
import readConfig from '../lib/readConfig';
|
||||
import * as testdataConfig from '../lib/testdataConfig';
|
||||
|
||||
export const pdocHidden: Pdoc = {
|
||||
_id: new ObjectID(),
|
||||
@@ -22,7 +22,7 @@ export const pdocHidden: Pdoc = {
|
||||
category: [],
|
||||
data: null,
|
||||
hidden: true,
|
||||
config: '',
|
||||
config: {},
|
||||
acMsg: '',
|
||||
};
|
||||
|
||||
@@ -151,7 +151,7 @@ export function setStar(domainId: string, pid: number, uid: number, star: boolea
|
||||
|
||||
export async function setTestdata(domainId: string, _id: number, filePath: string) {
|
||||
const pdoc = await get(domainId, _id);
|
||||
const config = await readConfig(filePath);
|
||||
const config = await testdataConfig.readConfig(filePath);
|
||||
const id = await file.add(filePath, 'data.zip', 1);
|
||||
if (pdoc.data instanceof ObjectID) file.del(pdoc.data);
|
||||
return await edit(domainId, _id, { data: id, config });
|
||||
|
||||
+33
-13
@@ -4,7 +4,9 @@ import { ObjectID } from 'mongodb';
|
||||
import { STATUS } from './builtin';
|
||||
import * as task from './task';
|
||||
import * as problem from './problem';
|
||||
import { Rdoc, TestCase } from '../interface';
|
||||
import {
|
||||
Rdoc, TestCase, PretestConfig, ContestInfo,
|
||||
} from '../interface';
|
||||
import { RecordNotFoundError } from '../error';
|
||||
import * as db from '../service/db';
|
||||
|
||||
@@ -46,28 +48,50 @@ export interface JudgeTask {
|
||||
type?: string,
|
||||
}
|
||||
|
||||
export async function add(domainId: string, data: RdocBase, addTask: boolean): Promise<ObjectID> {
|
||||
_.defaults(data, {
|
||||
export async function add(
|
||||
domainId: string, pid: number, uid: number,
|
||||
lang: string, code: string, addTask: boolean, contest?: ContestInfo,
|
||||
): Promise<ObjectID>
|
||||
export async function add(
|
||||
domainId: string, pid: number, uid: number,
|
||||
lang: string, code: string, addTask: boolean, config: PretestConfig,
|
||||
): Promise<ObjectID>
|
||||
export async function add(
|
||||
domainId: string, pid: number, uid: number,
|
||||
lang: string, code: string, addTask: boolean, contestOrConfig?: ContestInfo | PretestConfig,
|
||||
) {
|
||||
const data: Rdoc = {
|
||||
status: STATUS.STATUS_WAITING,
|
||||
type: 'judge',
|
||||
_id: new ObjectID(),
|
||||
uid,
|
||||
code,
|
||||
lang,
|
||||
pid,
|
||||
domainId,
|
||||
score: 0,
|
||||
time: 0,
|
||||
memory: 0,
|
||||
hidden: false,
|
||||
hidden: !!contestOrConfig,
|
||||
judgeTexts: [],
|
||||
compilerTexts: [],
|
||||
testCases: [],
|
||||
judger: null,
|
||||
judgeAt: null,
|
||||
});
|
||||
rejudged: false,
|
||||
};
|
||||
if ((contestOrConfig as ContestInfo).type) {
|
||||
// is contest
|
||||
data.contest = contestOrConfig as ContestInfo;
|
||||
} else {
|
||||
data.config = contestOrConfig as PretestConfig;
|
||||
}
|
||||
const [pdoc, res] = await Promise.all([
|
||||
problem.get(domainId, data.pid, null),
|
||||
problem.get(domainId, pid, null),
|
||||
coll.insertOne(data),
|
||||
]);
|
||||
if (addTask) {
|
||||
const t: any = {
|
||||
type: data.type || 'judge',
|
||||
type: 'judge',
|
||||
rid: res.insertedId,
|
||||
domainId,
|
||||
pid: data.pid,
|
||||
@@ -78,11 +102,7 @@ export async function add(domainId: string, data: RdocBase, addTask: boolean): P
|
||||
t.data = pdoc.data;
|
||||
t.config = pdoc.config;
|
||||
} else {
|
||||
t.config = yaml.safeDump({
|
||||
time: data.time,
|
||||
memory: data.memory,
|
||||
input: data.input,
|
||||
});
|
||||
t.config = yaml.safeDump(contestOrConfig);
|
||||
}
|
||||
await task.add(t);
|
||||
}
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "hydrooj",
|
||||
"version": "2.9.13",
|
||||
"version": "2.10.0",
|
||||
"main": "dist/loader.js",
|
||||
"bin": "bin/hydrooj.js",
|
||||
"repository": "https://github.com/hydro-dev/Hydro.git",
|
||||
|
||||
Reference in new issue
Block a user