judge: use basename instead of parseFilename

This commit is contained in:
undefined committed 2022-09-06 13:02:46 +08:00
1 parent 7bf2e73561
commit e9787f2ba5
8 files changed
+26 -53

No files matched your search

+8 -6
View File
@@ -14,7 +14,7 @@ interface Task {
function judgeSubtask(subtask: NormalizedSubtask, sid: string, judgeCase: Task['judgeCase']) { function judgeSubtask(subtask: NormalizedSubtask, sid: string, judgeCase: Task['judgeCase']) {
return async (ctx: Context) => { return async (ctx: Context) => {
subtask.type = subtask.type || 'min'; subtask.type ||= 'min';
const ctxSubtask = { const ctxSubtask = {
subtask, subtask,
status: 0, status: 0,
@@ -27,9 +27,9 @@ function judgeSubtask(subtask: NormalizedSubtask, sid: string, judgeCase: Task['
const runner = judgeCase(subtask.cases[cid], subtask.id.toString() ?? sid); const runner = judgeCase(subtask.cases[cid], subtask.id.toString() ?? sid);
cases.push(ctx.queue.add(async () => { cases.push(ctx.queue.add(async () => {
if (ctx.errored if (ctx.errored
|| (ctxSubtask.subtask.type === 'min' && ctxSubtask.score === 0) || (subtask.type === 'min' && ctxSubtask.score === 0)
|| (ctxSubtask.subtask.type === 'max' && ctxSubtask.score === ctxSubtask.subtask.score) || (subtask.type === 'max' && ctxSubtask.score === subtask.score)
|| ((ctxSubtask.subtask.if || []).filter((i) => ctx.failed[i]).length) || (subtask.if || []).filter((i) => ctx.failed[i]).length
) { ) {
ctx.next({ ctx.next({
case: { case: {
@@ -46,10 +46,12 @@ function judgeSubtask(subtask: NormalizedSubtask, sid: string, judgeCase: Task['
} else await runner(ctx, ctxSubtask, runner); } else await runner(ctx, ctxSubtask, runner);
})); }));
} }
await Promise.all(cases).catch((e) => { try {
await Promise.all(cases);
} catch (e) {
ctx.errored = true; ctx.errored = true;
throw e; throw e;
}); }
ctx.total_status = Math.max(ctx.total_status, ctxSubtask.status); ctx.total_status = Math.max(ctx.total_status, ctxSubtask.status);
return ctxSubtask.score; return ctxSubtask.score;
}; };
+3 -3
View File
@@ -9,7 +9,6 @@ import { Logger } from 'hydrooj/src/logger';
import * as setting from 'hydrooj/src/model/setting'; import * as setting from 'hydrooj/src/model/setting';
import * as system from 'hydrooj/src/model/system'; import * as system from 'hydrooj/src/model/system';
import task from 'hydrooj/src/model/task'; import task from 'hydrooj/src/model/task';
import * as monitor from 'hydrooj/src/service/monitor';
import storage from 'hydrooj/src/service/storage'; import storage from 'hydrooj/src/service/storage';
import { processTestdata } from '../cases'; import { processTestdata } from '../cases';
import { getConfig } from '../config'; import { getConfig } from '../config';
@@ -77,6 +76,7 @@ const session = {
export async function postInit() { export async function postInit() {
if (system.get('hydrojudge.disable')) return; if (system.get('hydrojudge.disable')) return;
task.consume({ type: 'judge' }, (t) => (new JudgeTask(session, t)).handle().catch(logger.error)); const handle = (t) => (new JudgeTask(session, t)).handle().catch(logger.error);
task.consume({ type: 'judge', priority: { $gt: -50 } }, (t) => (new JudgeTask(session, t)).handle().catch(logger.error)); task.consume({ type: 'judge' }, handle);
task.consume({ type: 'judge', priority: { $gt: -50 } }, handle);
} }
+3 -2
View File
@@ -1,3 +1,4 @@
import { basename } from 'path';
import { STATUS } from '@hydrooj/utils/lib/status'; import { STATUS } from '@hydrooj/utils/lib/status';
import { check, compileChecker } from '../check'; import { check, compileChecker } from '../check';
import compile from '../compile'; import compile from '../compile';
@@ -5,7 +6,7 @@ import { runFlow } from '../flow';
import { Logger } from '../log'; import { Logger } from '../log';
import { CmdFile, del, run } from '../sandbox'; import { CmdFile, del, run } from '../sandbox';
import signals from '../signals'; import signals from '../signals';
import { NormalizedCase, parseFilename } from '../utils'; import { NormalizedCase } from '../utils';
import { Context, ContextSubTask } from './interface'; import { Context, ContextSubTask } from './interface';
const Score = { const Score = {
@@ -136,7 +137,7 @@ export const judge = async (ctx: Context) => await runFlow(ctx, {
{ {
user_code: ctx.code, user_code: ctx.code,
...Object.fromEntries( ...Object.fromEntries(
(ctx.config.judge_extra_files || []).map((i) => [parseFilename(i), { src: i }]), (ctx.config.judge_extra_files || []).map((i) => [basename(i), { src: i }]),
), ),
}, },
), ),
+5 -6
View File
@@ -1,12 +1,11 @@
import { basename } from 'path';
import { STATUS } from '@hydrooj/utils/lib/status'; import { STATUS } from '@hydrooj/utils/lib/status';
import compile from '../compile'; import compile from '../compile';
import { runFlow } from '../flow'; import { runFlow } from '../flow';
import { runPiped } from '../sandbox'; import { runPiped } from '../sandbox';
import signals from '../signals'; import signals from '../signals';
import { parse } from '../testlib'; import { parse } from '../testlib';
import { import { findFileSync, NormalizedCase } from '../utils';
findFileSync, NormalizedCase, parseFilename,
} from '../utils';
import { Context, ContextSubTask } from './interface'; import { Context, ContextSubTask } from './interface';
const testlibSrc = findFileSync('@hydrooj/hydrojudge/vendor/testlib/testlib.h'); const testlibSrc = findFileSync('@hydrooj/hydrojudge/vendor/testlib/testlib.h');
@@ -81,7 +80,7 @@ export const judge = async (ctx: Context) => await runFlow(ctx, {
(() => { (() => {
const copyIn = {}; const copyIn = {};
for (const file of ctx.config.user_extra_files) { for (const file of ctx.config.user_extra_files) {
copyIn[parseFilename(file)] = { src: file }; copyIn[basename(file)] = { src: file };
} }
return compile(ctx.session.getLang(ctx.lang), ctx.code, copyIn, ctx.next); return compile(ctx.session.getLang(ctx.lang), ctx.code, copyIn, ctx.next);
})(), })(),
@@ -91,10 +90,10 @@ export const judge = async (ctx: Context) => await runFlow(ctx, {
user_code: ctx.code, user_code: ctx.code,
}; };
for (const file of ctx.config.judge_extra_files) { for (const file of ctx.config.judge_extra_files) {
copyIn[parseFilename(file)] = { src: file }; copyIn[basename(file)] = { src: file };
} }
return compile( return compile(
ctx.session.getLang(parseFilename(ctx.config.interactor).split('.')[1].replace('@', '.')), ctx.session.getLang(basename(ctx.config.interactor).split('.')[1].replace('@', '.')),
{ src: ctx.config.interactor }, { src: ctx.config.interactor },
copyIn, copyIn,
); );
@@ -23,31 +23,6 @@ export interface RuntimeContext {
executeUser?: Execute; executeUser?: Execute;
} }
export interface Config {
type: string;
subType?: string;
time: string;
memory: string;
subtasks?: NormalizedSubtask[];
count?: number;
checker_type?: string;
detail?: boolean;
filename?: string;
judge_extra_files: string[];
user_extra_files: string[];
template?: Record<string, [string, string]>;
checker?: string;
validator?: string;
std?: string;
hack?: string;
interactor?: string;
answers?: Record<string, [answer: string | string[], score: number]>;
}
export interface ContextSubTask { export interface ContextSubTask {
subtask: NormalizedSubtask; subtask: NormalizedSubtask;
score: number; score: number;
@@ -1,9 +1,10 @@
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 { check, compileChecker } from '../check';
import { runFlow } from '../flow'; import { runFlow } from '../flow';
import { del, run } from '../sandbox'; import { del, run } from '../sandbox';
import { NormalizedCase, parseFilename } from '../utils'; import { NormalizedCase } from '../utils';
import { Context, ContextSubTask } from './interface'; import { Context, ContextSubTask } from './interface';
const Score = { const Score = {
@@ -80,18 +81,16 @@ function judgeCase(c: NormalizedCase, sid: string) {
export const judge = async (ctx: Context) => { export const judge = async (ctx: Context) => {
await runFlow(ctx, { await runFlow(ctx, {
compile: async () => { compile: async () => {
ctx.checker = await (() => {
const copyIn = { user_code: ctx.code }; const copyIn = { user_code: ctx.code };
for (const file of ctx.config.judge_extra_files) { for (const file of ctx.config.judge_extra_files) {
copyIn[parseFilename(file)] = { src: file }; copyIn[basename(file)] = { src: file };
} }
return compileChecker( ctx.checker = await compileChecker(
ctx.session.getLang, ctx.session.getLang,
ctx.config.checker_type, ctx.config.checker_type,
ctx.config.checker, ctx.config.checker,
copyIn, copyIn,
); );
})();
ctx.clean.push(ctx.checker.clean); ctx.clean.push(ctx.checker.clean);
}, },
judgeCase, judgeCase,
+2
View File
@@ -1,3 +1,4 @@
import assert from 'assert';
import child from 'child_process'; import child from 'child_process';
import os from 'os'; import os from 'os';
import fs from 'fs-extra'; import fs from 'fs-extra';
@@ -12,6 +13,7 @@ if (uid !== 0) log.warn('Not running by root. tmpfs disabled.');
export function mount(path: string, size = '32m') { export function mount(path: string, size = '32m') {
fs.ensureDirSync(path); fs.ensureDirSync(path);
assert(size.match(/^\d+[kmg]b?$/gi));
if (linux && uid === 0) child.execSync(`mount tmpfs ${path} -t tmpfs -o size=${size}`); if (linux && uid === 0) child.execSync(`mount tmpfs ${path} -t tmpfs -o size=${size}`);
} }
+1 -6
View File
@@ -8,11 +8,6 @@ const EMPTY_STR = /^[ \r\n\t]*$/i;
export const cmd = parse; export const cmd = parse;
export function parseFilename(filePath: string) {
const t = filePath.split('/');
return t[t.length - 1];
}
export namespace Lock { export namespace Lock {
const data = {}; const data = {};
@@ -34,7 +29,7 @@ export function compilerText(stdout: string, stderr: string) {
return ret.join('\n'); return ret.join('\n');
} }
export function restrictFile(p: string) { function restrictFile(p: string) {
if (!p) return '/'; if (!p) return '/';
if (p[0] === '/') p = ''; if (p[0] === '/') p = '';
return p.replace(/\.\./gmi, ''); return p.replace(/\.\./gmi, '');