judge: remove check() function

This commit is contained in:
undefined committed 2022-09-06 13:02:46 +08:00
1 parent 1c6cdfc6ff
commit 805c8e4cd3
6 files changed
+43 -53

No files matched your search

-35
View File
@@ -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);
}
+8 -4
View File
@@ -1,6 +1,6 @@
/* eslint-disable no-template-curly-in-string */
import { STATUS } from '@hydrooj/utils/lib/status';
import { SystemError } from './error';
import { FormatError, SystemError } from './error';
import { CheckConfig } from './interface';
import { run } from './sandbox';
import { parse } from './testlib';
@@ -9,10 +9,9 @@ type Checker = (config: CheckConfig) => Promise<{
status: number,
score: number,
message: string,
code?: number,
}>;
const checkers: Record<string, Checker> = {
const checkers: Record<string, Checker> = new Proxy({
async default(config) {
const { stdout } = await run('/usr/bin/diff -BZ usrout answer', {
copyIn: {
@@ -196,6 +195,11 @@ const checkers: Record<string, Checker> = {
}
return parse(stderr, config.score);
},
};
}, {
get(self, key) {
if (!self[key]) throw new FormatError('Unknown checker type {0}', [key]);
return self[key];
},
});
export = checkers;
+27 -4
View File
@@ -1,11 +1,13 @@
import { LangConfig } from '@hydrooj/utils/lib/lang';
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 { CopyInFile, del, run } from './sandbox';
import { compilerText } from './utils';
export = async function compile(
export default async function compile(
lang: LangConfig, code: CopyInFile, copyIn: Record<string, CopyInFile> = {}, next?: Function,
): Promise<Execute> {
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 (!fileIds[target]) throw new CompileError({ stderr: 'Executable file not found.' });
if (next) next({ compilerText: compilerText(stdout, stderr) });
next?.({ compilerText: compilerText(stdout, stderr) });
return {
execute,
copyIn: { ...copyIn, [target]: { fileId: fileIds[target] } },
@@ -38,4 +40,25 @@ export = async function compile(
clean: () => Promise.resolve(null),
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);
}
-1
View File
@@ -9,7 +9,6 @@ export interface Execute {
export interface CheckConfig {
execute: string;
checker_type: string;
input: CopyInFile;
output: CopyInFile;
user_stdout: CopyInFile;
+4 -5
View File
@@ -1,7 +1,7 @@
import { basename } from 'path';
import { STATUS } from '@hydrooj/utils/lib/status';
import { check, compileChecker } from '../check';
import compile from '../compile';
import checkers from '../checkers';
import compile, { compileChecker } from '../compile';
import { runFlow } from '../flow';
import { Logger } from '../log';
import { CmdFile, del, run } from '../sandbox';
@@ -48,18 +48,17 @@ function judgeCase(c: NormalizedCase, sid: string) {
} else if (memory_usage_kb > c.memory * 1024) {
status = STATUS.STATUS_MEMORY_LIMIT_EXCEEDED;
} else {
[status, score, message] = await check({
({ status, score, message } = await checkers[ctx.config.checker_type]({
execute: ctx.checker.execute,
copyIn: ctx.checker.copyIn || {},
input: { src: c.input },
output: { src: c.output },
user_stdout: stdout,
user_stderr: stderr,
checker_type: ctx.config.checker_type,
score: c.score,
detail: ctx.config.detail ?? true,
env: { ...ctx.env, HYDRO_TESTCASE: c.id.toString() },
});
}));
}
} else if (status === STATUS.STATUS_RUNTIME_ERROR && code) {
if (code < 32) message = signals[code];
@@ -1,7 +1,8 @@
import { basename } from 'path';
import { readFile } from 'fs-extra';
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 { del, run } from '../sandbox';
import { NormalizedCase } from '../utils';
@@ -47,18 +48,17 @@ function judgeCase(c: NormalizedCase, sid: string) {
fileIds.push(...Object.values(res.fileIds));
}
if (status === STATUS.STATUS_ACCEPTED) {
[status, score, message] = await check({
({ status, score, message } = await checkers[ctx.config.checker_type]({
execute: ctx.checker.execute,
copyIn: ctx.checker.copyIn || {},
input: { src: c.input },
output: { src: c.output },
user_stdout: file,
user_stderr: { content: '' },
checker_type: ctx.config.checker_type,
score: c.score,
detail: ctx.config.detail ?? true,
env: { ...ctx.env, HYDRO_TESTCASE: c.id.toString() },
});
}));
}
await Promise.all(fileIds.map(del)).catch(() => { /* Ignore file doesn't exist */ });
ctxSubtask.score = Score[ctxSubtask.subtask.type](ctxSubtask.score, score);