mirror of
https://gitcode.com/gh_mirrors/hy/Hydro.git
synced 2026-10-19 01:38:19 +08:00
judge: remove useless suffix
This commit is contained in:
1 parent
805c8e4cd3
commit
7f967060cd
12 files changed
+61
-60
No files matched your search
@@ -1,10 +1,21 @@
|
||||
/* eslint-disable no-template-curly-in-string */
|
||||
import { STATUS } from '@hydrooj/utils/lib/status';
|
||||
import { FormatError, SystemError } from './error';
|
||||
import { CheckConfig } from './interface';
|
||||
import { run } from './sandbox';
|
||||
import { CopyInFile, run } from './sandbox';
|
||||
import { parse } from './testlib';
|
||||
|
||||
export interface CheckConfig {
|
||||
execute: string;
|
||||
input: CopyInFile;
|
||||
output: CopyInFile;
|
||||
user_stdout: CopyInFile;
|
||||
user_stderr: CopyInFile;
|
||||
copyIn: Record<string, CopyInFile>;
|
||||
score: number;
|
||||
detail: boolean;
|
||||
env?: Record<string, string>;
|
||||
}
|
||||
|
||||
type Checker = (config: CheckConfig) => Promise<{
|
||||
status: number,
|
||||
score: number,
|
||||
@@ -202,4 +213,4 @@ const checkers: Record<string, Checker> = new Proxy({
|
||||
},
|
||||
});
|
||||
|
||||
export = checkers;
|
||||
export default checkers;
|
||||
@@ -71,8 +71,8 @@ export const runFlow = async (ctx: Context, task: Task) => {
|
||||
const tasks = [];
|
||||
ctx.total_status = 0;
|
||||
ctx.total_score = 0;
|
||||
ctx.total_memory_usage_kb = 0;
|
||||
ctx.total_time_usage_ms = 0;
|
||||
ctx.total_memory = 0;
|
||||
ctx.total_time = 0;
|
||||
ctx.rerun = getConfig('rerun') || 0;
|
||||
ctx.queue = new Queue({ concurrency: getConfig('singleTaskParallelism') });
|
||||
ctx.failed = {};
|
||||
@@ -90,7 +90,7 @@ export const runFlow = async (ctx: Context, task: Task) => {
|
||||
ctx.end({
|
||||
status: ctx.total_status,
|
||||
score: ctx.total_score,
|
||||
time: Math.floor(ctx.total_time_usage_ms * 1000000) / 1000000,
|
||||
memory: ctx.total_memory_usage_kb,
|
||||
time: Math.floor(ctx.total_time * 1000000) / 1000000,
|
||||
memory: ctx.total_memory,
|
||||
});
|
||||
};
|
||||
@@ -19,7 +19,7 @@ const logger = new Logger('judge');
|
||||
|
||||
const session = {
|
||||
config: { detail: system.get('hydrojudge.detail') },
|
||||
async fetchCodeFile(name: string) {
|
||||
async fetchFile(name: string) {
|
||||
const target = path.join('/tmp/hydro/judge', name.replace(/\//g, '_'));
|
||||
await storage.get(`submission/${name}`, target);
|
||||
return target;
|
||||
|
||||
@@ -105,7 +105,7 @@ export default class Hydro {
|
||||
return filePath;
|
||||
}
|
||||
|
||||
async fetchCodeFile(name: string) {
|
||||
async fetchFile(name: string) {
|
||||
const res = await this.axios.post('judge/code', { id: name });
|
||||
const f = await this.axios.get(res.data.url, { responseType: 'stream' })
|
||||
.catch((e) => new Error(`DownloadFail(${name}): ${e.message}`));
|
||||
|
||||
@@ -6,15 +6,3 @@ export interface Execute {
|
||||
copyIn: Record<string, CopyInFile>;
|
||||
time?: number;
|
||||
}
|
||||
|
||||
export interface CheckConfig {
|
||||
execute: string;
|
||||
input: CopyInFile;
|
||||
output: CopyInFile;
|
||||
user_stdout: CopyInFile;
|
||||
user_stderr: CopyInFile;
|
||||
copyIn: Record<string, CopyInFile>;
|
||||
score: number;
|
||||
detail: boolean;
|
||||
env?: Record<string, string>;
|
||||
}
|
||||
@@ -23,7 +23,7 @@ function judgeCase(c: NormalizedCase, sid: string) {
|
||||
const copyIn = { ...ctx.execute.copyIn };
|
||||
if (filename) copyIn[`${filename}.in`] = c.input ? { src: c.input } : { content: '' };
|
||||
const copyOutCached = filename ? [`${filename}.out?`] : [];
|
||||
const stdin = filename ? null : c.input;
|
||||
const stdin = filename ? null : { src: c.input };
|
||||
const res = await run(
|
||||
ctx.execute.execute,
|
||||
{
|
||||
@@ -35,7 +35,7 @@ function judgeCase(c: NormalizedCase, sid: string) {
|
||||
cacheStdoutAndStderr: true,
|
||||
},
|
||||
);
|
||||
const { code, time_usage_ms, memory_usage_kb } = res;
|
||||
const { code, time, memory } = res;
|
||||
let { status } = res;
|
||||
let stdout: CmdFile = { fileId: res.fileIds[filename ? `${filename}.out` : 'stdout'] };
|
||||
const stderr = { fileId: res.fileIds['stderr'] };
|
||||
@@ -43,9 +43,9 @@ function judgeCase(c: NormalizedCase, sid: string) {
|
||||
let message: any = '';
|
||||
let score = 0;
|
||||
if (status === STATUS.STATUS_ACCEPTED) {
|
||||
if (time_usage_ms > c.time * ctx.execute.time) {
|
||||
if (time > c.time * ctx.execute.time) {
|
||||
status = STATUS.STATUS_TIME_LIMIT_EXCEEDED;
|
||||
} else if (memory_usage_kb > c.memory * 1024) {
|
||||
} else if (memory > c.memory * 1024) {
|
||||
status = STATUS.STATUS_MEMORY_LIMIT_EXCEEDED;
|
||||
} else {
|
||||
({ status, score, message } = await checkers[ctx.config.checker_type]({
|
||||
@@ -75,16 +75,16 @@ function judgeCase(c: NormalizedCase, sid: string) {
|
||||
ctxSubtask.score = Score[ctxSubtask.subtask.type](ctxSubtask.score, score);
|
||||
ctxSubtask.status = Math.max(ctxSubtask.status, status);
|
||||
if (ctxSubtask.status > STATUS.STATUS_ACCEPTED) ctx.failed[sid] = true;
|
||||
ctx.total_time_usage_ms += time_usage_ms;
|
||||
ctx.total_memory_usage_kb = Math.max(ctx.total_memory_usage_kb, memory_usage_kb);
|
||||
ctx.total_time += time;
|
||||
ctx.total_memory = Math.max(ctx.total_memory, memory);
|
||||
ctx.next({
|
||||
case: {
|
||||
id: c.id,
|
||||
subtaskId: ctxSubtask.subtask.id,
|
||||
status,
|
||||
score,
|
||||
time: time_usage_ms,
|
||||
memory: memory_usage_kb,
|
||||
time,
|
||||
memory,
|
||||
message,
|
||||
},
|
||||
addProgress: 100 / ctx.config.count,
|
||||
@@ -98,7 +98,7 @@ function judgeCase(c: NormalizedCase, sid: string) {
|
||||
const r = await run(langConfig.analysis, {
|
||||
copyIn: {
|
||||
...copyIn,
|
||||
input: stdin ? { src: stdin } : { content: '' },
|
||||
input: stdin || { content: '' },
|
||||
[langConfig.code_file || 'foo']: ctx.code,
|
||||
compile: { content: langConfig.compile || '' },
|
||||
execute: { content: langConfig.execute || '' },
|
||||
|
||||
@@ -19,7 +19,7 @@ function judgeCase(c: NormalizedCase) {
|
||||
return async (ctx: Context, ctxSubtask: ContextSubTask) => {
|
||||
ctx.executeInteractor.copyIn.in = c.input ? { src: c.input } : { content: '' };
|
||||
ctx.executeInteractor.copyIn.out = c.output ? { src: c.output } : { content: '' };
|
||||
const [{ code, time_usage_ms, memory_usage_kb }, resInteractor] = await runPiped(
|
||||
const [{ code, time, memory }, resInteractor] = await runPiped(
|
||||
{
|
||||
execute: ctx.executeUser.execute,
|
||||
copyIn: ctx.executeUser.copyIn,
|
||||
@@ -39,9 +39,9 @@ function judgeCase(c: NormalizedCase) {
|
||||
let status: number;
|
||||
let score = 0;
|
||||
let message: any = '';
|
||||
if (time_usage_ms > c.time * ctx.executeUser.time) {
|
||||
if (time > c.time * ctx.executeUser.time) {
|
||||
status = STATUS.STATUS_TIME_LIMIT_EXCEEDED;
|
||||
} else if (memory_usage_kb > c.memory * 1024) {
|
||||
} else if (memory > c.memory * 1024) {
|
||||
status = STATUS.STATUS_MEMORY_LIMIT_EXCEEDED;
|
||||
} else if ((code && code !== 13/* Broken Pipe */) || (code === 13 && !resInteractor.code)) {
|
||||
status = STATUS.STATUS_RUNTIME_ERROR;
|
||||
@@ -56,8 +56,8 @@ function judgeCase(c: NormalizedCase) {
|
||||
}
|
||||
ctxSubtask.score = Score[ctxSubtask.subtask.type](ctxSubtask.score, score);
|
||||
ctxSubtask.status = Math.max(ctxSubtask.status, status);
|
||||
ctx.total_time_usage_ms += time_usage_ms;
|
||||
ctx.total_memory_usage_kb = Math.max(ctx.total_memory_usage_kb, memory_usage_kb);
|
||||
ctx.total_time += time;
|
||||
ctx.total_memory = Math.max(ctx.total_memory, memory);
|
||||
ctx.next({
|
||||
status: STATUS.STATUS_JUDGING,
|
||||
case: {
|
||||
@@ -65,8 +65,8 @@ function judgeCase(c: NormalizedCase) {
|
||||
subtaskId: ctxSubtask.subtask.id,
|
||||
status,
|
||||
score,
|
||||
time: time_usage_ms,
|
||||
memory: memory_usage_kb,
|
||||
time,
|
||||
memory,
|
||||
message,
|
||||
},
|
||||
addProgress: 100 / ctx.config.count,
|
||||
|
||||
@@ -8,8 +8,8 @@ export type Context = JudgeTask & RuntimeContext;
|
||||
export interface RuntimeContext {
|
||||
total_score?: number;
|
||||
total_status?: number;
|
||||
total_time_usage_ms?: number;
|
||||
total_memory_usage_kb?: number;
|
||||
total_time?: number;
|
||||
total_memory?: number;
|
||||
|
||||
queue?: PQueue;
|
||||
errored?: boolean;
|
||||
|
||||
@@ -52,14 +52,12 @@ export const judge = async (ctx: Context) => {
|
||||
const { filename } = ctx.config;
|
||||
if (filename) copyIn[`${filename}.in`] = { content: ctx.input };
|
||||
const copyOut = filename ? [`${filename}.out?`] : [];
|
||||
const stdin = path.resolve(ctx.tmpdir, '0.in');
|
||||
await fs.writeFile(stdin, ctx.input || '');
|
||||
const stdout = path.resolve(ctx.tmpdir, '0.out');
|
||||
const stderr = path.resolve(ctx.tmpdir, '0.err');
|
||||
const res = await run(
|
||||
ctx.execute.execute,
|
||||
{
|
||||
stdin: filename ? null : stdin,
|
||||
stdin: filename ? null : { content: ctx.input },
|
||||
stdout: filename ? null : stdout,
|
||||
stderr,
|
||||
copyIn,
|
||||
@@ -68,14 +66,14 @@ export const judge = async (ctx: Context) => {
|
||||
memory: parseMemoryMB(ctx.config.memory || '128m'),
|
||||
},
|
||||
);
|
||||
const { code, time_usage_ms, memory_usage_kb } = res;
|
||||
const { code, time, memory } = res;
|
||||
let { status } = res;
|
||||
if (!fs.existsSync(stdout)) fs.writeFileSync(stdout, '');
|
||||
const message: string[] = [];
|
||||
if (status === STATUS.STATUS_ACCEPTED) {
|
||||
if (time_usage_ms > parseTimeMS(ctx.config.time || '1s') * ctx.execute.time) {
|
||||
if (time > parseTimeMS(ctx.config.time || '1s') * ctx.execute.time) {
|
||||
status = STATUS.STATUS_TIME_LIMIT_EXCEEDED;
|
||||
} else if (memory_usage_kb > parseMemoryMB(ctx.config.memory || '128m') * 1024) {
|
||||
} else if (memory > parseMemoryMB(ctx.config.memory || '128m') * 1024) {
|
||||
status = STATUS.STATUS_MEMORY_LIMIT_EXCEEDED;
|
||||
}
|
||||
} else if (code) {
|
||||
@@ -91,8 +89,8 @@ export const judge = async (ctx: Context) => {
|
||||
subtaskId: 0,
|
||||
status,
|
||||
score: 100,
|
||||
time: time_usage_ms,
|
||||
memory: memory_usage_kb,
|
||||
time,
|
||||
memory,
|
||||
message: message.join('\n').substring(0, 102400),
|
||||
},
|
||||
});
|
||||
@@ -104,7 +102,7 @@ export const judge = async (ctx: Context) => {
|
||||
const r = await run(langConfig.analysis, {
|
||||
copyIn: {
|
||||
...copyIn,
|
||||
input: { src: stdin },
|
||||
input: { content: ctx.input },
|
||||
[langConfig.code_file || 'foo']: ctx.code,
|
||||
compile: { content: langConfig.compile || '' },
|
||||
execute: { content: langConfig.execute || '' },
|
||||
@@ -130,7 +128,7 @@ export const judge = async (ctx: Context) => {
|
||||
ctx.end({
|
||||
status,
|
||||
score: status === STATUS.STATUS_ACCEPTED ? 100 : 0,
|
||||
time: Math.floor(time_usage_ms * 1000000) / 1000000,
|
||||
memory: memory_usage_kb,
|
||||
time: Math.floor(time * 1000000) / 1000000,
|
||||
memory,
|
||||
});
|
||||
};
|
||||
@@ -30,7 +30,7 @@ const statusMap: Map<SandboxStatus, number> = new Map([
|
||||
|
||||
interface Parameter {
|
||||
time?: number;
|
||||
stdin?: string;
|
||||
stdin?: CopyInFile;
|
||||
stdout?: string;
|
||||
stderr?: string;
|
||||
execute?: string;
|
||||
@@ -46,8 +46,10 @@ interface Parameter {
|
||||
interface SandboxAdaptedResult {
|
||||
status: number;
|
||||
code: number;
|
||||
time_usage_ms: number;
|
||||
memory_usage_kb?: number;
|
||||
/** in miliseconds */
|
||||
time: number;
|
||||
/** in kilobytes */
|
||||
memory?: number;
|
||||
files: Record<string, string>;
|
||||
fileIds?: Record<string, string>;
|
||||
stdout?: string;
|
||||
@@ -72,7 +74,7 @@ function proc({
|
||||
time = 16000,
|
||||
memory = parseMemoryMB(getConfig('memoryMax')),
|
||||
processLimit = getConfig('processLimit'),
|
||||
stdin = '', copyIn = {}, copyOut = [], copyOutCached = [],
|
||||
stdin = { content: '' }, copyIn = {}, copyOut = [], copyOutCached = [],
|
||||
cacheStdoutAndStderr = false,
|
||||
env = {},
|
||||
}: Parameter = {}): Cmd {
|
||||
@@ -89,7 +91,7 @@ function proc({
|
||||
args: parseArgs(execute),
|
||||
env: [...getConfig('env').split('\n'), ...Object.keys(env).map((i) => `${i}=${env[i].replace(/=/g, '\\=')}`)],
|
||||
files: [
|
||||
stdin ? { src: stdin } : { content: '' },
|
||||
stdin,
|
||||
{ name: 'stdout', max: Math.floor(1024 * 1024 * size) },
|
||||
{ name: 'stderr', max: Math.floor(1024 * 1024 * size) },
|
||||
],
|
||||
@@ -110,12 +112,12 @@ async function adaptResult(result: SandboxResult, params: Parameter): Promise<Sa
|
||||
// FIXME: Signalled?
|
||||
const ret: SandboxAdaptedResult = {
|
||||
status: statusMap.get(result.status) || STATUS.STATUS_ACCEPTED,
|
||||
time_usage_ms: result.time / 1000000 / rate,
|
||||
memory_usage_kb: result.memory / 1024,
|
||||
time: result.time / 1000000 / rate,
|
||||
memory: result.memory / 1024,
|
||||
files: result.files,
|
||||
code: result.exitStatus,
|
||||
};
|
||||
if (ret.time_usage_ms >= (params.time || 16000)) {
|
||||
if (ret.time >= (params.time || 16000)) {
|
||||
ret.status = STATUS.STATUS_TIME_LIMIT_EXCEEDED;
|
||||
}
|
||||
ret.files = result.files || {};
|
||||
|
||||
@@ -19,7 +19,7 @@ interface Session {
|
||||
getNext: (task: JudgeTask) => NextFunction;
|
||||
getEnd: (task: JudgeTask) => NextFunction;
|
||||
cacheOpen: (source: string, files: any[], next?: NextFunction) => Promise<string>;
|
||||
fetchCodeFile: (target: string) => Promise<string>;
|
||||
fetchFile: (target: string) => Promise<string>;
|
||||
config: { detail: boolean, host?: string };
|
||||
}
|
||||
|
||||
@@ -110,7 +110,7 @@ export class JudgeTask {
|
||||
if ((this.code as any).content.startsWith('@@hydro_submission_file@@')) {
|
||||
const id = (this.code as any).content.split('@@hydro_submission_file@@')[1]?.split('#')?.[0];
|
||||
if (!id) throw new SystemError('Submission File Not Found');
|
||||
const target = await this.session.fetchCodeFile(id);
|
||||
const target = await this.session.fetchFile(id);
|
||||
this.code = { src: target };
|
||||
this.clean.push(() => fs.remove(target));
|
||||
}
|
||||
|
||||
@@ -514,7 +514,9 @@ export interface JudgeResultBody {
|
||||
case?: TestCase,
|
||||
status?: number;
|
||||
score?: number;
|
||||
/** in miliseconds */
|
||||
time?: number;
|
||||
/** in kilobytes */
|
||||
memory?: number;
|
||||
message?: string | JudgeMessage;
|
||||
compilerText?: string;
|
||||
|
||||
Reference in new issue
Block a user