From a2004056ac5e7bbf57835dc26188866a3b533452 Mon Sep 17 00:00:00 2001 From: undefined Date: Fri, 25 Feb 2022 12:09:32 +0800 Subject: [PATCH] core: update judge config --- packages/hydrojudge/package.json | 2 +- packages/hydrojudge/src/cases.ts | 4 +- packages/hydrojudge/src/check.ts | 12 +- packages/hydrojudge/src/checkers.ts | 10 +- packages/hydrojudge/src/compile.ts | 6 +- packages/hydrojudge/src/hosts/hydro.ts | 11 +- packages/hydrojudge/src/hosts/index.ts | 4 +- packages/hydrojudge/src/hosts/vj4.ts | 2 + packages/hydrojudge/src/interface.ts | 1 + packages/hydrojudge/src/judge/default.ts | 19 +-- packages/hydrojudge/src/judge/hack.ts | 132 ------------------- packages/hydrojudge/src/judge/index.ts | 3 +- packages/hydrojudge/src/judge/interactive.ts | 7 +- packages/hydrojudge/src/judge/run.ts | 44 +++---- packages/hydrojudge/src/sandbox.ts | 4 +- packages/hydrojudge/src/service.ts | 5 +- packages/hydrojudge/src/sysinfo.ts | 6 +- packages/hydrojudge/src/utils.ts | 20 +-- packages/hydrooj/package.json | 2 +- packages/hydrooj/setting.yaml | 46 +++---- packages/hydrooj/src/model/record.ts | 1 + packages/hydrooj/src/upgrade.ts | 4 + 22 files changed, 100 insertions(+), 245 deletions(-) delete mode 100644 packages/hydrojudge/src/judge/hack.ts diff --git a/packages/hydrojudge/package.json b/packages/hydrojudge/package.json index 3f7b947ec..aa5c0ff05 100644 --- a/packages/hydrojudge/package.json +++ b/packages/hydrojudge/package.json @@ -1,7 +1,7 @@ { "name": "@hydrooj/hydrojudge", "bin": "bin/hydrojudge.js", - "version": "2.13.8", + "version": "2.14.0", "main": "package.json", "author": "undefined ", "repository": "https://github.com/hydro-dev/Hydro.git", diff --git a/packages/hydrojudge/src/cases.ts b/packages/hydrojudge/src/cases.ts index 223fa2350..3383a496f 100644 --- a/packages/hydrojudge/src/cases.ts +++ b/packages/hydrojudge/src/cases.ts @@ -155,7 +155,7 @@ async function read1(folder: string, files: string[], checkFile, cfg, rst) { return config; } -async function readAutoCases(folder, { next }, cfg, rst) { +async function readAutoCases(folder: string, { next }, cfg, rst) { const config = { checker_type: 'default', count: 0, @@ -177,7 +177,7 @@ async function readAutoCases(folder, { next }, cfg, rst) { let result = await read0(folder, files, checkFile, cfg); if (!result.count) result = await read1(folder, files, checkFile, cfg, rst); Object.assign(config, result); - next({ message: { message: 'Found {0} testcases.', params: [config.count] } }); + if (cfg.isSelfSubmission) next({ message: { message: 'Found {0} testcases.', params: [config.count] } }); } catch (e) { throw new SystemError('Cannot parse testdata.', [e.message, ...e.params]); } diff --git a/packages/hydrojudge/src/check.ts b/packages/hydrojudge/src/check.ts index 14460cd60..8223d7d9f 100644 --- a/packages/hydrojudge/src/check.ts +++ b/packages/hydrojudge/src/check.ts @@ -4,7 +4,6 @@ import checkers from './checkers'; import compile from './compile'; import { SystemError } from './error'; import { CheckConfig, Execute } from './interface'; -import { parseFilename } from './utils'; const testlibSrc = findFileSync('@hydrooj/hydrojudge/vendor/testlib/testlib.h'); @@ -21,6 +20,15 @@ export async function compileChecker(getLang: Function, checkerType: string, che if (!checkers[checkerType]) throw new SystemError('Unknown checker type {0}.', [checkerType]); if (checkerType === 'testlib') copyIn['testlib.h'] = { src: testlibSrc }; const file = await fs.readFile(checker); + 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(getLang(parseFilename(checker).split('.')[1].replace('@', '.')), file.toString(), 'checker', copyIn); + return await compile(lang, file.toString(), copyIn); } diff --git a/packages/hydrojudge/src/checkers.ts b/packages/hydrojudge/src/checkers.ts index 999557d8b..2f39675d4 100644 --- a/packages/hydrojudge/src/checkers.ts +++ b/packages/hydrojudge/src/checkers.ts @@ -79,7 +79,7 @@ const checkers: Record = { * exit code:返回判断结果 */ async hustoj(config) { - const { code, stdout } = await run('${dir}/checker input answer usrout', { + const { code, stdout } = await run(`${config.execute} input answer usrout`, { copyIn: { usrout: config.user_stdout, answer: config.output, @@ -104,7 +104,7 @@ const checkers: Record = { * argv[6]:输出错误报告的文件 */ async lemon(config) { - const { files } = await run(`\${dir}/checker input usrout answer ${config.score} score message`, { + const { files } = await run(`${config.execute} input usrout answer ${config.score} score message`, { copyIn: { usrout: config.user_stdout, answer: config.output, @@ -131,7 +131,7 @@ const checkers: Record = { * exit code:返回判断结果 */ async qduoj(config) { - const { status, stdout } = await run('${dir}/checker input usrout', { + const { status, stdout } = await run(`${config.execute} input usrout`, { copyIn: { usrout: config.user_stdout, input: config.input, @@ -157,7 +157,7 @@ const checkers: Record = { */ async syzoj(config) { // eslint-disable-next-line prefer-const - let { status, stdout, stderr } = await run('${dir}/checker', { + let { status, stdout, stderr } = await run(config.execute, { copyIn: { input: config.input, user_out: config.user_stdout, @@ -173,7 +173,7 @@ const checkers: Record = { }, async testlib(config) { - const { stderr, status } = await run('${dir}/checker ${dir}/in ${dir}/user_out ${dir}/answer', { + const { stderr, status } = await run(`${config.execute} /w/in /w/user_out /w/answer`, { copyIn: { in: config.input, user_out: config.user_stdout, diff --git a/packages/hydrojudge/src/compile.ts b/packages/hydrojudge/src/compile.ts index 7fa45905b..44b69544a 100644 --- a/packages/hydrojudge/src/compile.ts +++ b/packages/hydrojudge/src/compile.ts @@ -7,15 +7,15 @@ import { CopyInFile } from './sandbox/interface'; import { compilerText } from './utils'; export = async function compile( - lang: LangConfig, code: string, target: string, copyIn: Record = {}, next?: Function, + lang: LangConfig, code: string, copyIn: Record = {}, next?: Function, ): Promise { - target = lang.target || target; + const target = lang.target || 'foo'; copyIn[lang.code_file] = { content: code }; if (lang.compile) { const { status, stdout, stderr, fileIds, } = await run( - lang.compile.replace(/\$\{name\}/g, target), + lang.compile, { copyIn, copyOutCached: [target] }, ); if (status !== STATUS.STATUS_ACCEPTED) throw new CompileError({ status, stdout, stderr }); diff --git a/packages/hydrojudge/src/hosts/hydro.ts b/packages/hydrojudge/src/hosts/hydro.ts index bdfaa4216..f5b5beefd 100644 --- a/packages/hydrojudge/src/hosts/hydro.ts +++ b/packages/hydrojudge/src/hosts/hydro.ts @@ -112,7 +112,11 @@ class JudgeTask { this.stat.read_cases = new Date(); this.config = await readCases( this.folder, - { detail: this.session.config.detail, ...this.config }, + { + detail: this.session.config.detail, + isSelfSubmission: this.config.problemOwner === this.request.uid, + ...this.config, + }, { next: this.next, key: md5(`${this.source}/${getConfig('secret')}`) }, ); this.stat.judge = new Date(); @@ -243,10 +247,11 @@ export default class Hydro { return filePath; } - getLang(name: string) { + getLang(name: string, doThrow = true) { if (this.language[name]) return this.language[name]; if (name === 'cpp' && this.language.cc) return this.language.cc; - throw new SystemError('Unsupported language {0}', [name]); + if (doThrow) throw new SystemError('Unsupported language {0}', [name]); + return null; } async consume(queue: Queue) { diff --git a/packages/hydrojudge/src/hosts/index.ts b/packages/hydrojudge/src/hosts/index.ts index d2b90b0a3..43f9f622f 100644 --- a/packages/hydrojudge/src/hosts/index.ts +++ b/packages/hydrojudge/src/hosts/index.ts @@ -1,2 +1,2 @@ -export { default as vj4, default } from './vj4'; -export { default as hydro } from './hydro'; +export { default as vj4 } from './vj4'; +export { default as hydro, default } from './hydro'; diff --git a/packages/hydrojudge/src/hosts/vj4.ts b/packages/hydrojudge/src/hosts/vj4.ts index c82a18b6f..07590d907 100644 --- a/packages/hydrojudge/src/hosts/vj4.ts +++ b/packages/hydrojudge/src/hosts/vj4.ts @@ -1,6 +1,8 @@ export default class VJ4 { constructor() { console.log('新版本不再支持 VJ4。请降级至 hydrojudge@2.5.21 或迁移到 Hydro。'); + console.log('This version of HydroJudge nolonger supports VJ4. Please downgrade to'); + console.log('hydrojudge@2.5.21 or migrate to Hydro.'); console.log('详细文档: https://hydro.js.org/ '); process.exit(1); } diff --git a/packages/hydrojudge/src/interface.ts b/packages/hydrojudge/src/interface.ts index 1a9250cc3..e61f2f148 100644 --- a/packages/hydrojudge/src/interface.ts +++ b/packages/hydrojudge/src/interface.ts @@ -14,6 +14,7 @@ export interface CompileErrorInfo { } export interface CheckConfig { + execute: string; checker_type: string; input: CopyInFile; output: CopyInFile; diff --git a/packages/hydrojudge/src/judge/default.ts b/packages/hydrojudge/src/judge/default.ts index f6ccb41f1..bf33ac86f 100644 --- a/packages/hydrojudge/src/judge/default.ts +++ b/packages/hydrojudge/src/judge/default.ts @@ -41,7 +41,7 @@ function judgeCase(c: Case, sid: string) { const copyOutCached = filename ? [`${filename}.out?`] : []; const stdin = filename ? null : c.input; const res = await run( - ctx.execute.execute.replace(/\$\{name\}/g, 'code'), + ctx.execute.execute, { stdin, copyIn, @@ -67,6 +67,7 @@ function judgeCase(c: Case, sid: string) { status = STATUS.STATUS_MEMORY_LIMIT_EXCEEDED; } else { [status, score, message] = await check({ + execute: ctx.checker.execute, copyIn: ctx.checker.copyIn || {}, input: { src: c.input }, output: { src: c.output }, @@ -142,15 +143,15 @@ export const judge = async (ctx: Context) => { } else throw new CompileError('Language not supported by provided templates'); } [ctx.execute, ctx.checker] = await Promise.all([ + compile( + ctx.getLang(ctx.lang), ctx.code, + Object.fromEntries( + (ctx.config.user_extra_files || []).map((i) => [i.split('/').pop(), { src: i }]), + ), + ctx.next, + ), (() => { - const copyIn = {}; - for (const file of ctx.config.user_extra_files) { - copyIn[parseFilename(file)] = { src: file }; - } - return compile(ctx.getLang(ctx.lang), ctx.code, 'code', copyIn, ctx.next); - })(), - (() => { - if (!ctx.config.checker_type || ['default', 'strict'].includes(ctx.config.checker_type)) { + if (['default', 'strict'].includes(ctx.config.checker_type || 'default')) { return { execute: '', copyIn: {}, clean: () => Promise.resolve(null) }; } const copyIn = {}; diff --git a/packages/hydrojudge/src/judge/hack.ts b/packages/hydrojudge/src/judge/hack.ts deleted file mode 100644 index 680f72abf..000000000 --- a/packages/hydrojudge/src/judge/hack.ts +++ /dev/null @@ -1,132 +0,0 @@ -// Not implemented -import path from 'path'; -import fs from 'fs-extra'; -import { STATUS } from '@hydrooj/utils/lib/status'; -import { check, compileChecker } from '../check'; -import compile from '../compile'; -import { CompileError } from '../error'; -import { run } from '../sandbox'; -import signals from '../signals'; -import { copyInDir, parseFilename } from '../utils'; -import { Context } from './interface'; - -export const judge = async (ctx: Context) => { - if (ctx.config.template) { - if (ctx.config.template[ctx.lang]) { - const tpl = ctx.config.template[ctx.lang]; - ctx.code = tpl[0] + ctx.code + tpl[1]; - } else throw new CompileError('Language not supported by provided templates'); - } - ctx.next({ status: STATUS.STATUS_COMPILING }); - if (!ctx.config.validator || !ctx.config.std) throw new CompileError('config.validator or config.std is missing.'); - const [execute, executeValidator, executeStd, executeChecker] = await Promise.all([ - // UserProgram - (() => { - const copyIn = {}; - for (const file of ctx.config.user_extra_files) { - copyIn[parseFilename(file)] = { src: file }; - } - return compile(ctx.getLang(ctx.lang), ctx.code, 'code', copyIn, ctx.next); - })(), - // Validator - (async () => { - const copyIn = {}; - for (const file of ctx.config.judge_extra_files) { - copyIn[parseFilename(file)] = { src: file }; - } - const file = await fs.readFile(ctx.config.validator); - return await compile(ctx.getLang(parseFilename(ctx.config.validator).split('.')[1]), file.toString(), 'validator', copyIn); - })(), - // Std - (async () => { - const copyIn = {}; - for (const file of ctx.config.user_extra_files) { - copyIn[parseFilename(file)] = { src: file }; - } - const file = await fs.readFile(ctx.config.std); - return await compile(ctx.getLang(parseFilename(ctx.config.std).split('.')[1]), file.toString(), 'std', copyIn); - })(), - // Checker - (() => { - if (!ctx.config.checker_type || ctx.config.checker_type === 'default') return null; - const copyIn = {}; - for (const file of ctx.config.judge_extra_files) { - copyIn[parseFilename(file)] = { src: file }; - } - return compileChecker( - ctx.getLang, - ctx.config.checker_type, - ctx.config.checker, - copyIn, - ); - })(), - ]); - ctx.clean.push(execute.clean, executeValidator.clean, executeStd.clean, executeChecker.clean); - ctx.next({ status: STATUS.STATUS_JUDGING, progress: 0 }); - const { filename } = ctx.config; - const input = path.resolve(ctx.tmpdir, 'input'); - await fs.writeFile(input, ctx.config.hack); - if (filename) execute.copyIn[`${filename}.in`] = { src: input }; - const copyOut = filename ? [`${filename}.out`] : []; - const stdin = filename ? null : input; - const stdout = path.resolve(ctx.tmpdir, 'user.out'); - const stderr = path.resolve(ctx.tmpdir, 'user.err'); - const res = await run( - ctx.execute.execute.replace(/\$\{name\}/g, 'code'), - { - stdin, - stdout: filename ? null : stdout, - stderr, - copyIn: execute.copyIn, - copyOut, - time: 1000, - memory: 512, - }, - ); - const { code, time_usage_ms, memory_usage_kb } = res; - let { status } = res; - if (res.files[`${filename}.out`] || !fs.existsSync(stdout)) { - fs.writeFileSync(stdout, res.files[`${filename}.out`] || ''); - } - let message = ''; - if (status === STATUS.STATUS_ACCEPTED) { - if (time_usage_ms > 1000) { - status = STATUS.STATUS_TIME_LIMIT_EXCEEDED; - } else if (memory_usage_kb > 512 * 1024) { - status = STATUS.STATUS_MEMORY_LIMIT_EXCEEDED; - } else { - [status, , message] = await check({ - copyIn: copyInDir(path.resolve(ctx.tmpdir, 'checker')), - input: { src: input }, - output: { src: stdout }, - user_stdout: { src: stdout }, - user_stderr: { src: stderr }, - checker_type: ctx.config.checker_type, - score: 100, - detail: ctx.config.detail, - }); - } - } else if (status === STATUS.STATUS_RUNTIME_ERROR && code) { - if (code < 32) message = signals[code]; - else message = `您的程序返回了 ${code}.`; - } - ctx.next({ - status: STATUS.STATUS_JUDGING, - case: { - status, - score: 0, - time_ms: time_usage_ms, - memory_kb: memory_usage_kb, - message, - }, - }); - - ctx.stat.done = new Date(); - ctx.next({ message: JSON.stringify(ctx.stat) }); - ctx.end({ - status, - score: ctx.total_score, - time_ms: Math.floor(ctx.total_time_usage_ms * 1000000) / 1000000, - memory_kb: ctx.total_memory_usage_kb, - }); -}; diff --git a/packages/hydrojudge/src/judge/index.ts b/packages/hydrojudge/src/judge/index.ts index 2d0af9edd..53ef04a18 100644 --- a/packages/hydrojudge/src/judge/index.ts +++ b/packages/hydrojudge/src/judge/index.ts @@ -1,10 +1,9 @@ import * as def from './default'; -import * as hack from './hack'; import * as interactive from './interactive'; import { Context } from './interface'; import * as run from './run'; import * as submit_answer from './submit_answer'; export = { - default: def, interactive, run, submit_answer, hack, objective: submit_answer, + default: def, interactive, run, submit_answer, objective: submit_answer, } as Record }>; diff --git a/packages/hydrojudge/src/judge/interactive.ts b/packages/hydrojudge/src/judge/interactive.ts index 81f63ecc8..f34bad513 100644 --- a/packages/hydrojudge/src/judge/interactive.ts +++ b/packages/hydrojudge/src/judge/interactive.ts @@ -24,13 +24,13 @@ function judgeCase(c: Case) { ctx.executeInteractor.copyIn.out = c.output ? { src: c.output } : { content: '' }; const [{ code, time_usage_ms, memory_usage_kb }, resInteractor] = await runPiped( { - execute: ctx.executeUser.execute.replace(/\$\{name\}/g, 'code'), + execute: ctx.executeUser.execute, copyIn: ctx.executeUser.copyIn, time: ctxSubtask.subtask.time * ctx.executeUser.time, memory: ctxSubtask.subtask.memory, }, { - execute: `${ctx.executeInteractor.execute.replace(/\$\{name\}/g, 'interactor')} /w/in /w/tout /w/out`, + execute: `${ctx.executeInteractor.execute} /w/in /w/tout /w/out`, copyIn: ctx.executeInteractor.copyIn, time: ctxSubtask.subtask.time * 2 * ctx.executeInteractor.time, memory: ctxSubtask.subtask.memory * 2, @@ -103,7 +103,7 @@ export const judge = async (ctx: Context) => { for (const file of ctx.config.user_extra_files) { copyIn[parseFilename(file)] = { src: file }; } - return compile(ctx.getLang(ctx.lang), ctx.code, 'code', copyIn, ctx.next); + return compile(ctx.getLang(ctx.lang), ctx.code, copyIn, ctx.next); })(), (() => { const copyIn = { 'testlib.h': { src: testlibSrc } }; @@ -113,7 +113,6 @@ export const judge = async (ctx: Context) => { return compile( ctx.getLang(parseFilename(ctx.config.interactor).split('.')[1].replace('@', '.')), fs.readFileSync(ctx.config.interactor).toString(), - 'interactor', copyIn, ); })(), diff --git a/packages/hydrojudge/src/judge/run.ts b/packages/hydrojudge/src/judge/run.ts index f5bde47ff..a0dd84c6a 100644 --- a/packages/hydrojudge/src/judge/run.ts +++ b/packages/hydrojudge/src/judge/run.ts @@ -8,46 +8,32 @@ import signals from '../signals'; import { compilerText, parseMemoryMB, parseTimeMS } from '../utils'; import { Context } from './interface'; +const failure = (status: number, message?: string) => ({ + status, + score: 0, + time_ms: 0, + memory_kb: 0, + message, +}); + export const judge = async (ctx: Context) => { ctx.stat.judge = new Date(); ctx.next({ status: STATUS.STATUS_COMPILING }); try { - ctx.execute = await compile(ctx.getLang(ctx.lang), ctx.code, 'code', {}, ctx.next); + ctx.execute = await compile(ctx.getLang(ctx.lang), ctx.code, {}, ctx.next); } catch (e) { if (e instanceof CompileError) { ctx.next({ status: STATUS.STATUS_COMPILE_ERROR, - case: { - status: STATUS.STATUS_COMPILE_ERROR, - score: 0, - time_ms: 0, - memory_kb: 0, - message: compilerText(e.stdout, e.stderr), - }, - }); - ctx.end({ - status: STATUS.STATUS_COMPILE_ERROR, - score: 0, - time_ms: 0, - memory_kb: 0, + 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: { - status: STATUS.STATUS_SYSTEM_ERROR, - score: 0, - time_ms: 0, - memory_kb: 0, - message: `${e.message}\n${JSON.stringify(e.params)}`, - }, - }); - ctx.end({ - status: STATUS.STATUS_COMPILE_ERROR, - score: 0, - time_ms: 0, - memory_kb: 0, + case: failure(STATUS.STATUS_SYSTEM_ERROR, `${e.message}\n${JSON.stringify(e.params)}`), }); + ctx.end(failure(STATUS.STATUS_SYSTEM_ERROR)); } return; } @@ -62,7 +48,7 @@ export const judge = async (ctx: Context) => { const stdout = path.resolve(ctx.tmpdir, '0.out'); const stderr = path.resolve(ctx.tmpdir, '0.err'); const res = await run( - ctx.execute.execute.replace(/\$\{name\}/g, 'code'), + ctx.execute.execute, { stdin: filename ? null : stdin, stdout: filename ? null : stdout, @@ -96,7 +82,7 @@ export const judge = async (ctx: Context) => { status, time_ms: time_usage_ms, memory_kb: memory_usage_kb, - message: message.join('\n').substr(0, 102400), + message: message.join('\n').substring(0, 102400), }, }); ctx.stat.done = new Date(); diff --git a/packages/hydrojudge/src/sandbox.ts b/packages/hydrojudge/src/sandbox.ts index 26438c0c2..86d7f1f3f 100644 --- a/packages/hydrojudge/src/sandbox.ts +++ b/packages/hydrojudge/src/sandbox.ts @@ -59,7 +59,7 @@ function checkStringArray(args: ParseEntry[]): args is string[] { } function parseArgs(execute: string): string[] { - const args = cmd(execute.replace(/\$\{dir\}/g, '/w')); + const args = cmd(execute); if (!checkStringArray(args)) { throw new SystemError(`${execute} contains invalid operator`); } @@ -76,7 +76,7 @@ function proc({ env = {}, }: Parameter = {}): Cmd { if (!supportOptional) { - copyOut = (copyOut as string[]).map((i) => (i.endsWith('?') ? i.substr(0, i.length - 1) : i)); + copyOut = copyOut.map((i) => (i.endsWith('?') ? i.substring(0, i.length - 1) : i)); } const size = parseMemoryMB(getConfig('stdio_size')); const rate = getConfig('rate'); diff --git a/packages/hydrojudge/src/service.ts b/packages/hydrojudge/src/service.ts index 87c34e6b1..23fbc2b4f 100644 --- a/packages/hydrojudge/src/service.ts +++ b/packages/hydrojudge/src/service.ts @@ -134,10 +134,11 @@ async function postInit() { }; } - function getLang(lang: string) { + function getLang(lang: string, doThrow = true) { if (setting.langs[lang]) return setting.langs[lang]; if (lang === 'cpp' && setting.langs['cc']) return setting.langs['cc']; - throw new SystemError('Unsupported language {0}.', [lang]); + if (doThrow) throw new SystemError('Unsupported language {0}.', [lang]); + return null; } class JudgeTask { diff --git a/packages/hydrojudge/src/sysinfo.ts b/packages/hydrojudge/src/sysinfo.ts index 90147e180..7169926e3 100644 --- a/packages/hydrojudge/src/sysinfo.ts +++ b/packages/hydrojudge/src/sysinfo.ts @@ -35,10 +35,10 @@ int main(){ }, end: () => { }, getLang: () => ({ - compile: '/usr/bin/g++ -Wall -std=c++14 -o foo.cc foo.cc -lm', - execute: 'foo', + compile: '/usr/bin/g++ -Wall -std=c++14 -o foo foo.cc -lm', + execute: '/w/foo', code_file: 'foo.cc', - highlight: 'cpp astyle-c', + highlight: 'cpp', monaco: 'cpp', display: 'C++', time_limit_rate: 1, diff --git a/packages/hydrojudge/src/utils.ts b/packages/hydrojudge/src/utils.ts index f84378d4d..38050b48e 100644 --- a/packages/hydrojudge/src/utils.ts +++ b/packages/hydrojudge/src/utils.ts @@ -22,7 +22,6 @@ const encrypt = (algorithm: string, content: crypto.BinaryLike) => { return hash.digest('hex'); }; -export const sha1 = (content: string) => encrypt('sha1', content); export const md5 = (content: string) => encrypt('md5', content); export class Queue extends EventEmitter { @@ -69,26 +68,11 @@ export namespace Lock { export function compilerText(stdout: string, stderr: string) { const ret = []; - if (!EMPTY_STR.test(stdout)) ret.push(stdout.substr(0, 1024 * 1024)); - if (!EMPTY_STR.test(stderr)) ret.push(stderr.substr(0, 1024 * 1024)); + if (!EMPTY_STR.test(stdout)) ret.push(stdout.substring(0, 1024 * 1024)); + if (!EMPTY_STR.test(stderr)) ret.push(stderr.substring(0, 1024 * 1024)); return ret.join('\n'); } -export function copyInDir(dir: string) { - const files = {}; - if (fs.existsSync(dir)) { - fs.readdirSync(dir).forEach((f1) => { - const p1 = `${dir}/${f1}`; - if (fs.statSync(p1).isDirectory()) { - fs.readdirSync(p1).forEach((f2) => { - files[`${f1}/${f2}`] = { src: `${dir}/${f1}/${f2}` }; - }); - } else files[f1] = { src: `${dir}/${f1}` }; - }); - } - return files; -} - export function restrictFile(p: string) { if (!p) return '/'; if (p[0] === '/') p = ''; diff --git a/packages/hydrooj/package.json b/packages/hydrooj/package.json index 9893b602b..d4a9df876 100644 --- a/packages/hydrooj/package.json +++ b/packages/hydrooj/package.json @@ -1,6 +1,6 @@ { "name": "hydrooj", - "version": "3.4.31", + "version": "3.5.0", "bin": "bin/hydrooj.js", "main": "src/loader", "module": "src/loader", diff --git a/packages/hydrooj/setting.yaml b/packages/hydrooj/setting.yaml index 14fe0cb69..de133e968 100644 --- a/packages/hydrooj/setting.yaml +++ b/packages/hydrooj/setting.yaml @@ -32,33 +32,33 @@ langs: target: Compiler output file display: Display name c: - compile: /usr/bin/gcc -Wall --std=c99 -o ${name} foo.c -lm - highlight: c astyle-c + compile: /usr/bin/gcc -Wall --std=c99 -o foo foo.c -lm + highlight: c monaco: cpp display: C cc: - compile: /usr/bin/g++ -Wall -std=c++14 -o ${name} foo.cc -lm + compile: /usr/bin/g++ -Wall -std=c++14 -o foo foo.cc -lm code_file: foo.cc - highlight: cpp astyle-c + highlight: cpp monaco: cpp display: C++ cc.std98: - compile: /usr/bin/g++ -Wall -std=c++98 -o ${name} foo.cc -lm + compile: /usr/bin/g++ -Wall -std=c++98 -o foo foo.cc -lm display: C++ 98 cc.std11: - compile: /usr/bin/g++ -Wall -std=c++11 -o ${name} foo.cc -lm + compile: /usr/bin/g++ -Wall -std=c++11 -o foo foo.cc -lm display: C++ 11 cc.std14: display: C++ 14 cc.std17: - compile: /usr/bin/g++ -Wall -std=c++17 -o ${name} foo.cc -lm + compile: /usr/bin/g++ -Wall -std=c++17 -o foo foo.cc -lm display: C++ 17 pas: - compile: /usr/bin/fpc -O2 -o${dir}/${name} foo.pas + compile: /usr/bin/fpc -O2 -o/w/foo foo.pas highlight: pascal display: Pascal java: - compile: /usr/bin/bash -c "javac -d ${dir} -encoding utf8 ./Main.java && jar cvf Main.jar *.class >/dev/null" + compile: /usr/bin/bash -c "javac -d /w -encoding utf8 ./Main.java && jar cvf Main.jar *.class >/dev/null" code_file: Main.java target: Main.jar execute: /usr/bin/java -cp Main.jar Main @@ -67,46 +67,42 @@ langs: monaco: java display: Java py: - compile: /usr/bin/python -c "import py_compile; py_compile.compile('${dir}/foo.py', '${dir}/${name}', doraise=True)" + compile: /usr/bin/python -c "import py_compile; py_compile.compile('/w/foo.py', '/w/foo', doraise=True)" code_file: foo.py - execute: /usr/bin/python ${name} + execute: /usr/bin/python foo highlight: python display: Python py.py2: display: Python 2 py.py3: - compile: /usr/bin/python3 -c "import py_compile; py_compile.compile('${dir}/foo.py', '${dir}/${name}', doraise=True)" - execute: /usr/bin/python3 ${name} + compile: /usr/bin/python3 -c "import py_compile; py_compile.compile('/w/foo.py', '/w/foo', doraise=True)" + execute: /usr/bin/python3 foo display: Python 3 php: execute: /usr/bin/php foo.php display: PHP rs: - compile: /usr/bin/rustc -O -o ${dir}/${name} ${dir}/foo.rs + compile: /usr/bin/rustc -O -o /w/foo /w/foo.rs highlight: rust display: Rust hs: - compile: /usr/bin/ghc -O -outputdir /tmp -o ${name} foo.hs + compile: /usr/bin/ghc -O -outputdir /tmp -o foo foo.hs highlight: haskell display: Haskell js: - execute: /usr/bin/jsc ${dir}/foo.js + execute: /usr/bin/jsc /w/foo.js highlight: javascript display: Javascript (JSC) go: - compile: /usr/bin/go build -o ${name} foo.go + compile: /usr/bin/go build -o foo foo.go display: Golang rb: execute: /usr/bin/ruby foo.rb highlight: ruby display: Ruby cs: - compile: /usr/bin/mcs -optimize+ -out:${dir}/${name} ${dir}/foo.cs - execute: /usr/bin/mono ${name} - highlight: csharp astyle-cs + compile: /usr/bin/mcs -optimize+ -out:/w/foo /w/foo.cs + execute: /usr/bin/mono foo + highlight: csharp monaco: csharp - display: Csharp - jl: - execute: /usr/bin/julia ${dir}/foo.jl - highlight: julia - display: Julia + display: 'C#' diff --git a/packages/hydrooj/src/model/record.ts b/packages/hydrooj/src/model/record.ts index e092a9e80..18ccbb82a 100644 --- a/packages/hydrooj/src/model/record.ts +++ b/packages/hydrooj/src/model/record.ts @@ -72,6 +72,7 @@ class RecordModel { pdoc = await problem.get(pdoc.reference.domainId, pdoc.reference.pid); if (!pdoc) throw new ProblemNotFoundError(rdoc.domainId, rdoc.pid); } + (config as any).problemOwner = pdoc.owner; source = `${pdoc.domainId}/${pdoc.docId}`; data = pdoc.data; if (typeof pdoc.config === 'string') throw new Error(pdoc.config); diff --git a/packages/hydrooj/src/upgrade.ts b/packages/hydrooj/src/upgrade.ts index a859cbfec..d8f6cc006 100644 --- a/packages/hydrooj/src/upgrade.ts +++ b/packages/hydrooj/src/upgrade.ts @@ -683,6 +683,10 @@ const scripts: UpgradeScript[] = [ await TaskModel.deleteMany({ type: 'schedule', subType: 'contest.problemHide' }); return true; }, + async function _59_60() { + const langs = await system.get('hydrooj.langs'); + await system.set('hydrooj.langs', langs.replace(/\$\{dir\}/g, '/w').replace(/\$\{name\}/g, 'foo')); + }, ]; export default scripts;