mirror of
https://gitcode.com/gh_mirrors/hy/Hydro.git
synced 2026-10-20 09:46:28 +08:00
judge: remove check() function
This commit is contained in:
1 parent
1c6cdfc6ff
commit
805c8e4cd3
6 files changed
+43
-53
No files matched your search
@@ -1,35 +0,0 @@
|
|||||||
import { findFileSync } from '@hydrooj/utils/lib/utils';
|
|
||||||
import checkers from './checkers';
|
|
||||||
import compile from './compile';
|
|
||||||
import { SystemError } from './error';
|
|
||||||
import { CheckConfig, Execute } from './interface';
|
|
||||||
|
|
||||||
const testlibSrc = findFileSync('@hydrooj/hydrojudge/vendor/testlib/testlib.h');
|
|
||||||
|
|
||||||
export async function check(config: CheckConfig): Promise<[number, number, string]> {
|
|
||||||
if (!checkers[config.checker_type]) throw new SystemError('Unknown checker type {0}', [config.checker_type]);
|
|
||||||
const {
|
|
||||||
code, status, score, message,
|
|
||||||
} = await checkers[config.checker_type](config);
|
|
||||||
if (code) throw new SystemError('Checker returned {0}.', [code]);
|
|
||||||
return [status, score, message];
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function compileChecker(getLang: Function, checkerType: string, checker: string, copyIn: any): Promise<Execute> {
|
|
||||||
if (['default', 'strict'].includes(checkerType)) {
|
|
||||||
return { execute: '', copyIn: {}, clean: () => Promise.resolve(null) };
|
|
||||||
}
|
|
||||||
if (!checkers[checkerType]) throw new SystemError('Unknown checker type {0}.', [checkerType]);
|
|
||||||
if (checkerType === 'testlib') copyIn['testlib.h'] = { src: testlibSrc };
|
|
||||||
const s = checker.replace('@', '.').split('.');
|
|
||||||
let lang;
|
|
||||||
let langId = s.pop();
|
|
||||||
while (s.length) {
|
|
||||||
lang = getLang(langId, false);
|
|
||||||
if (lang) break;
|
|
||||||
langId = `${s.pop()}.${langId}`;
|
|
||||||
}
|
|
||||||
if (!lang) throw new SystemError('Unknown checker language.');
|
|
||||||
// TODO cache compiled checker
|
|
||||||
return await compile(lang, { src: checker }, copyIn);
|
|
||||||
}
|
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
/* eslint-disable no-template-curly-in-string */
|
/* eslint-disable no-template-curly-in-string */
|
||||||
import { STATUS } from '@hydrooj/utils/lib/status';
|
import { STATUS } from '@hydrooj/utils/lib/status';
|
||||||
import { SystemError } from './error';
|
import { FormatError, SystemError } from './error';
|
||||||
import { CheckConfig } from './interface';
|
import { CheckConfig } from './interface';
|
||||||
import { run } from './sandbox';
|
import { run } from './sandbox';
|
||||||
import { parse } from './testlib';
|
import { parse } from './testlib';
|
||||||
@@ -9,10 +9,9 @@ type Checker = (config: CheckConfig) => Promise<{
|
|||||||
status: number,
|
status: number,
|
||||||
score: number,
|
score: number,
|
||||||
message: string,
|
message: string,
|
||||||
code?: number,
|
|
||||||
}>;
|
}>;
|
||||||
|
|
||||||
const checkers: Record<string, Checker> = {
|
const checkers: Record<string, Checker> = new Proxy({
|
||||||
async default(config) {
|
async default(config) {
|
||||||
const { stdout } = await run('/usr/bin/diff -BZ usrout answer', {
|
const { stdout } = await run('/usr/bin/diff -BZ usrout answer', {
|
||||||
copyIn: {
|
copyIn: {
|
||||||
@@ -196,6 +195,11 @@ const checkers: Record<string, Checker> = {
|
|||||||
}
|
}
|
||||||
return parse(stderr, config.score);
|
return parse(stderr, config.score);
|
||||||
},
|
},
|
||||||
};
|
}, {
|
||||||
|
get(self, key) {
|
||||||
|
if (!self[key]) throw new FormatError('Unknown checker type {0}', [key]);
|
||||||
|
return self[key];
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
export = checkers;
|
export = checkers;
|
||||||
@@ -1,11 +1,13 @@
|
|||||||
import { LangConfig } from '@hydrooj/utils/lib/lang';
|
import { LangConfig } from '@hydrooj/utils/lib/lang';
|
||||||
import { STATUS } from '@hydrooj/utils/lib/status';
|
import { STATUS } from '@hydrooj/utils/lib/status';
|
||||||
import { CompileError } from './error';
|
import { findFileSync } from '@hydrooj/utils/lib/utils';
|
||||||
|
import checkers from './checkers';
|
||||||
|
import { CompileError, FormatError } from './error';
|
||||||
import { Execute } from './interface';
|
import { Execute } from './interface';
|
||||||
import { CopyInFile, del, run } from './sandbox';
|
import { CopyInFile, del, run } from './sandbox';
|
||||||
import { compilerText } from './utils';
|
import { compilerText } from './utils';
|
||||||
|
|
||||||
export = async function compile(
|
export default async function compile(
|
||||||
lang: LangConfig, code: CopyInFile, copyIn: Record<string, CopyInFile> = {}, next?: Function,
|
lang: LangConfig, code: CopyInFile, copyIn: Record<string, CopyInFile> = {}, next?: Function,
|
||||||
): Promise<Execute> {
|
): Promise<Execute> {
|
||||||
const target = lang.target || 'foo';
|
const target = lang.target || 'foo';
|
||||||
@@ -24,7 +26,7 @@ export = async function compile(
|
|||||||
);
|
);
|
||||||
if (status !== STATUS.STATUS_ACCEPTED) throw new CompileError({ status, stdout, stderr });
|
if (status !== STATUS.STATUS_ACCEPTED) throw new CompileError({ status, stdout, stderr });
|
||||||
if (!fileIds[target]) throw new CompileError({ stderr: 'Executable file not found.' });
|
if (!fileIds[target]) throw new CompileError({ stderr: 'Executable file not found.' });
|
||||||
if (next) next({ compilerText: compilerText(stdout, stderr) });
|
next?.({ compilerText: compilerText(stdout, stderr) });
|
||||||
return {
|
return {
|
||||||
execute,
|
execute,
|
||||||
copyIn: { ...copyIn, [target]: { fileId: fileIds[target] } },
|
copyIn: { ...copyIn, [target]: { fileId: fileIds[target] } },
|
||||||
@@ -38,4 +40,25 @@ export = async function compile(
|
|||||||
clean: () => Promise.resolve(null),
|
clean: () => Promise.resolve(null),
|
||||||
time,
|
time,
|
||||||
};
|
};
|
||||||
};
|
}
|
||||||
|
|
||||||
|
const testlibSrc = findFileSync('@hydrooj/hydrojudge/vendor/testlib/testlib.h');
|
||||||
|
|
||||||
|
export async function compileChecker(getLang: Function, checkerType: string, checker: string, copyIn: any): Promise<Execute> {
|
||||||
|
if (['default', 'strict'].includes(checkerType)) {
|
||||||
|
return { execute: '', copyIn: {}, clean: () => Promise.resolve(null) };
|
||||||
|
}
|
||||||
|
if (!checkers[checkerType]) throw new FormatError('Unknown checker type {0}.', [checkerType]);
|
||||||
|
if (checkerType === 'testlib') copyIn['testlib.h'] = { src: testlibSrc };
|
||||||
|
const s = checker.replace('@', '.').split('.');
|
||||||
|
let lang;
|
||||||
|
let langId = s.pop();
|
||||||
|
while (s.length) {
|
||||||
|
lang = getLang(langId, false);
|
||||||
|
if (lang) break;
|
||||||
|
langId = `${s.pop()}.${langId}`;
|
||||||
|
}
|
||||||
|
if (!lang) throw new FormatError('Unknown checker language.');
|
||||||
|
// TODO cache compiled checker
|
||||||
|
return await compile(lang, { src: checker }, copyIn);
|
||||||
|
}
|
||||||
@@ -9,7 +9,6 @@ export interface Execute {
|
|||||||
|
|
||||||
export interface CheckConfig {
|
export interface CheckConfig {
|
||||||
execute: string;
|
execute: string;
|
||||||
checker_type: string;
|
|
||||||
input: CopyInFile;
|
input: CopyInFile;
|
||||||
output: CopyInFile;
|
output: CopyInFile;
|
||||||
user_stdout: CopyInFile;
|
user_stdout: CopyInFile;
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { basename } from 'path';
|
import { basename } from 'path';
|
||||||
import { STATUS } from '@hydrooj/utils/lib/status';
|
import { STATUS } from '@hydrooj/utils/lib/status';
|
||||||
import { check, compileChecker } from '../check';
|
import checkers from '../checkers';
|
||||||
import compile from '../compile';
|
import compile, { compileChecker } from '../compile';
|
||||||
import { runFlow } from '../flow';
|
import { runFlow } from '../flow';
|
||||||
import { Logger } from '../log';
|
import { Logger } from '../log';
|
||||||
import { CmdFile, del, run } from '../sandbox';
|
import { CmdFile, del, run } from '../sandbox';
|
||||||
@@ -48,18 +48,17 @@ function judgeCase(c: NormalizedCase, sid: string) {
|
|||||||
} else if (memory_usage_kb > c.memory * 1024) {
|
} else if (memory_usage_kb > c.memory * 1024) {
|
||||||
status = STATUS.STATUS_MEMORY_LIMIT_EXCEEDED;
|
status = STATUS.STATUS_MEMORY_LIMIT_EXCEEDED;
|
||||||
} else {
|
} else {
|
||||||
[status, score, message] = await check({
|
({ status, score, message } = await checkers[ctx.config.checker_type]({
|
||||||
execute: ctx.checker.execute,
|
execute: ctx.checker.execute,
|
||||||
copyIn: ctx.checker.copyIn || {},
|
copyIn: ctx.checker.copyIn || {},
|
||||||
input: { src: c.input },
|
input: { src: c.input },
|
||||||
output: { src: c.output },
|
output: { src: c.output },
|
||||||
user_stdout: stdout,
|
user_stdout: stdout,
|
||||||
user_stderr: stderr,
|
user_stderr: stderr,
|
||||||
checker_type: ctx.config.checker_type,
|
|
||||||
score: c.score,
|
score: c.score,
|
||||||
detail: ctx.config.detail ?? true,
|
detail: ctx.config.detail ?? true,
|
||||||
env: { ...ctx.env, HYDRO_TESTCASE: c.id.toString() },
|
env: { ...ctx.env, HYDRO_TESTCASE: c.id.toString() },
|
||||||
});
|
}));
|
||||||
}
|
}
|
||||||
} else if (status === STATUS.STATUS_RUNTIME_ERROR && code) {
|
} else if (status === STATUS.STATUS_RUNTIME_ERROR && code) {
|
||||||
if (code < 32) message = signals[code];
|
if (code < 32) message = signals[code];
|
||||||
|
|||||||
@@ -1,7 +1,8 @@
|
|||||||
import { basename } from 'path';
|
import { basename } from 'path';
|
||||||
import { readFile } from 'fs-extra';
|
import { readFile } from 'fs-extra';
|
||||||
import { STATUS } from '@hydrooj/utils/lib/status';
|
import { STATUS } from '@hydrooj/utils/lib/status';
|
||||||
import { check, compileChecker } from '../check';
|
import checkers from '../checkers';
|
||||||
|
import { compileChecker } from '../compile';
|
||||||
import { runFlow } from '../flow';
|
import { runFlow } from '../flow';
|
||||||
import { del, run } from '../sandbox';
|
import { del, run } from '../sandbox';
|
||||||
import { NormalizedCase } from '../utils';
|
import { NormalizedCase } from '../utils';
|
||||||
@@ -47,18 +48,17 @@ function judgeCase(c: NormalizedCase, sid: string) {
|
|||||||
fileIds.push(...Object.values(res.fileIds));
|
fileIds.push(...Object.values(res.fileIds));
|
||||||
}
|
}
|
||||||
if (status === STATUS.STATUS_ACCEPTED) {
|
if (status === STATUS.STATUS_ACCEPTED) {
|
||||||
[status, score, message] = await check({
|
({ status, score, message } = await checkers[ctx.config.checker_type]({
|
||||||
execute: ctx.checker.execute,
|
execute: ctx.checker.execute,
|
||||||
copyIn: ctx.checker.copyIn || {},
|
copyIn: ctx.checker.copyIn || {},
|
||||||
input: { src: c.input },
|
input: { src: c.input },
|
||||||
output: { src: c.output },
|
output: { src: c.output },
|
||||||
user_stdout: file,
|
user_stdout: file,
|
||||||
user_stderr: { content: '' },
|
user_stderr: { content: '' },
|
||||||
checker_type: ctx.config.checker_type,
|
|
||||||
score: c.score,
|
score: c.score,
|
||||||
detail: ctx.config.detail ?? true,
|
detail: ctx.config.detail ?? true,
|
||||||
env: { ...ctx.env, HYDRO_TESTCASE: c.id.toString() },
|
env: { ...ctx.env, HYDRO_TESTCASE: c.id.toString() },
|
||||||
});
|
}));
|
||||||
}
|
}
|
||||||
await Promise.all(fileIds.map(del)).catch(() => { /* Ignore file doesn't exist */ });
|
await Promise.all(fileIds.map(del)).catch(() => { /* Ignore file doesn't exist */ });
|
||||||
ctxSubtask.score = Score[ctxSubtask.subtask.type](ctxSubtask.score, score);
|
ctxSubtask.score = Score[ctxSubtask.subtask.type](ctxSubtask.score, score);
|
||||||
|
|||||||
Reference in new issue
Block a user