core: 添加buildContent方法

This commit is contained in:
undefined committed 2020-11-20 19:40:13 +08:00
1 parent f81d7daa54
commit 19ebf5e9a8
5 files changed
+116 -92

No files matched your search

+11 -46
View File
@@ -11,7 +11,7 @@ import { LocalProblemConfig } from 'hydrooj';
import { import {
Route, Handler, param, Types, Route, Handler, param, Types,
} from 'hydrooj/dist/service/server'; } from 'hydrooj/dist/service/server';
import { streamToBuffer } from 'hydrooj/dist/utils'; import { buildContent, streamToBuffer } from 'hydrooj/dist/utils';
import { ProblemAdd } from 'hydrooj/dist/lib/ui'; import { ProblemAdd } from 'hydrooj/dist/lib/ui';
import * as file from 'hydrooj/dist/model/file'; import * as file from 'hydrooj/dist/model/file';
import * as solution from 'hydrooj/dist/model/solution'; import * as solution from 'hydrooj/dist/model/solution';
@@ -60,57 +60,22 @@ class FpsProblemImportHandler extends Handler {
const problem = global.Hydro.model.problem; const problem = global.Hydro.model.problem;
for (const p of result.fps.item) { for (const p of result.fps.item) {
const testdata = new AdmZip(); const testdata = new AdmZip();
const content = []; const content = buildContent({
if (p.description) { description: p.description,
content.push( input: p.input,
`<h2>${this.translate('Description')}</h2>`, output: p.output,
...p.description, samples: p.sample_input
); ? p.sample_input.map((si: string, i: number) => [si, p.sample_output[i]])
} : [],
if (p.input) { hint: p.hint,
content.push( }, 'html', this.translate.bind(this));
`<h2>${this.translate('Input Format')}</h2>`,
...p.input,
);
}
if (p.output) {
content.push(
`<h2>${this.translate('Output Format')}</h2>`,
...p.output,
);
}
if (p.sample_input) {
if (p.sample_input.length === 1) {
content.push(
`<h2>${this.translate('Sample Input')}</h2>`,
`<pre><code>${p.sample_input[0]}</code></pre>`,
`<h2>${this.translate('Sample Output')}</h2>`,
`<pre><code>${p.sample_output[0]}</code></pre>`,
);
} else {
for (let i = 0; i < p.sample_input.length; i++) {
content.push(
`<h2>${this.translate('Sample Input')}${i + 1}</h2>`,
`<pre><code>${p.sample_input[i]}</code></pre>`,
`<h2>${this.translate('Sample Output')}${i + 1}</h2>`,
`<pre><code>${p.sample_output[i]}</code></pre>`,
);
}
}
}
if (p.hint) {
content.push(
`<h2>${this.translate('Hint')}</h2>`,
...p.hint,
);
}
const config: LocalProblemConfig = { const config: LocalProblemConfig = {
time: p.time_limit[0]._ + p.time_limit[0].$.unit, time: p.time_limit[0]._ + p.time_limit[0].$.unit,
memory: p.memory_limit[0]._ + p.memory_limit[0].$.unit, memory: p.memory_limit[0]._ + p.memory_limit[0].$.unit,
}; };
const title = decodeHTML(p.title.join(' ')); const title = decodeHTML(p.title.join(' '));
const tags = filter(p.source, (i: string) => i.trim()); const tags = filter(p.source, (i: string) => i.trim());
const pid = await problem.add(domainId, null, title, content.join('\n'), this.user._id, tags, []); const pid = await problem.add(domainId, null, title, content, this.user._id, tags, []);
testdata.addFile('config.yaml', Buffer.from(`time: ${config.time}\nmemory: ${config.memory}`)); testdata.addFile('config.yaml', Buffer.from(`time: ${config.time}\nmemory: ${config.memory}`));
if (p.test_output) { if (p.test_output) {
for (let i = 0; i < p.test_input.length; i++) { for (let i = 0; i < p.test_input.length; i++) {
+1 -1
View File
@@ -1,6 +1,6 @@
{ {
"name": "hydrooj", "name": "hydrooj",
"version": "2.13.52", "version": "2.13.53",
"bin": "bin/hydrooj.js", "bin": "bin/hydrooj.js",
"main": "dist/loader.js", "main": "dist/loader.js",
"typings": "dist/loader.d.ts", "typings": "dist/loader.d.ts",
+68
View File
@@ -201,3 +201,71 @@ export function sleep(timeout: number) {
}, timeout); }, timeout);
}); });
} }
function deepen(modifyString: (source: string) => string) {
function modifyObject<T>(source: T): T {
if (typeof source !== 'object' || !source) return source;
if (Array.isArray(source)) return source.map(modifyObject) as any;
const result = {} as T;
for (const key in source) {
result[modifyString(key)] = modifyObject(source[key]);
}
return result;
}
return function t<T>(source: T): T {
if (typeof source === 'string') {
return modifyString(source) as any;
}
return modifyObject(source);
};
}
export const camelCase = deepen((source) => source.replace(/[_-][a-z]/g, (str) => str.slice(1).toUpperCase()));
export const paramCase = deepen((source) => source.replace(/_/g, '-').replace(/(?<!^)[A-Z]/g, (str) => `-${str.toLowerCase()}`));
export const snakeCase = deepen((source) => source.replace(/-/g, '_').replace(/(?<!^)[A-Z]/g, (str) => `_${str.toLowerCase()}`));
interface ProblemSource {
description?: string,
input?: string,
output?: string,
samples?: [string, string][],
hint?: string,
source?: string,
}
export function buildContent(source: ProblemSource, type: 'markdown' | 'html' = 'markdown', translate?: Function) {
const _ = translate || ((s: string) => s);
return type === 'html'
? [
...source.description ? [`<h2>${_('Description')}</h2>`, source.description] : [],
...source.input ? [`<h2>${_('Input Format')}</h2>`, source.input] : [],
...source.output ? [`<h2>'${_('Output Format')}</h2>`, source.output] : [],
...(source.samples).map((sample, i) => [
`<h2>${_('Sample Input')} ${i + 1}</h2><pre>`,
sample[0],
`</pre><h2>${_('Sample Output')} ${i + 1}</h2><pre>`,
sample[1],
'</pre>',
].join('\n')),
...source.hint ? [`<h2>${_('Hint')}</h2>`, source.hint] : [],
...source.source ? [`<h2>${_('Source')}</h2>`, source.source] : [],
].join('\n')
: [
...source.description ? [`## ${_('Description')}`, source.description] : [],
...source.input ? [`## ${_('Input Format')}`, source.input] : [],
...source.output ? [`## '${_('Output Format')}`, source.output] : [],
...(source.samples).map((sample, i) => [
`## ${_('Sample Input')} ${i + 1}`,
'```',
sample[0],
'```',
`## ${_('Sample Output')} ${i + 1}`,
'```',
sample[1],
'```',
].join('\n')),
...source.hint ? [`## ${_('Hint')}`, source.hint] : [],
...source.source ? [`## ${_('Source')}`, source.source] : [],
].join('\n');
}
+9 -31
View File
@@ -10,7 +10,7 @@ import {
Route, Handler, param, Types, Route, Handler, param, Types,
} from 'hydrooj/dist/service/server'; } from 'hydrooj/dist/service/server';
import { BadRequestError } from 'hydrooj/dist/error'; import { BadRequestError } from 'hydrooj/dist/error';
import { streamToBuffer } from 'hydrooj/dist/utils'; import { buildContent, streamToBuffer } from 'hydrooj/dist/utils';
import { ProblemAdd } from 'hydrooj/dist/lib/ui'; import { ProblemAdd } from 'hydrooj/dist/lib/ui';
import * as file from 'hydrooj/dist/model/file'; import * as file from 'hydrooj/dist/model/file';
import * as problem from 'hydrooj/dist/model/problem'; import * as problem from 'hydrooj/dist/model/problem';
@@ -31,36 +31,14 @@ class ImportQduojHandler extends Handler {
for (const folder of folders) { for (const folder of folders) {
const buf = await fs.readFile(path.join(tmp, folder, 'problem.json')); const buf = await fs.readFile(path.join(tmp, folder, 'problem.json'));
const pdoc = JSON.parse(buf.toString()); const pdoc = JSON.parse(buf.toString());
const content = [ const content = buildContent({
...pdoc.description?.value description: pdoc.description?.value,
? [ input: pdoc.input_description?.value,
'<h2>Description</h2>', output: pdoc.output_description?.value,
pdoc.description.value, samples: pdoc.samples.map((i) => [i.input, i.output]),
] : [], hint: pdoc.hint?.value,
...pdoc.input_description?.value source: pdoc.source?.value,
? [ }, 'html');
'<h2>Input Description</h2>',
pdoc.input_description.value,
] : [],
...pdoc.output_description?.value
? [
'<h2>Output Description</h2>',
pdoc.output_description.value,
] : [],
...(pdoc.samples as any[]).map((sample, i) => [
`<h2>Sample Input ${i + 1}</h2><pre>`,
sample.input,
`</pre><h2>Sample Output ${i + 1}</h2><pre>`,
sample.output,
'</pre>',
].join('\n')),
...pdoc.hint?.value
? [
'<h2>Hint</h2>',
pdoc.hint.value,
] : [],
...pdoc.source ? ['<h2>Source</h2>', pdoc.source] : [],
].join('\n');
const pid = await problem.add(domainId, pdoc.display_id, pdoc.title, content, this.user._id, pdoc.tags); const pid = await problem.add(domainId, pdoc.display_id, pdoc.title, content, this.user._id, pdoc.tags);
const testdata = new AdmZip(); const testdata = new AdmZip();
const config: LocalProblemConfig = { const config: LocalProblemConfig = {
+27 -14
View File
@@ -2,6 +2,7 @@
/* eslint-disable no-await-in-loop */ /* eslint-disable no-await-in-loop */
import mysql from 'mysql'; import mysql from 'mysql';
import 'hydrooj'; import 'hydrooj';
import { buildContent } from 'hydrooj/dist/utils';
const { const {
user, problem, builtin: { PRIV }, user, problem, builtin: { PRIV },
@@ -79,20 +80,32 @@ export async function run({
submit int 11 Y 总提交次数 submit int 11 Y 总提交次数
solved int 11 Y 解答(未用) solved int 11 Y 解答(未用)
*/ */
const [pdocs] = await query('SELECT * FROM `problem`'); const [[pcount]] = await query('SELECT count(*) FROM `problem`');
for (const pdoc of pdocs) { const step = 50;
const pid = await problem.add( const pageCount = Math.ceil(pcount / step);
'system', `P${pdoc.problem_id}`, for (let pageId = 0; pageId < pageCount; pageId++) {
pdoc.title, pdoc.description + pdoc.input + pdoc.output + pdoc.sample_input + pdoc.sample_output + pdoc.hint, const [pdocs] = await query(`SELECT * FROM \`problem\` LIMIT ${pageId * step}, ${step}`);
1, pdoc.source.split(' '), undefined, undefined, pdoc.defunct === 'Y', for (const pdoc of pdocs) {
); const pid = await problem.add(
const [cdoc] = await query(`SELECT * FROM 'privilege' WHERE rightstr = 'p${pdoc.problem_id}'`); 'system', `P${pdoc.problem_id}`,
await problem.edit('system', pid, { pdoc.title, buildContent({
nAccept: pdoc.accepted, description: pdoc.description,
nSubmit: pdoc.submit, input: pdoc.input,
config: { time: `${pdoc.time_limit}s`, memory: `${pdoc.memory_limit}m` }, output: pdoc.output,
owner: uidMap[cdoc[0].user_id], samples: [[pdoc.sample_input, pdoc.sample_output]],
}); hint: pdoc.hint,
source: pdoc.source,
}, 'html'),
1, pdoc.source.split(' '), undefined, undefined, pdoc.defunct === 'Y',
);
const [cdoc] = await query(`SELECT * FROM 'privilege' WHERE rightstr = 'p${pdoc.problem_id}'`);
await problem.edit('system', pid, {
nAccept: pdoc.accepted,
nSubmit: pdoc.submit,
config: { time: `${pdoc.time_limit}s`, memory: `${pdoc.memory_limit}m` },
owner: uidMap[cdoc[0].user_id],
});
}
} }
return true; return true;
} }