mirror of
https://gitcode.com/gh_mirrors/hy/Hydro.git
synced 2026-10-20 01:38:19 +08:00
draft: hack?
This commit is contained in:
1 parent
cd3a426ef8
commit
8b956575ee
10 files changed
+213
-10
No files matched your search
@@ -24,5 +24,5 @@ export async function compileChecker(checkerType: string, checker: string, copyI
|
||||
if (!checkers[checkerType]) { throw new SystemError(`未知比较器类型:${checkerType}`); }
|
||||
const file = await fs.readFile(checker);
|
||||
// TODO cache compiled checker
|
||||
await compile(checker.split('.')[1], file.toString(), 'checker', copyIn);
|
||||
return await compile(checker.split('.')[1], file.toString(), 'checker', copyIn);
|
||||
}
|
||||
@@ -0,0 +1,132 @@
|
||||
// Not implemented
|
||||
import path from 'path';
|
||||
import fs from 'fs-extra';
|
||||
import { STATUS } from 'hydrooj/dist/model/builtin';
|
||||
import { CompileError } from '../error';
|
||||
import { copyInDir, parseFilename } from '../utils';
|
||||
import { run } from '../sandbox';
|
||||
import compile from '../compile';
|
||||
import signals from '../signals';
|
||||
import { check, compileChecker } from '../check';
|
||||
|
||||
export const judge = async (ctx) => {
|
||||
if (ctx.config.template) {
|
||||
if (ctx.config.template[ctx.lang]) {
|
||||
const tpl = ctx.config.template[ctx.lang];
|
||||
ctx.code = tpl[0] + ctx.code + tpl[1];
|
||||
} else throw new CompileError('Language not supported by provided templates');
|
||||
}
|
||||
ctx.next({ status: STATUS.STATUS_COMPILING });
|
||||
if (!ctx.config.validator || !ctx.config.std) throw new CompileError('config.validator or config.std is missing.');
|
||||
const [execute, executeValidator, executeStd, executeChecker] = await Promise.all([
|
||||
// UserProgram
|
||||
(async () => {
|
||||
const copyIn = {};
|
||||
for (const file of ctx.config.user_extra_files) {
|
||||
copyIn[parseFilename(file)] = { src: file };
|
||||
}
|
||||
return await compile(ctx.lang, ctx.code, 'code', copyIn, ctx.next);
|
||||
})(),
|
||||
// Validator
|
||||
(async () => {
|
||||
const copyIn = {};
|
||||
for (const file of ctx.config.judge_extra_files) {
|
||||
copyIn[parseFilename(file)] = { src: file };
|
||||
}
|
||||
const file = await fs.readFile(ctx.config.validator);
|
||||
return await compile(parseFilename(ctx.config.validator).split('.')[1], file.toString(), 'validator', copyIn);
|
||||
})(),
|
||||
// Std
|
||||
(async () => {
|
||||
const copyIn = {};
|
||||
for (const file of ctx.config.user_extra_files) {
|
||||
copyIn[parseFilename(file)] = { src: file };
|
||||
}
|
||||
const file = await fs.readFile(ctx.config.std);
|
||||
return await compile(parseFilename(ctx.config.std).split('.')[1], file.toString(), 'std', copyIn);
|
||||
})(),
|
||||
// Checker
|
||||
(async () => {
|
||||
if (!ctx.config.checker_type || ctx.config.checker_type === 'default') return null;
|
||||
const copyIn = {};
|
||||
for (const file of ctx.config.judge_extra_files) {
|
||||
copyIn[parseFilename(file)] = { src: file };
|
||||
}
|
||||
return await compileChecker(
|
||||
ctx.config.checker_type,
|
||||
ctx.config.checker,
|
||||
copyIn,
|
||||
);
|
||||
})(),
|
||||
]);
|
||||
ctx.clean.push(execute.clean, executeValidator.clean, executeStd.clean, executeChecker.clean);
|
||||
ctx.next({ status: STATUS.STATUS_JUDGING, progress: 0 });
|
||||
const { filename } = ctx.config;
|
||||
const input = path.resolve(ctx.tmpdir, 'input');
|
||||
await fs.writeFile(input, ctx.config.hack);
|
||||
if (filename) execute.copyIn[`${filename}.in`] = { src: input };
|
||||
const copyOut = filename ? [`${filename}.out`] : [];
|
||||
const stdin = filename ? null : input;
|
||||
const stdout = path.resolve(ctx.tmpdir, 'user.out');
|
||||
const stderr = path.resolve(ctx.tmpdir, 'user.err');
|
||||
const res = await run(
|
||||
ctx.execute.execute.replace(/\$\{name\}/g, 'code'),
|
||||
{
|
||||
stdin,
|
||||
stdout: filename ? null : stdout,
|
||||
stderr,
|
||||
copyIn: execute.copyIn,
|
||||
copyOut,
|
||||
time_limit_ms: 1000,
|
||||
memory_limit_mb: 256,
|
||||
},
|
||||
);
|
||||
const { code, time_usage_ms, memory_usage_kb } = res;
|
||||
let { status } = res;
|
||||
if (res.files[`${filename}.out`] || !fs.existsSync(stdout)) {
|
||||
fs.writeFileSync(stdout, res.files[`${filename}.out`] || '');
|
||||
}
|
||||
let message = '';
|
||||
if (status === STATUS.STATUS_ACCEPTED) {
|
||||
if (time_usage_ms > 1000) {
|
||||
status = STATUS.STATUS_TIME_LIMIT_EXCEEDED;
|
||||
} else if (memory_usage_kb > 256 * 1024) {
|
||||
status = STATUS.STATUS_MEMORY_LIMIT_EXCEEDED;
|
||||
} else {
|
||||
[status, , message] = await check({
|
||||
copyIn: copyInDir(path.resolve(ctx.tmpdir, 'checker')),
|
||||
stdin: input,
|
||||
stdout,
|
||||
user_stdout: stdout,
|
||||
user_stderr: stderr,
|
||||
checker: ctx.config.checker,
|
||||
checker_type: ctx.config.checker_type,
|
||||
score: 100,
|
||||
detail: ctx.config.detail,
|
||||
});
|
||||
}
|
||||
} else if (status === STATUS.STATUS_RUNTIME_ERROR && code) {
|
||||
status = STATUS.STATUS_RUNTIME_ERROR;
|
||||
if (code < 32) message = signals[code];
|
||||
else message = `您的程序返回了 ${code}.`;
|
||||
}
|
||||
ctx.next({
|
||||
status: STATUS.STATUS_JUDGING,
|
||||
case: {
|
||||
status,
|
||||
score: 0,
|
||||
time_ms: time_usage_ms,
|
||||
memory_kb: memory_usage_kb,
|
||||
message,
|
||||
},
|
||||
});
|
||||
|
||||
ctx.stat.done = new Date();
|
||||
ctx.next({ message: JSON.stringify(ctx.stat) });
|
||||
ctx.end({
|
||||
status,
|
||||
score: ctx.total_score,
|
||||
time_ms: Math.floor(ctx.total_time_usage_ms * 1000000) / 1000000,
|
||||
memory_kb: ctx.total_memory_usage_kb,
|
||||
});
|
||||
};
|
||||
@@ -2,7 +2,8 @@ import * as def from './default';
|
||||
import * as interactive from './interactive';
|
||||
import * as run from './run';
|
||||
import * as submit_answer from './submit_answer';
|
||||
import * as hack from './hack';
|
||||
|
||||
export = {
|
||||
default: def, interactive, run, submit_answer,
|
||||
default: def, interactive, run, submit_answer, hack,
|
||||
}
|
||||
@@ -210,6 +210,7 @@ async function postInit() {
|
||||
tmpfs.mount(this.tmpdir, '64m');
|
||||
console.log(`Submission: ${this.rid}`, { pid: this.pid });
|
||||
if (this.config.input) await this.run();
|
||||
else if (this.config.hack) await this.hack();
|
||||
else await this.submission();
|
||||
} catch (e) {
|
||||
if (e instanceof CompileError) {
|
||||
@@ -249,6 +250,19 @@ async function postInit() {
|
||||
await judge[this.config.type || 'default'].judge(this);
|
||||
}
|
||||
|
||||
async hack() {
|
||||
this.stat.cache_start = new Date();
|
||||
this.folder = await cacheOpen(this.domainId, this.pid, this.data);
|
||||
this.stat.read_cases = new Date();
|
||||
this.config = await readYamlCases(
|
||||
this.folder,
|
||||
this.config,
|
||||
{ next: this.next },
|
||||
);
|
||||
this.stat.judge = new Date();
|
||||
await judge.hack.judge(this);
|
||||
}
|
||||
|
||||
async run() {
|
||||
this.stat.judge = new Date();
|
||||
await judge.run.judge(this);
|
||||
|
||||
Reference in new issue
Block a user