From ce692352079f0dec91e86d0833897a986d11f904 Mon Sep 17 00:00:00 2001 From: undefined Date: Tue, 1 Sep 2020 13:35:06 +0800 Subject: [PATCH] =?UTF-8?q?draft:=20=E4=BB=8Efps=E6=96=87=E4=BB=B6?= =?UTF-8?q?=E5=AF=BC=E5=85=A5=E9=A2=98=E7=9B=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/fps-importer/handler.ts | 95 +++++++++++++++++++++++++ packages/fps-importer/package.json | 24 +++++++ packages/fps-importer/tsconfig.json | 19 +++++ packages/hydrojudge/package.json | 2 +- packages/hydrooj/package.json | 4 +- packages/hydrooj/src/handler/problem.ts | 4 +- packages/hydrooj/src/interface.ts | 10 +-- 7 files changed, 149 insertions(+), 9 deletions(-) create mode 100644 packages/fps-importer/handler.ts create mode 100644 packages/fps-importer/package.json create mode 100644 packages/fps-importer/tsconfig.json diff --git a/packages/fps-importer/handler.ts b/packages/fps-importer/handler.ts new file mode 100644 index 000000000..3a037713e --- /dev/null +++ b/packages/fps-importer/handler.ts @@ -0,0 +1,95 @@ +/* eslint-disable no-await-in-loop */ +import path from 'path'; +import os from 'os'; +import fs from 'fs-extra'; +import TurndownService from 'turndown'; +import AdmZip from 'adm-zip'; +import xml2js from 'xml2js'; +import { LocalProblemConfig } from 'hydrooj'; +import { + Route, Handler, param, Types, +} from 'hydrooj/dist/service/server'; +import { PERM } from 'hydrooj/dist/model/builtin'; + +const turndownService = new TurndownService(); + +class FpsProblemImportHandler extends Handler { + async get() { + this.response.template = 'problem_import_fps.html'; + } + + @param('input', Types.String) + async post(domainId: string, input: string) { + const result = await xml2js.parseStringPromise(input); + const problem = global.Hydro.model.problem; + for (const p of result.fps.item) { + const testdata = new AdmZip(); + const content = []; + if (p.description) { + content.push( + this.translate('problem.import.problem_description'), + p.description.map((i) => turndownService.turndown(i)).join('\n'), + ); + } + if (p.input) { + content.push( + this.translate('problem.import.input_format'), + p.input.map((i) => turndownService.turndown(i)).join('\n'), + ); + } + if (p.output) { + content.push( + this.translate('problem.import.output_format'), + p.output.map((i) => turndownService.turndown(i)).join('\n'), + ); + } + if (p.sample_input) { + content.push( + this.translate('problem.import.sample_input'), + // eslint-disable-next-line prefer-template + p.sample_input.map((i: string) => ('```\n' + i + '\n```')).join('\n'), + ); + } + if (p.sample_output) { + content.push( + this.translate('problem.import.sample_output'), + // eslint-disable-next-line prefer-template + p.sample_output.map((i: string) => ('```\n' + i + '\n```')).join('\n'), + ); + } + if (p.hint) { + content.push( + this.translate('problem.import.hint'), + p.hint.map((i) => turndownService.turndown(i)).join('\n'), + ); + } + const config: LocalProblemConfig = { + time: p.time_limit[0]._ + p.time_limit[0].$.unit, + memory: p.memory_limit[0]._ + p.memory_limit[0].$.unit, + }; + const pid = await problem.add(domainId, null, p.title.join(' '), content.join('\n'), this.user._id, p.source, []); + testdata.addFile('config.yaml', Buffer.from(`time:${config.time}\nmemory:${config.memory}`)); + for (let i = 0; i < p.test_input.length; i++) { + testdata.addFile(`${i + 1}.in`, Buffer.from(p.test_input[i])); + testdata.addFile(`${i + 1}.out`, Buffer.from(p.test_output[i])); + } + const file = path.resolve(os.tmpdir(), 'hydro', `${Math.random()}.zip`); + await new Promise((resolve, reject) => { + testdata.writeZip(file, (err) => { + if (err) reject(err); + resolve(); + }); + }); + await problem.setTestdata(domainId, pid, file); + await fs.unlink(file); + } + this.response.body = { count: result.fps.item.length }; + this.response.redirect = this.url('problem_main'); + } +} + +export async function apply() { + Route('problem_import_fps', '/problem/import/fps', FpsProblemImportHandler, PERM.PERM_CREATE_PROBLEM); +} + +global.Hydro.handler.fpsImport = apply; diff --git a/packages/fps-importer/package.json b/packages/fps-importer/package.json new file mode 100644 index 000000000..d8f87ad6a --- /dev/null +++ b/packages/fps-importer/package.json @@ -0,0 +1,24 @@ +{ + "name": "@hydrooj/fps-importer", + "version": "1.0.0", + "description": "Import FPS problems", + "main": "package.json", + "repository": "https://github.com/hydro-dev/Hydro.git", + "author": "undefined ", + "license": "AGPL-3.0-only", + "dependencies": { + "adm-zip": "^0.4.16", + "fs-extra": "^9.0.1", + "hydrooj": "^2.12.22", + "turndown": "^6.0.0", + "xml2js": "^0.4.23" + }, + "devDependencies": { + "@types/turndown": "^5.0.0", + "@types/xml2js": "^0.4.5" + }, + "scripts": { + "build": "tsc", + "lint": "eslint . --ext ts --fix" + } +} diff --git a/packages/fps-importer/tsconfig.json b/packages/fps-importer/tsconfig.json new file mode 100644 index 000000000..aa7d73857 --- /dev/null +++ b/packages/fps-importer/tsconfig.json @@ -0,0 +1,19 @@ +{ + "compilerOptions": { + "target": "es2019", + "module": "commonjs", + "esModuleInterop": true, + "moduleResolution": "node", + "declaration": true, + "sourceMap": true, + "composite": true, + "strictBindCallApply": true, + "experimentalDecorators": true, + "outDir": ".", + "rootDir": "." + }, + "include": [ + "*.ts" + ], + "exclude": [] +} \ No newline at end of file diff --git a/packages/hydrojudge/package.json b/packages/hydrojudge/package.json index b63e938ab..4035ab04f 100644 --- a/packages/hydrojudge/package.json +++ b/packages/hydrojudge/package.json @@ -17,7 +17,7 @@ "shell-quote": "^1.7.2", "systeminformation": "^4.26.10" }, - "license": "GPL-3.0-only", + "license": "AGPL-3.0-only", "devDependencies": { "@types/bson": "^4.0.2", "@types/fs-extra": "^9.0.1", diff --git a/packages/hydrooj/package.json b/packages/hydrooj/package.json index 2f979cf09..1e32f53d0 100644 --- a/packages/hydrooj/package.json +++ b/packages/hydrooj/package.json @@ -1,12 +1,12 @@ { "name": "hydrooj", - "version": "2.12.22", + "version": "2.12.23", "bin": "bin/hydrooj.js", "main": "dist/loader.js", "typings": "dist/loader.d.ts", "repository": "https://github.com/hydro-dev/Hydro.git", "author": "masnn", - "license": "GPL-3.0-only", + "license": "AGPL-3.0-only", "engines": { "node": ">=10.10" }, diff --git a/packages/hydrooj/src/handler/problem.ts b/packages/hydrooj/src/handler/problem.ts index 29bfe1899..a00dd5f60 100644 --- a/packages/hydrooj/src/handler/problem.ts +++ b/packages/hydrooj/src/handler/problem.ts @@ -270,8 +270,8 @@ class ProblemPretestHandler extends ProblemDetailHandler { lang, code, true, { input, - time: 1000, - memory: 256, + time: '1s', + memory: '256m', }, ); const rdoc = await record.get(domainId, rid); diff --git a/packages/hydrooj/src/interface.ts b/packages/hydrooj/src/interface.ts index d37ce127e..3d48274ff 100644 --- a/packages/hydrooj/src/interface.ts +++ b/packages/hydrooj/src/interface.ts @@ -101,8 +101,10 @@ export interface SubtaskConfig { export interface LocalProblemConfig { type?: LocalProblemType, score?: number, - time?: number, - memory?: number, + /** ms */ + time?: string, + /** Megabytes */ + memory?: string, checker_type?: string, checker?: string, interactor?: string, @@ -167,8 +169,8 @@ export interface TestCase { } export interface PretestConfig { - time?: number, - memory?: number, + time?: string, + memory?: string, input: string, }