mirror of
https://gitcode.com/gh_mirrors/hy/Hydro.git
synced 2026-10-20 01:38:19 +08:00
core: drop array-style problem content (#882)
This commit is contained in:
1 parent
23dfcbeeae
commit
6ae902d3ca
9 files changed
+120
-180
No files matched your search
@@ -221,26 +221,7 @@ export interface ProblemConfig {
|
||||
hackable?: boolean;
|
||||
}
|
||||
|
||||
export interface PlainContentNode {
|
||||
type: 'Plain',
|
||||
subType: 'html' | 'markdown',
|
||||
text: string,
|
||||
}
|
||||
export interface TextContentNode {
|
||||
type: 'Text',
|
||||
subType: 'html' | 'markdown',
|
||||
sectionTitle: string,
|
||||
text: string,
|
||||
}
|
||||
export interface SampleContentNode {
|
||||
type: 'Sample',
|
||||
text: string,
|
||||
sectionTitle: string,
|
||||
payload: [string, string],
|
||||
}
|
||||
// TODO drop contentNode support
|
||||
export type ContentNode = PlainContentNode | TextContentNode | SampleContentNode;
|
||||
export type Content = string | ContentNode[] | Record<string, ContentNode[]>;
|
||||
export type Content = string | Record<string, string>;
|
||||
|
||||
export interface Document {
|
||||
_id: ObjectId;
|
||||
|
||||
@@ -1,17 +1,18 @@
|
||||
import { ContentNode } from '../interface';
|
||||
|
||||
export interface ProblemSource {
|
||||
description?: string,
|
||||
input?: string,
|
||||
output?: string,
|
||||
samples?: [string, string][],
|
||||
samplesRaw?: string,
|
||||
hint?: string,
|
||||
source?: string,
|
||||
}
|
||||
|
||||
export function buildContent(source: ProblemSource | ContentNode[], type: 'markdown' | 'html' = 'markdown', translate?: Function) {
|
||||
export function buildContent(source: ProblemSource, type: 'markdown' | 'html' = 'markdown', translate?: Function) {
|
||||
const _ = translate || ((s: string) => s);
|
||||
let cnt = 0;
|
||||
// Keep it for backward compatibility, but don't add to typings
|
||||
// required by upgrade 90_91
|
||||
if (source instanceof Array) {
|
||||
return type === 'html'
|
||||
? source.map((node) => [
|
||||
@@ -54,6 +55,7 @@ export function buildContent(source: ProblemSource | ContentNode[], type: 'markd
|
||||
sample[1],
|
||||
'</code></pre>',
|
||||
].join('')),
|
||||
...source.samplesRaw ? [source.samplesRaw] : [],
|
||||
...source.hint ? [`<h2>${_('Hint')}</h2>`, source.hint] : [],
|
||||
...source.source ? [`<h2>${_('Source')}</h2>`, source.source] : [],
|
||||
].join('\n')
|
||||
@@ -69,6 +71,7 @@ export function buildContent(source: ProblemSource | ContentNode[], type: 'markd
|
||||
sample[1],
|
||||
'```',
|
||||
].join('\n')),
|
||||
...source.samplesRaw ? [source.samplesRaw] : [],
|
||||
...source.hint ? [`## ${_('Hint')}`, source.hint] : [],
|
||||
...source.source ? [`## ${_('Source')}`, source.source] : [],
|
||||
].join('\n');
|
||||
|
||||
@@ -45,12 +45,7 @@ function findOverrideContent(dir: string, base: string) {
|
||||
if (!files.length) return null;
|
||||
for (const file of files) {
|
||||
const lang = file.slice(8, -3);
|
||||
let content: string | any[] = fs.readFileSync(path.join(dir, file), 'utf8');
|
||||
try {
|
||||
content = JSON.parse(content);
|
||||
if (!(content instanceof Array)) content = JSON.stringify(content);
|
||||
} catch (e) { }
|
||||
languages[lang] = content;
|
||||
languages[lang] = fs.readFileSync(path.join(dir, file), 'utf8');
|
||||
}
|
||||
return JSON.stringify(languages);
|
||||
}
|
||||
@@ -548,12 +543,12 @@ export class ProblemModel {
|
||||
const docId = overridePid
|
||||
? (await ProblemModel.edit(domainId, overridePid, {
|
||||
title: pdoc.title.trim(),
|
||||
content: overrideContent || pdoc.content || 'No content',
|
||||
content: overrideContent || pdoc.content.toString() || 'No content',
|
||||
tag,
|
||||
difficulty: pdoc.difficulty,
|
||||
})).docId
|
||||
: await ProblemModel.add(
|
||||
domainId, pid, pdoc.title.trim(), overrideContent || pdoc.content || 'No content',
|
||||
domainId, pid, pdoc.title.trim(), overrideContent || pdoc.content.toString() || 'No content',
|
||||
operator || pdoc.owner, tag, { hidden: pdoc.hidden, difficulty: pdoc.difficulty },
|
||||
);
|
||||
// TODO delete unused file when updating pdoc
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
/* eslint-disable consistent-return */
|
||||
/* eslint-disable @typescript-eslint/no-unused-vars */
|
||||
/* eslint-disable no-await-in-loop */
|
||||
/* eslint-disable @typescript-eslint/naming-convention */
|
||||
@@ -51,25 +52,7 @@ export const coreScripts: MigrationScript[] = [
|
||||
return true;
|
||||
},
|
||||
// Init
|
||||
...new Array(26).fill(unsupportedUpgrade),
|
||||
null,
|
||||
async function _28_29() {
|
||||
return await iterateAllProblem(['content', 'html'], async (pdoc) => {
|
||||
try {
|
||||
const parsed = JSON.parse(pdoc.content);
|
||||
if (parsed instanceof Array) {
|
||||
await problem.edit(pdoc.domainId, pdoc.docId, { content: buildContent(parsed, pdoc.html ? 'html' : 'markdown') });
|
||||
return;
|
||||
}
|
||||
const res = {};
|
||||
for (const key in parsed) {
|
||||
if (typeof parsed[key] === 'string') res[key] = parsed[key];
|
||||
else res[key] = buildContent(parsed[key]);
|
||||
}
|
||||
await problem.edit(pdoc.domainId, pdoc.docId, { content: JSON.stringify(res) });
|
||||
} catch { }
|
||||
});
|
||||
},
|
||||
...new Array(28).fill(unsupportedUpgrade),
|
||||
async function _29_30() {
|
||||
return await iterateAllDomain((ddoc) => RecordModel.coll.updateMany({ domainId: ddoc._id }, { $set: { pdomain: ddoc._id } }));
|
||||
},
|
||||
@@ -685,4 +668,38 @@ export const coreScripts: MigrationScript[] = [
|
||||
}
|
||||
});
|
||||
},
|
||||
async function _90_91() {
|
||||
await document.collStatus.updateMany({ docType: document.TYPE_PROBLEM }, { $unset: { nSubmit: '', nAccept: '' } });
|
||||
const psdocs = await document.coll.find({ docType: document.TYPE_PROBLEM_SOLUTION, vote: { $ne: 0 } })
|
||||
.project({ docId: 1, domainId: 1 }).toArray();
|
||||
for (const psdoc of psdocs) {
|
||||
const filter = { docType: document.TYPE_PROBLEM_SOLUTION, domainId: psdoc.domainId, docId: psdoc.docId };
|
||||
const [upvote, downvote] = await Promise.all([
|
||||
document.collStatus.countDocuments({ ...filter, vote: 1 }),
|
||||
document.collStatus.countDocuments({ ...filter, vote: -1 }),
|
||||
]);
|
||||
if (upvote - downvote !== psdoc.vote) {
|
||||
await document.set(psdoc.domainId, document.TYPE_PROBLEM_SOLUTION, psdoc.docId, { vote: upvote - downvote });
|
||||
}
|
||||
}
|
||||
await iterateAllProblem(['domainId', 'docId', 'tag'], async (pdoc) => {
|
||||
if (pdoc.tag?.some((i) => typeof i !== 'string')) {
|
||||
return { tag: pdoc.tag.filter((i) => i).map((i) => i.toString()) };
|
||||
}
|
||||
});
|
||||
return await iterateAllProblem(['domainId', 'docId', 'content', 'html'], async (pdoc) => {
|
||||
try {
|
||||
const parsed = JSON.parse(pdoc.content);
|
||||
if (parsed instanceof Array) {
|
||||
return { content: buildContent(parsed as any, pdoc.html ? 'html' : 'markdown') };
|
||||
}
|
||||
const res = {};
|
||||
for (const key in parsed) {
|
||||
if (typeof parsed[key] === 'string') res[key] = parsed[key];
|
||||
else res[key] = buildContent(parsed[key]);
|
||||
}
|
||||
return { content: JSON.stringify(res) };
|
||||
} catch { }
|
||||
});
|
||||
},
|
||||
];
|
||||
Reference in new issue
Block a user