diff --git a/packages/hydrojudge/package.json b/packages/hydrojudge/package.json index 998ae9079..52297e21e 100644 --- a/packages/hydrojudge/package.json +++ b/packages/hydrojudge/package.json @@ -1,7 +1,7 @@ { "name": "@hydrooj/hydrojudge", "bin": "bin/hydrojudge.js", - "version": "2.4.19", + "version": "2.5.0", "os": [ "linux" ], diff --git a/packages/hydrojudge/src/cases.ts b/packages/hydrojudge/src/cases.ts index 91534d8ac..c93cb6237 100644 --- a/packages/hydrojudge/src/cases.ts +++ b/packages/hydrojudge/src/cases.ts @@ -88,8 +88,8 @@ async function read0(folder: string, files: string[], checkFile, cfg) { const config = { count: 0, subtasks: [{ - time_limit_ms: parseTimeMS(cfg.time || '1s'), - memory_limit_mb: parseMemoryMB(cfg.memory || '256m'), + time: parseTimeMS(cfg.time || '1s'), + memory: parseMemoryMB(cfg.memory || '256m'), type: 'sum', cases: [], score: Math.floor(100 / cases.length), @@ -105,8 +105,8 @@ async function read0(folder: string, files: string[], checkFile, cfg) { } if (extra < cases.length) { config.subtasks.push({ - time_limit_ms: parseTimeMS(cfg.time || '1s'), - memory_limit_mb: parseMemoryMB(cfg.memory || '256m'), + time: parseTimeMS(cfg.time || '1s'), + memory: parseMemoryMB(cfg.memory || '256m'), type: 'sum', cases: [], score: Math.floor(100 / cases.length) + 1, @@ -134,8 +134,8 @@ async function read1(folder: string, files: string[], checkFile, cfg) { if (fs.existsSync(path.resolve(folder, c.output))) { if (!subtask[REG.subtask(data)]) { subtask[REG.subtask(data)] = [{ - time_limit_ms: parseTimeMS(cfg.time || '1s'), - memory_limit_mb: parseMemoryMB(cfg.memory || '256m'), + time: parseTimeMS(cfg.time || '1s'), + memory: parseMemoryMB(cfg.memory || '256m'), type: 'min', cases: [c], }]; @@ -199,7 +199,7 @@ function isValidConfig(config) { if (config.count > (getConfig('testcases_max') || 100)) { throw new FormatError('Too many testcases. Cancelled.'); } - const total_time = sum(config.subtasks.map((subtask) => subtask.time_limit_ms * subtask.cases.length)); + const total_time = sum(config.subtasks.map((subtask) => subtask.time * subtask.cases.length)); if (total_time > (getConfig('total_time_limit') || 60) * 1000) { throw new FormatError('Total time limit longer than {0}s. Cancelled.', [+getConfig('total_time_limit') || 60]); } diff --git a/packages/hydrojudge/src/judge/default.ts b/packages/hydrojudge/src/judge/default.ts index 7fbdf154d..3e4a6b2c0 100644 --- a/packages/hydrojudge/src/judge/default.ts +++ b/packages/hydrojudge/src/judge/default.ts @@ -50,8 +50,8 @@ function judgeCase(c, sid) { stderr, copyIn, copyOut, - time_limit_ms: ctxSubtask.subtask.time_limit_ms * ctx.execute.time, - memory_limit_mb: ctxSubtask.subtask.memory_limit_mb, + time: ctxSubtask.subtask.time * ctx.execute.time, + memory: ctxSubtask.subtask.memory, }, ); const { code, time_usage_ms, memory_usage_kb } = res; @@ -62,9 +62,9 @@ function judgeCase(c, sid) { let message: any = ''; let score = 0; if (status === STATUS.STATUS_ACCEPTED) { - if (time_usage_ms > ctxSubtask.subtask.time_limit_ms * ctx.execute.time) { + if (time_usage_ms > ctxSubtask.subtask.time * ctx.execute.time) { status = STATUS.STATUS_TIME_LIMIT_EXCEEDED; - } else if (memory_usage_kb > ctxSubtask.subtask.memory_limit_mb * 1024) { + } else if (memory_usage_kb > ctxSubtask.subtask.memory * 1024) { status = STATUS.STATUS_MEMORY_LIMIT_EXCEEDED; } else { [status, score, message] = await check({ diff --git a/packages/hydrojudge/src/judge/hack.ts b/packages/hydrojudge/src/judge/hack.ts index 8b9e56330..8e81be8dc 100644 --- a/packages/hydrojudge/src/judge/hack.ts +++ b/packages/hydrojudge/src/judge/hack.ts @@ -77,8 +77,8 @@ export const judge = async (ctx) => { stderr, copyIn: execute.copyIn, copyOut, - time_limit_ms: 1000, - memory_limit_mb: 512, + time: 1000, + memory: 512, }, ); const { code, time_usage_ms, memory_usage_kb } = res; diff --git a/packages/hydrojudge/src/judge/interactive.ts b/packages/hydrojudge/src/judge/interactive.ts index 008658acd..47711f894 100644 --- a/packages/hydrojudge/src/judge/interactive.ts +++ b/packages/hydrojudge/src/judge/interactive.ts @@ -24,21 +24,21 @@ function judgeCase(c) { { execute: ctx.executeUser.execute.replace(/\$\{name\}/g, 'code'), copyIn: ctx.executeUser.copyIn, - time_limit_ms: ctxSubtask.subtask.time_limit_ms, - memory_limit_mb: ctxSubtask.subtask.memory_limit_mb, + time: ctxSubtask.subtask.time, + memory: ctxSubtask.subtask.memory, }, { execute: `${ctx.executeInteractor.execute.replace(/\$\{name\}/g, 'interactor')} /w/in /w/tout`, copyIn: ctx.executeInteractor.copyIn, - time_limit_ms: ctxSubtask.subtask.time_limit_ms * 2, - memory_limit_mb: ctxSubtask.subtask.memory_limit_mb * 2, + time: ctxSubtask.subtask.time * 2, + memory: ctxSubtask.subtask.memory * 2, }, ]); let status; let score = 0; let message: any = ''; - if (time_usage_ms > ctxSubtask.subtask.time_limit_ms) { + if (time_usage_ms > ctxSubtask.subtask.time) { status = STATUS.STATUS_TIME_LIMIT_EXCEEDED; - } else if (memory_usage_kb > ctxSubtask.subtask.memory_limit_mb * 1024) { + } else if (memory_usage_kb > ctxSubtask.subtask.memory * 1024) { status = STATUS.STATUS_MEMORY_LIMIT_EXCEEDED; } else if (code) { status = STATUS.STATUS_RUNTIME_ERROR; diff --git a/packages/hydrojudge/src/judge/run.ts b/packages/hydrojudge/src/judge/run.ts index 6cd04efd6..f80fd4f3e 100644 --- a/packages/hydrojudge/src/judge/run.ts +++ b/packages/hydrojudge/src/judge/run.ts @@ -69,8 +69,8 @@ export const judge = async (ctx) => { stderr, copyIn, copyOut, - time_limit_ms: parseTimeMS(ctx.config.time || '1s'), - memory_limit_mb: parseMemoryMB(ctx.config.memory || '128m'), + time: parseTimeMS(ctx.config.time || '1s'), + memory: parseMemoryMB(ctx.config.memory || '128m'), }, ); const { code, time_usage_ms, memory_usage_kb } = res; diff --git a/packages/hydrojudge/src/sandbox.ts b/packages/hydrojudge/src/sandbox.ts index 64a2e1674..7da948604 100644 --- a/packages/hydrojudge/src/sandbox.ts +++ b/packages/hydrojudge/src/sandbox.ts @@ -25,8 +25,8 @@ const statusMap = { function proc({ execute = '', - time_limit_ms = 16000, - memory_limit_mb = 1024, + time = 16000, + memory = 1024, process_limit = 32, stdin = '', copyIn = {}, copyOut = [], copyOutCached = [], } = {}) { @@ -39,9 +39,9 @@ function proc({ { name: 'stdout', max: 1024 * 1024 * size }, { name: 'stderr', max: 1024 * 1024 * size }, ], - cpuLimit: time_limit_ms * 1000 * 1000, - realCpuLimit: time_limit_ms * 3000 * 1000, - memoryLimit: memory_limit_mb * 1024 * 1024, + cpuLimit: time * 1000 * 1000, + realCpuLimit: time * 3000 * 1000, + memoryLimit: memory * 1024 * 1024, procLimit: process_limit, copyIn, copyOut, @@ -58,7 +58,7 @@ async function adaptResult(result, params) { files: result.files, code: result.exitStatus, }; - if (ret.time_usage_ms >= (params.time_limit_ms || 16000)) { + if (ret.time_usage_ms >= (params.time || 16000)) { ret.status = STATUS.STATUS_TIME_LIMIT_EXCEEDED; } ret.files = result.files || {}; diff --git a/packages/hydrooj/package.json b/packages/hydrooj/package.json index 95d3427f1..43ad1ba17 100644 --- a/packages/hydrooj/package.json +++ b/packages/hydrooj/package.json @@ -1,6 +1,6 @@ { "name": "hydrooj", - "version": "2.21.19", + "version": "2.22.0", "bin": "bin/hydrooj.js", "main": "dist/loader.js", "typings": "dist/loader.d.ts", diff --git a/packages/hydrooj/src/handler/problem.ts b/packages/hydrooj/src/handler/problem.ts index 50584f275..da6d501cc 100644 --- a/packages/hydrooj/src/handler/problem.ts +++ b/packages/hydrooj/src/handler/problem.ts @@ -11,6 +11,7 @@ import { import paginate from '../lib/paginate'; import { isPid } from '../lib/validator'; import difficultyAlgorithm from '../lib/difficulty'; +import { parseConfig } from '../lib/testdataConfig'; import * as system from '../model/system'; import problem from '../model/problem'; import record from '../model/record'; @@ -189,6 +190,12 @@ export class ProblemDetailHandler extends ProblemHandler { // e.g. ![img](a.jpg) will navigate to ![img](./pid/file/a.jpg) this.response.body.pdoc.content = this.response.body.pdoc.content .replace(/\(file:\/\//g, `(./${this.pdoc.docId}/file/`); + // Get time and memory limit + try { + this.response.body.pdoc.config = await parseConfig(this.pdoc.config); + } catch (e) { + this.response.body.pdoc.config = `Cannot parse: ${e.message}`; + } } @param('pid', Types.UnsignedInt) diff --git a/packages/hydrooj/src/interface.ts b/packages/hydrooj/src/interface.ts index 713a90040..ae6e19ff2 100644 --- a/packages/hydrooj/src/interface.ts +++ b/packages/hydrooj/src/interface.ts @@ -189,7 +189,6 @@ declare module './model/problem' { data: FileInfo[], additional_file: FileInfo[], hidden: boolean, - acMsg?: string, html?: boolean, difficulty?: number, /** @deprecated */ diff --git a/packages/hydrooj/src/lib/testdataConfig.ts b/packages/hydrooj/src/lib/testdataConfig.ts index 226d96b99..7d16e4d4b 100644 --- a/packages/hydrooj/src/lib/testdataConfig.ts +++ b/packages/hydrooj/src/lib/testdataConfig.ts @@ -21,24 +21,26 @@ export async function parseConfig(config: string | ProblemConfig) { let cfg: ProblemConfig = {}; if (typeof config === 'string') { // TODO should validate here? - cfg = readYamlCases(load(config) as Record) as ProblemConfig; + cfg = await readYamlCases(load(config) as Record) as ProblemConfig; } else cfg = config; - if (cfg.cases) { - for (const c of cfg.cases) { - result.memoryMax = Math.max(result.memoryMax, c.memory); - result.memoryMin = Math.min(result.memoryMin, c.memory); - result.timeMax = Math.max(result.timeMax, c.time); - result.timeMin = Math.min(result.timeMin, c.time); - result.count++; - } - } else if (cfg.subtasks) { + if (cfg.subtasks.length) { for (const subtask of cfg.subtasks) { result.memoryMax = Math.max(result.memoryMax, subtask.memory); result.memoryMin = Math.min(result.memoryMin, subtask.memory); result.timeMax = Math.max(result.timeMax, subtask.time); result.timeMin = Math.min(result.timeMin, subtask.time); } + } else if (cfg.time || cfg.memory) { + if (cfg.time) result.timeMax = result.timeMin = cfg.time as unknown as number; + if (cfg.memory) result.memoryMax = result.memoryMin = cfg.memory as unknown as number; + } + if (result.memoryMax < result.memoryMin) { + result.memoryMax = result.memoryMin = 256; + } + if (result.timeMax < result.timeMin) { + result.timeMax = result.timeMin = 1000; } + return result; } global.Hydro.lib.testdataConfig = { parseConfig }; diff --git a/packages/hydrooj/src/model/problem.ts b/packages/hydrooj/src/model/problem.ts index 60e9239f8..0645752c2 100644 --- a/packages/hydrooj/src/model/problem.ts +++ b/packages/hydrooj/src/model/problem.ts @@ -28,8 +28,7 @@ export class ProblemModel { static PROJECTION_PUBLIC: Field[] = [ ...ProblemModel.PROJECTION_LIST, - 'content', 'html', 'data', 'config', 'acMsg', - 'additional_file', + 'content', 'html', 'data', 'config', 'additional_file', ]; static extend(getter: Getter) { @@ -258,7 +257,6 @@ ProblemModel.extend((docId, pid) => ({ additional_file: [], hidden: true, config: '', - acMsg: '', difficulty: 0, })); diff --git a/packages/migrate-vijos/package.json b/packages/migrate-vijos/package.json index f29552922..5db7ddb9b 100644 --- a/packages/migrate-vijos/package.json +++ b/packages/migrate-vijos/package.json @@ -1,6 +1,6 @@ { "name": "@hydrooj/migrate-vijos", - "version": "1.4.0", + "version": "1.4.1", "main": "package.json", "repository": "git@github.com:hydro-dev/Hydro.git", "author": "undefined ", diff --git a/packages/migrate-vijos/script.ts b/packages/migrate-vijos/script.ts index cef6a06ce..ed64baff6 100644 --- a/packages/migrate-vijos/script.ts +++ b/packages/migrate-vijos/script.ts @@ -74,7 +74,6 @@ const tasks = { return res; }, }, - ac_msg: 'acMsg', parent_doc_id: { field: 'parentId', processer: (parentId, doc) => { diff --git a/packages/ui-default/package.json b/packages/ui-default/package.json index 44a6391bd..0e7fcb90a 100644 --- a/packages/ui-default/package.json +++ b/packages/ui-default/package.json @@ -1,6 +1,6 @@ { "name": "@hydrooj/ui-default", - "version": "4.5.14", + "version": "4.5.15", "author": "undefined ", "license": "AGPL-3.0", "main": "hydro.js", diff --git a/packages/ui-default/templates/partials/problem_sidebar_normal.html b/packages/ui-default/templates/partials/problem_sidebar_normal.html index c6b72068a..a8c21f984 100644 --- a/packages/ui-default/templates/partials/problem_sidebar_normal.html +++ b/packages/ui-default/templates/partials/problem_sidebar_normal.html @@ -126,10 +126,6 @@

{{ _('Information') }}

{% else %} {{ _('(None)') }} {% endif %} - {% if pdoc['acMsg'] and pdoc['psdoc']['status'] == STATUS.STATUS_ACCEPTED %} -
{{ _('AC Message') }}
-
{{ pdoc['acMsg'] }}
- {% endif %} {% endif %} {% endif %} diff --git a/packages/ui-default/templates/problem_detail.html b/packages/ui-default/templates/problem_detail.html index e2218d718..7130a9538 100644 --- a/packages/ui-default/templates/problem_detail.html +++ b/packages/ui-default/templates/problem_detail.html @@ -25,7 +25,27 @@
-

{{ pdoc.title }}

+

+ {%- if rdoc -%} + + + {{ rdoc.score }} + + {%- endif %} + {{ pdoc.title }} +

+
+
+ {% if rdoc %} +

+ + + {{ rdoc.score }} + +

+ {% endif %} + {{ _('Time Limit') }}: {{ pdoc.config.timeMax if pdoc.config.timeMax == pdoc.config.timeMin else pdoc.config.timeMin+'~'+pdoc.config.timeMax }}ms + {{ _('Memory Limit') }}: {{ pdoc.config.memoryMax if pdoc.config.memoryMax == pdoc.config.memoryMin else pdoc.config.memoryMin+'~'+pdoc.config.memoryMax }}MiB
{% if tdoc %} diff --git a/packages/utils/lib/cases.ts b/packages/utils/lib/cases.ts index b13089d4c..431ef2f1d 100644 --- a/packages/utils/lib/cases.ts +++ b/packages/utils/lib/cases.ts @@ -35,8 +35,8 @@ export default async function readYamlCases(cfg: Record = {}, check } else if (cfg.cases) { config.subtasks = [{ score: parseInt(cfg.score, 10) || Math.floor(100 / cfg.cases.length), - time_limit_ms: parseTimeMS(cfg.time || '1s'), - memory_limit_mb: parseMemoryMB(cfg.memory || '512m'), + time: parseTimeMS(cfg.time || '1s'), + memory: parseMemoryMB(cfg.memory || '256m'), cases: [], type: 'sum', }]; @@ -63,11 +63,13 @@ export default async function readYamlCases(cfg: Record = {}, check score: parseInt(subtask.score, 10), if: subtask.if || [], cases, - time_limit_ms: parseTimeMS(subtask.time || cfg.time || '1s'), - memory_limit_mb: parseMemoryMB(subtask.memory || cfg.memory || '512m'), + time: parseTimeMS(subtask.time || cfg.time || '1s'), + memory: parseMemoryMB(subtask.memory || cfg.memory || '256m'), }); } } + if (cfg.time) config.time = parseTimeMS(cfg.time); + if (cfg.memory) config.memory = parseMemoryMB(cfg.memory); if (config.type === 'submit_answer' && !cfg.outputs) throw new Error('outputs config not found'); return Object.assign(cfg, config); } @@ -83,7 +85,7 @@ export function convertIniConfig(ini: string) { cases: [{ input: `input/${input.toLowerCase()}`, output: `output/${output.toLowerCase()}` }], score: parseInt(score, 10), time: `${time}s`, - memory: '512m', + memory: '256m', }; if (!Number.isNaN(parseInt(memory, 10))) cur.memory = `${Math.floor(parseInt(memory, 10) / 1024)}m`; res.subtasks.push(cur); diff --git a/packages/utils/lib/utils.ts b/packages/utils/lib/utils.ts index 64f8a9b4a..197133026 100644 --- a/packages/utils/lib/utils.ts +++ b/packages/utils/lib/utils.ts @@ -161,13 +161,15 @@ const TIME_UNITS = { '': 1000, m: 1, u: 0.001 }; const MEMORY_RE = /^([0-9]+(?:\.[0-9]*)?)([kmg])b?$/i; const MEMORY_UNITS = { k: 1 / 1024, m: 1, g: 1024 }; -export function parseTimeMS(str: string) { +export function parseTimeMS(str: string | number) { + if (typeof str === 'number') return str; const match = TIME_RE.exec(str); if (!match) throw new Error(`${str} error parsing time`); return Math.floor(parseFloat(match[1]) * TIME_UNITS[match[2]]); } -export function parseMemoryMB(str: string) { +export function parseMemoryMB(str: string | number) { + if (typeof str === 'number') return str; const match = MEMORY_RE.exec(str); if (!match) throw new Error(`${str} error parsing memory`); return Math.ceil(parseFloat(match[1]) * MEMORY_UNITS[match[2]]); diff --git a/packages/utils/package.json b/packages/utils/package.json index 38c12437c..5142b2fef 100644 --- a/packages/utils/package.json +++ b/packages/utils/package.json @@ -1,6 +1,6 @@ { "name": "@hydrooj/utils", - "version": "1.0.1", + "version": "1.0.2", "description": "hydrooj utils", "main": "package.json", "repository": "https://github.com/hydro-dev/Hydro.git",