mirror of
https://gitcode.com/gh_mirrors/hy/Hydro.git
synced 2026-10-20 01:38:19 +08:00
judge: 限制测试包中文件数量
This commit is contained in:
1 parent
de7223e055
commit
1231fb2ce7
5 files changed
+32
-19
No files matched your search
@@ -1,11 +1,12 @@
|
|||||||
{
|
{
|
||||||
"name": "@hydrooj/hydrojudge",
|
"name": "@hydrooj/hydrojudge",
|
||||||
"bin": "bin/hydrojudge.js",
|
"bin": "bin/hydrojudge.js",
|
||||||
"version": "2.1.13",
|
"version": "2.1.14",
|
||||||
"main": "package.json",
|
"main": "package.json",
|
||||||
"author": "masnn",
|
"author": "masnn",
|
||||||
"repository": "https://github.com/hydro-dev/Hydro.git",
|
"repository": "https://github.com/hydro-dev/Hydro.git",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"adm-zip": "^0.4.16",
|
||||||
"axios": "^0.21.0",
|
"axios": "^0.21.0",
|
||||||
"bson": "^4.1.0",
|
"bson": "^4.1.0",
|
||||||
"fs-extra": "^9.0.1",
|
"fs-extra": "^9.0.1",
|
||||||
|
|||||||
@@ -243,7 +243,7 @@ export async function readYamlCases(folder: string, cfg: Dictionary<any> = {}, a
|
|||||||
} else if (cfg.subtasks) {
|
} else if (cfg.subtasks) {
|
||||||
for (const subtask of cfg.subtasks) {
|
for (const subtask of cfg.subtasks) {
|
||||||
const cases = [];
|
const cases = [];
|
||||||
for (const c of subtask) {
|
for (const c of subtask.cases) {
|
||||||
config.count++;
|
config.count++;
|
||||||
cases.push({
|
cases.push({
|
||||||
input: checkFile(c.input, '找不到输入文件 '),
|
input: checkFile(c.input, '找不到输入文件 '),
|
||||||
@@ -269,14 +269,17 @@ export async function readYamlCases(folder: string, cfg: Dictionary<any> = {}, a
|
|||||||
function convertIniConfig(ini: string) {
|
function convertIniConfig(ini: string) {
|
||||||
const f = ini.split('\n');
|
const f = ini.split('\n');
|
||||||
const count = parseInt(f[0], 10);
|
const count = parseInt(f[0], 10);
|
||||||
const res = { cases: [] };
|
const res = { subtasks: [] };
|
||||||
for (let i = 1; i <= count; i++) {
|
for (let i = 1; i <= count; i++) {
|
||||||
const [input, output, time, score, memory] = f[i].split('|');
|
const [input, output, time, score, memory] = f[i].split('|');
|
||||||
const cur = {
|
const cur = {
|
||||||
input: `input/${input}`, output: `output/${output}`, score: parseInt(score, 10), time: `${time}s`, memory: '128m',
|
cases: [{ input: `input/${input}`, output: `output/${output}` }],
|
||||||
|
score: parseInt(score, 10),
|
||||||
|
time: `${time}s`,
|
||||||
|
memory: '128m',
|
||||||
};
|
};
|
||||||
if (!Number.isNaN(parseInt(memory, 10))) cur.memory = `${Math.floor(parseInt(memory, 10) / 1024)}m`;
|
if (!Number.isNaN(parseInt(memory, 10))) cur.memory = `${Math.floor(parseInt(memory, 10) / 1024)}m`;
|
||||||
res.cases.push(cur);
|
res.subtasks.push(cur);
|
||||||
}
|
}
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,12 +1,12 @@
|
|||||||
/* eslint-disable no-await-in-loop */
|
/* eslint-disable no-await-in-loop */
|
||||||
import path from 'path';
|
import path from 'path';
|
||||||
import child from 'child_process';
|
|
||||||
import axios from 'axios';
|
import axios from 'axios';
|
||||||
|
import AdmZip from 'adm-zip';
|
||||||
import fs from 'fs-extra';
|
import fs from 'fs-extra';
|
||||||
import WebSocket from 'ws';
|
import WebSocket from 'ws';
|
||||||
import * as tmpfs from '../tmpfs';
|
import * as tmpfs from '../tmpfs';
|
||||||
import log from '../log';
|
import log from '../log';
|
||||||
import { compilerText } from '../utils';
|
import { compilerText, Queue } from '../utils';
|
||||||
import { CACHE_DIR, TEMP_DIR } from '../config';
|
import { CACHE_DIR, TEMP_DIR } from '../config';
|
||||||
import { FormatError, CompileError, SystemError } from '../error';
|
import { FormatError, CompileError, SystemError } from '../error';
|
||||||
import { STATUS_COMPILE_ERROR, STATUS_SYSTEM_ERROR } from '../status';
|
import { STATUS_COMPILE_ERROR, STATUS_SYSTEM_ERROR } from '../status';
|
||||||
@@ -240,15 +240,18 @@ export default class VJ4 {
|
|||||||
`${this.config.server_url}d/${domainId}/p/${pid}/data`,
|
`${this.config.server_url}d/${domainId}/p/${pid}/data`,
|
||||||
{ responseType: 'stream' },
|
{ responseType: 'stream' },
|
||||||
);
|
);
|
||||||
const w = await fs.createWriteStream(tmpFilePath);
|
const w = fs.createWriteStream(tmpFilePath);
|
||||||
res.data.pipe(w);
|
res.data.pipe(w);
|
||||||
await new Promise((resolve, reject) => {
|
await new Promise((resolve, reject) => {
|
||||||
w.on('finish', resolve);
|
w.on('finish', resolve);
|
||||||
w.on('error', reject);
|
w.on('error', reject);
|
||||||
});
|
});
|
||||||
fs.ensureDirSync(path.dirname(savePath));
|
fs.ensureDirSync(path.dirname(savePath));
|
||||||
|
const zip = new AdmZip(tmpFilePath);
|
||||||
|
const entries = zip.getEntries();
|
||||||
|
if (entries.length > 1000) throw new FormatError('Too many files');
|
||||||
await new Promise((resolve, reject) => {
|
await new Promise((resolve, reject) => {
|
||||||
child.exec(`unzip ${tmpFilePath} -d ${savePath}`, (e) => {
|
zip.extractAllToAsync(savePath, true, (e) => {
|
||||||
if (e) reject(e);
|
if (e) reject(e);
|
||||||
else resolve();
|
else resolve();
|
||||||
});
|
});
|
||||||
@@ -262,20 +265,23 @@ export default class VJ4 {
|
|||||||
return savePath;
|
return savePath;
|
||||||
}
|
}
|
||||||
|
|
||||||
async recordPretestData(rid, savePath) {
|
async recordPretestData(rid: string, savePath: string) {
|
||||||
log.info(`Getting pretest data: ${this.config.host}/${rid}`);
|
log.info(`Getting pretest data: ${this.config.host}/${rid}`);
|
||||||
const tmpFilePath = path.resolve(CACHE_DIR, `download_${this.config.host}_${rid}`);
|
const tmpFilePath = path.resolve(CACHE_DIR, `download_${this.config.host}_${rid}`);
|
||||||
await this.ensureLogin();
|
await this.ensureLogin();
|
||||||
const res = await this.axios.get(`records/${rid}/data`, { responseType: 'stream' });
|
const res = await this.axios.get(`records/${rid}/data`, { responseType: 'stream' });
|
||||||
const w = await fs.createWriteStream(tmpFilePath);
|
const w = fs.createWriteStream(tmpFilePath);
|
||||||
res.data.pipe(w);
|
res.data.pipe(w);
|
||||||
await new Promise((resolve, reject) => {
|
await new Promise((resolve, reject) => {
|
||||||
w.on('finish', resolve);
|
w.on('finish', resolve);
|
||||||
w.on('error', reject);
|
w.on('error', reject);
|
||||||
});
|
});
|
||||||
fs.ensureDirSync(path.dirname(savePath));
|
fs.ensureDirSync(path.dirname(savePath));
|
||||||
|
const zip = new AdmZip(tmpFilePath);
|
||||||
|
const entries = zip.getEntries();
|
||||||
|
if (entries.length > 1000) throw new FormatError('Too many files');
|
||||||
await new Promise((resolve, reject) => {
|
await new Promise((resolve, reject) => {
|
||||||
child.exec(`unzip ${tmpFilePath} -d ${savePath}`, (e) => {
|
zip.extractAllToAsync(savePath, true, (e) => {
|
||||||
if (e) reject(e);
|
if (e) reject(e);
|
||||||
else resolve();
|
else resolve();
|
||||||
});
|
});
|
||||||
@@ -285,7 +291,7 @@ export default class VJ4 {
|
|||||||
return savePath;
|
return savePath;
|
||||||
}
|
}
|
||||||
|
|
||||||
async consume(queue) {
|
async consume(queue: Queue<any>) {
|
||||||
log.info('正在连接 %sjudge/consume-conn', this.config.server_url);
|
log.info('正在连接 %sjudge/consume-conn', this.config.server_url);
|
||||||
const res = await this.axios.get('judge/consume-conn/info');
|
const res = await this.axios.get('judge/consume-conn/info');
|
||||||
this.ws = new WebSocket(`${this.config.server_url.replace(/^http/i, 'ws')}judge/consume-conn/websocket?t=${res.data.entropy}`, {
|
this.ws = new WebSocket(`${this.config.server_url.replace(/^http/i, 'ws')}judge/consume-conn/websocket?t=${res.data.entropy}`, {
|
||||||
|
|||||||
@@ -2,10 +2,10 @@
|
|||||||
/* eslint-disable no-await-in-loop */
|
/* eslint-disable no-await-in-loop */
|
||||||
import 'hydrooj';
|
import 'hydrooj';
|
||||||
import path from 'path';
|
import path from 'path';
|
||||||
import child from 'child_process';
|
|
||||||
import { ObjectID } from 'bson';
|
import { ObjectID } from 'bson';
|
||||||
import fs from 'fs-extra';
|
import fs from 'fs-extra';
|
||||||
import { homedir, tmpdir } from 'os';
|
import { homedir, tmpdir } from 'os';
|
||||||
|
import AdmZip from 'adm-zip';
|
||||||
|
|
||||||
declare module 'hydrooj/dist/interface' {
|
declare module 'hydrooj/dist/interface' {
|
||||||
interface SystemKeys {
|
interface SystemKeys {
|
||||||
@@ -73,8 +73,11 @@ async function postInit() {
|
|||||||
w.on('error', reject);
|
w.on('error', reject);
|
||||||
});
|
});
|
||||||
fs.ensureDirSync(path.dirname(savePath));
|
fs.ensureDirSync(path.dirname(savePath));
|
||||||
|
const zip = new AdmZip(tmpFilePath);
|
||||||
|
const entries = zip.getEntries();
|
||||||
|
if (entries.length > 1000) throw new FormatError('Too many files');
|
||||||
await new Promise((resolve, reject) => {
|
await new Promise((resolve, reject) => {
|
||||||
child.exec(`unzip ${tmpFilePath} -d ${savePath}`, (e) => {
|
zip.extractAllToAsync(savePath, true, (e) => {
|
||||||
if (e) reject(e);
|
if (e) reject(e);
|
||||||
else resolve();
|
else resolve();
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -13,19 +13,19 @@ const EMPTY_STR = /^[ \r\n\t]*$/i;
|
|||||||
|
|
||||||
export const cmd = parse;
|
export const cmd = parse;
|
||||||
|
|
||||||
export function parseTimeMS(str) {
|
export function parseTimeMS(str: string) {
|
||||||
const match = TIME_RE.exec(str);
|
const match = TIME_RE.exec(str);
|
||||||
if (!match) throw new FormatError(str, ['error parsing time']);
|
if (!match) throw new FormatError(str, ['error parsing time']);
|
||||||
return Math.floor(parseFloat(match[1]) * TIME_UNITS[match[2]]);
|
return Math.floor(parseFloat(match[1]) * TIME_UNITS[match[2]]);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function parseMemoryMB(str) {
|
export function parseMemoryMB(str: string) {
|
||||||
const match = MEMORY_RE.exec(str);
|
const match = MEMORY_RE.exec(str);
|
||||||
if (!match) throw new FormatError(str, ['error parsing memory']);
|
if (!match) throw new FormatError(str, ['error parsing memory']);
|
||||||
return Math.floor(parseFloat(match[1]) * MEMORY_UNITS[match[2]]);
|
return Math.floor(parseFloat(match[1]) * MEMORY_UNITS[match[2]]);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function sleep(timeout) {
|
export function sleep(timeout: number) {
|
||||||
return new Promise((resolve) => {
|
return new Promise((resolve) => {
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
resolve();
|
resolve();
|
||||||
@@ -84,7 +84,7 @@ export function compilerText(stdout: string, stderr: string) {
|
|||||||
return ret.join('\n');
|
return ret.join('\n');
|
||||||
}
|
}
|
||||||
|
|
||||||
export function copyInDir(dir) {
|
export function copyInDir(dir: string) {
|
||||||
const files = {};
|
const files = {};
|
||||||
if (fs.existsSync(dir)) {
|
if (fs.existsSync(dir)) {
|
||||||
fs.readdirSync(dir).forEach((f1) => {
|
fs.readdirSync(dir).forEach((f1) => {
|
||||||
|
|||||||
Reference in new issue
Block a user