mirror of
https://gitcode.com/gh_mirrors/hy/Hydro.git
synced 2026-10-17 09:36:08 +08:00
judge: optimize
This commit is contained in:
3 files changed
+37
-97
No files matched your search
@@ -1,14 +1,11 @@
|
||||
import { STATUS } from '@hydrooj/utils/lib/status';
|
||||
import checkers from '../checkers';
|
||||
import { runFlow } from '../flow';
|
||||
import { Logger } from '../log';
|
||||
import { del, runQueued } from '../sandbox';
|
||||
import signals from '../signals';
|
||||
import { NormalizedCase } from '../utils';
|
||||
import { Context, ContextSubTask } from './interface';
|
||||
|
||||
const logger = new Logger('judge/default');
|
||||
|
||||
function judgeCase(c: NormalizedCase) {
|
||||
return async (ctx: Context, ctxSubtask: ContextSubTask, runner?: Function) => {
|
||||
const { address_space_limit, process_limit } = ctx.session.getLang(ctx.lang);
|
||||
@@ -58,31 +55,9 @@ function judgeCase(c: NormalizedCase) {
|
||||
ctx.rerun--;
|
||||
return await runner(ctx, ctxSubtask);
|
||||
}
|
||||
if (!ctx.request.rejudged && [STATUS.STATUS_WRONG_ANSWER, STATUS.STATUS_RUNTIME_ERROR].includes(status)) {
|
||||
const langConfig = ctx.session.getLang(ctx.lang);
|
||||
if (langConfig.analysis && !ctx.analysis) {
|
||||
ctx.analysis = true;
|
||||
try {
|
||||
const r = await runQueued(langConfig.analysis, {
|
||||
copyIn: {
|
||||
...ctx.execute.copyIn,
|
||||
input: { src: c.input },
|
||||
[langConfig.code_file || 'foo']: ctx.code,
|
||||
compile: { content: langConfig.compile || '' },
|
||||
execute: { content: langConfig.execute || '' },
|
||||
},
|
||||
time: 5000,
|
||||
memory: 256,
|
||||
env: ctx.env,
|
||||
});
|
||||
const out = r.stdout.toString();
|
||||
if (out.length) ctx.next({ compilerText: out.substring(0, 1024) });
|
||||
if (process.env.DEV) console.log(r);
|
||||
} catch (e) {
|
||||
logger.info('Failed to run analysis');
|
||||
logger.error(e);
|
||||
}
|
||||
}
|
||||
if (!ctx.request.rejudged && !ctx.analysis && [STATUS.STATUS_WRONG_ANSWER, STATUS.STATUS_RUNTIME_ERROR].includes(status)) {
|
||||
ctx.analysis = true;
|
||||
await ctx.runAnalysis(ctx.execute, { src: ctx.input });
|
||||
}
|
||||
return {
|
||||
id: c.id,
|
||||
|
||||
@@ -1,49 +1,16 @@
|
||||
import { STATUS } from '@hydrooj/utils/lib/status';
|
||||
import { CompileError } from '../error';
|
||||
import { Execute } from '../interface';
|
||||
import { Logger } from '../log';
|
||||
import { runQueued } from '../sandbox';
|
||||
import signals from '../signals';
|
||||
import { JudgeTask } from '../task';
|
||||
import { compilerText, parseMemoryMB, parseTimeMS } from '../utils';
|
||||
|
||||
const failure = (status: number, message?: string) => ({
|
||||
status,
|
||||
score: 0,
|
||||
time: 0,
|
||||
memory: 0,
|
||||
message,
|
||||
});
|
||||
import { parseMemoryMB, parseTimeMS } from '../utils';
|
||||
|
||||
const logger = new Logger('judge/run');
|
||||
|
||||
export const judge = async (ctx: JudgeTask) => {
|
||||
ctx.stat.judge = new Date();
|
||||
ctx.next({ status: STATUS.STATUS_COMPILING });
|
||||
let execute: Execute;
|
||||
try {
|
||||
execute = await ctx.compile(
|
||||
ctx.lang, ctx.code,
|
||||
Object.fromEntries(
|
||||
(ctx.config.user_extra_files || []).map((i) => [i.split('/').pop(), { src: i }]),
|
||||
),
|
||||
);
|
||||
} catch (e) {
|
||||
if (e instanceof CompileError) {
|
||||
ctx.next({
|
||||
status: STATUS.STATUS_COMPILE_ERROR,
|
||||
case: failure(STATUS.STATUS_COMPILE_ERROR, compilerText(e.stdout, e.stderr)),
|
||||
});
|
||||
ctx.end(failure(STATUS.STATUS_COMPILE_ERROR));
|
||||
} else {
|
||||
ctx.next({
|
||||
status: STATUS.STATUS_SYSTEM_ERROR,
|
||||
case: failure(STATUS.STATUS_SYSTEM_ERROR, `${e.message}\n${JSON.stringify(e.params)}`),
|
||||
});
|
||||
ctx.end(failure(STATUS.STATUS_SYSTEM_ERROR));
|
||||
}
|
||||
return;
|
||||
}
|
||||
const execute = await ctx.compile(ctx.lang, ctx.code);
|
||||
ctx.next({ status: STATUS.STATUS_JUDGING, progress: 0 });
|
||||
const { address_space_limit, process_limit } = ctx.session.getLang(ctx.lang);
|
||||
const res = await runQueued(
|
||||
@@ -76,6 +43,9 @@ export const judge = async (ctx: JudgeTask) => {
|
||||
message.push(res.stdout, res.stderr);
|
||||
ctx.next({
|
||||
status,
|
||||
time: Math.floor(time * 1000000) / 1000000,
|
||||
memory,
|
||||
score: status === STATUS.STATUS_ACCEPTED ? 100 : 0,
|
||||
case: {
|
||||
subtaskId: 0,
|
||||
status,
|
||||
@@ -86,39 +56,9 @@ export const judge = async (ctx: JudgeTask) => {
|
||||
},
|
||||
});
|
||||
if ([STATUS.STATUS_WRONG_ANSWER, STATUS.STATUS_RUNTIME_ERROR].includes(status)) {
|
||||
const langConfig = ctx.session.getLang(ctx.lang);
|
||||
if (langConfig.analysis) {
|
||||
try {
|
||||
const r = await runQueued(langConfig.analysis, {
|
||||
copyIn: {
|
||||
...execute.copyIn,
|
||||
input: { content: ctx.input },
|
||||
[langConfig.code_file || 'foo']: ctx.code,
|
||||
compile: { content: langConfig.compile || '' },
|
||||
execute: { content: langConfig.execute || '' },
|
||||
},
|
||||
env: {
|
||||
...ctx.env,
|
||||
HYDRO_PRETEST: 'true',
|
||||
},
|
||||
time: 5000,
|
||||
memory: 256,
|
||||
});
|
||||
const out = r.stdout.toString();
|
||||
if (out.length) ctx.next({ compilerText: out.substring(0, 1024) });
|
||||
if (process.env.DEV) console.log(r);
|
||||
} catch (e) {
|
||||
logger.info('Failed to run analysis');
|
||||
logger.error(e);
|
||||
}
|
||||
}
|
||||
await ctx.runAnalysis(execute, { content: ctx.input });
|
||||
}
|
||||
ctx.stat.done = new Date();
|
||||
if (process.env.DEV) ctx.next({ message: JSON.stringify(ctx.stat) });
|
||||
ctx.end({
|
||||
status,
|
||||
score: status === STATUS.STATUS_ACCEPTED ? 100 : 0,
|
||||
time: Math.floor(time * 1000000) / 1000000,
|
||||
memory,
|
||||
});
|
||||
ctx.end({ status });
|
||||
};
|
||||
@@ -10,10 +10,10 @@ import checkers from './checkers';
|
||||
import compile, { compileWithTestlib } from './compile';
|
||||
import { getConfig } from './config';
|
||||
import { CompileError, FormatError } from './error';
|
||||
import { NextFunction, ParsedConfig } from './interface';
|
||||
import { Execute, NextFunction, ParsedConfig } from './interface';
|
||||
import judge from './judge';
|
||||
import { Logger } from './log';
|
||||
import { CopyIn, CopyInFile } from './sandbox';
|
||||
import { CopyIn, CopyInFile, runQueued } from './sandbox';
|
||||
import { compilerText, md5 } from './utils';
|
||||
|
||||
interface Session {
|
||||
@@ -156,4 +156,29 @@ export class JudgeTask {
|
||||
this.clean.push(result.clean);
|
||||
return result;
|
||||
}
|
||||
|
||||
async runAnalysis(execute: Execute, input: CopyInFile) {
|
||||
const langConfig = this.session.getLang(this.lang);
|
||||
if (!langConfig.analysis) return;
|
||||
try {
|
||||
const r = await runQueued(langConfig.analysis, {
|
||||
copyIn: {
|
||||
...execute.copyIn,
|
||||
input,
|
||||
[langConfig.code_file || 'foo']: this.code,
|
||||
compile: { content: langConfig.compile || '' },
|
||||
execute: { content: langConfig.execute || '' },
|
||||
},
|
||||
env: this.env,
|
||||
time: 5000,
|
||||
memory: 256,
|
||||
});
|
||||
const out = r.stdout.toString();
|
||||
if (out.length) this.next({ compilerText: out.substring(0, 1024) });
|
||||
if (process.env.DEV) console.log(r);
|
||||
} catch (e) {
|
||||
logger.info('Failed to run analysis');
|
||||
logger.error(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user