From 90bdb4810d08910c374acc7a78cffdeeac6bc249 Mon Sep 17 00:00:00 2001 From: undefined Date: Wed, 13 Nov 2024 11:31:13 +0800 Subject: [PATCH] keep things simple --- packages/hydrooj/src/interface.ts | 8 +-- packages/hydrooj/src/model/document.ts | 30 ----------- packages/hydrooj/src/model/problem.ts | 71 ++++++-------------------- 3 files changed, 17 insertions(+), 92 deletions(-) diff --git a/packages/hydrooj/src/interface.ts b/packages/hydrooj/src/interface.ts index 119e465e8..54e48adfc 100644 --- a/packages/hydrooj/src/interface.ts +++ b/packages/hydrooj/src/interface.ts @@ -223,7 +223,7 @@ export interface ProblemConfig { hackable?: boolean; } -export type LocalizedContent = ({ id: string, name: string, lang: string } | { from: string, name: string, lang: string })[]; +export type LocalizedContent = ({ content: string, name: string, lang: string })[]; export type Content = string | LocalizedContent; export interface Document { @@ -680,11 +680,6 @@ export interface ContestBalloonDoc { sentAt?: Date; } -export interface ContentDoc { - _id: string; - content: string; -} - declare module './service/db' { interface Collections { 'blacklist': BlacklistDoc; @@ -696,7 +691,6 @@ declare module './service/db' { 'document.status': StatusDocBase & { [K in keyof DocStatusType]: { docType: K } & DocStatusType[K]; }[keyof DocStatusType]; - 'content': ContentDoc; 'discussion.history': DiscussionHistoryDoc; 'user': Udoc; 'user.preference': UserPreferenceDoc; diff --git a/packages/hydrooj/src/model/document.ts b/packages/hydrooj/src/model/document.ts index 06b29bdac..a20d893f2 100644 --- a/packages/hydrooj/src/model/document.ts +++ b/packages/hydrooj/src/model/document.ts @@ -19,7 +19,6 @@ type NormalArrayKeys = Exclude, Symbol>; export const coll = db.collection('document'); export const collStatus = db.collection('document.status'); -export const collContent = db.collection('content'); export const TYPE_PROBLEM: 10 = 10; export const TYPE_PROBLEM_SOLUTION: 11 = 11; @@ -426,29 +425,6 @@ export async function revSetStatus( return res.value; } -export async function getContent(contentId: string) { - return await collContent.findOne({ _id: contentId }); -} - -export async function getContents(contentIds: string[]) { - return await collContent.find({ _id: { $in: contentIds } }).toArray(); -} - -export async function addContent(content: string) { - const id = String.random(32); - await collContent.insertOne({ _id: id, content }); - return id; -} - -export async function setContent(contentId: string, content: string) { - const res = await collContent.updateOne({ _id: contentId }, { $set: { content } }); - return !!res.matchedCount; -} - -export async function deleteContent(contentId: string) { - return await collContent.deleteOne({ _id: contentId }); -} - export async function apply(ctx: Context) { ctx.on('domain/delete', (domainId) => Promise.all([ coll.deleteMany({ domainId }), @@ -487,7 +463,6 @@ export async function apply(ctx: Context) { global.Hydro.model.document = { coll, - collContent, collStatus, add, @@ -519,11 +494,6 @@ global.Hydro.model.document = { setStatus, setMultiStatus, setSub, - getContent, - getContents, - addContent, - setContent, - deleteContent, TYPE_CONTEST, TYPE_CONTEST_CLARIFICATION, diff --git a/packages/hydrooj/src/model/problem.ts b/packages/hydrooj/src/model/problem.ts index 171b88ca8..53f170113 100644 --- a/packages/hydrooj/src/model/problem.ts +++ b/packages/hydrooj/src/model/problem.ts @@ -41,19 +41,20 @@ function sortable(source: string, namespaces: Record) { function findOverrideContent(dir: string, base: string) { let files = fs.readdirSync(dir); - if (files.includes(`${base}.md`)) return fs.readFileSync(path.join(dir, `${base}.md`), 'utf8'); - if (files.includes(`${base}.pdf`)) return `@[PDF](file://${base}.pdf)`; - const languages = {}; + if (files.includes(`${base}.md`)) return [{ name: 'default', content: fs.readFileSync(path.join(dir, `${base}.md`), 'utf8'), lang: 'en' }]; + if (files.includes(`${base}.pdf`)) return [{ name: 'default', content: `@[PDF](file://${base}.pdf)`, lang: 'en' }]; + const c: LocalizedContent = []; files = files.filter((i) => new RegExp(`^${base}(?:_|.)([a-zA-Z_]+)\\.(md|pdf)$`).test(i)); if (!files.length) return null; for (const file of files) { const match = file.match(`^${base}(?:_|.)([a-zA-Z_]+)\\.(md|pdf)$`); const lang = match[1]; const ext = match[2]; - if (ext === 'pdf') languages[lang] = `@[PDF](file://${file})`; - else languages[lang] = fs.readFileSync(path.join(dir, file), 'utf8'); + // TODO: parse markdown header to get name + if (ext === 'pdf') c.push({ name: lang, content: `@[PDF](file://${file})`, lang }); + else c.push({ name: lang, content: fs.readFileSync(path.join(dir, file), 'utf8'), lang }); } - return JSON.stringify(languages); + return c; } interface ProblemImportOptions { @@ -138,22 +139,10 @@ export class ProblemModel { static async add( domainId: string, pid: string = '', title: string, - content: { content?: string, from?: string, lang: string, name: string }[] | string, + content: { content: string, lang: string, name: string }[] | string, owner: number, tag: string[] = [], meta: ProblemCreateOptions = {}, ) { - let c: LocalizedContent; - if (typeof content === 'string') { - c.push({ id: await document.addContent(content), name: 'default', lang: 'en' }); - } else { - for (const entry of content) { - if (entry.from) { - c.push(entry as any); - } else { - const id = await document.addContent(entry.content); - c.push({ id, name: entry.name, lang: entry.lang }); - } - } - } + const c = typeof content === 'string' ? [{ content, lang: 'en', name: 'default' }] : content; const [doc] = await ProblemModel.getMulti(domainId, {}) .sort({ docId: -1 }).limit(1).project({ docId: 1 }) .toArray(); @@ -206,11 +195,6 @@ export class ProblemModel { return res; } - static async getContent(contentIds: string[]) { - const content = await document.getContents(contentIds); - return Object.fromEntries(content.map((i) => [i._id.toString(), i.content])); - } - static getMulti(domainId: string, query: Filter, projection = ProblemModel.PROJECTION_LIST) { return document.getMulti(domainId, document.TYPE_PROBLEM, query, projection).sort({ sort: 1 }); } @@ -235,10 +219,7 @@ export class ProblemModel { return document.getMultiStatus(domainId, document.TYPE_PROBLEM, query); } - static async edit( - domainId: string, _id: number, - $set: (Partial & ({ content?: { content: string }[] })), - ): Promise { + static async edit(domainId: string, _id: number, $set: Partial): Promise { const delpid = $set.pid === ''; const ddoc = await DomainModel.get(domainId); if (delpid) { @@ -248,23 +229,6 @@ export class ProblemModel { $set.sort = sortable($set.pid, ddoc.namespaces); } await bus.parallel('problem/before-edit', $set); - if ($set.content) { - const update = $set.content instanceof Array ? $set.content : [{ content: $set.content, lang: 'en', name: 'default' }]; - const existing = await document.get(domainId, document.TYPE_PROBLEM, _id); - if (!existing) throw new ProblemNotFoundError(domainId, _id); - const contents = existing.content; - const final = []; - for (const entry of update) { - if ('id' in entry && contents.find((i) => i.id === entry.id)) { - await document.setContent(entry.id, entry.content); - final.push({ id: entry.id, name: entry.name, lang: entry.lang }); - } else { - const cid = await document.addContent(entry.content); - final.push({ id: cid, name: entry.name, lang: entry.lang }); - } - } - $set.content = final; - } const result = await document.set(domainId, document.TYPE_PROBLEM, _id, $set, delpid ? { pid: '' } : undefined); await bus.emit('problem/edit', result); return result; @@ -277,7 +241,7 @@ export class ProblemModel { if (pid && (/^[0-9]+$/.test(pid) || await ProblemModel.get(target, pid))) pid = ''; if (!pid && original.pid && !await ProblemModel.get(target, original.pid)) pid = original.pid; return await ProblemModel.add( - target, pid, original.title, original.content.map((i) => ({ name: i.name, lang: i.lang, from: 'id' in i ? i.id : i.from })), + target, pid, original.title, original.content, original.owner, original.tag, { hidden: original.hidden, reference: { domainId, pid: _id } }, ); } @@ -585,8 +549,8 @@ export class ProblemModel { const docId = overridePid ? (await ProblemModel.edit(domainId, overridePid, { title: pdoc.title.trim(), - content: [{ - id: '', name: 'default', content: overrideContent || pdoc.content.toString() || 'No content', lang: 'en', + content: overrideContent || [{ + name: 'default', content: pdoc.content.toString() || 'No content', lang: 'en', }], tag, difficulty: pdoc.difficulty, @@ -663,19 +627,16 @@ export class ProblemModel { nAccept: pdoc.nAccept, difficulty: pdoc.difficulty, }); - const [c] = await Promise.all([ - ProblemModel.getContent(pdoc.content.map((i) => ('id' in i ? i.id : i.from))), - fs.writeFile(problemYaml, problemYamlContent), - ]); + await fs.writeFile(problemYaml, problemYamlContent); for (const i of pdoc.content) { - await fs.writeFile(path.join(problemPath, `problem_${'id' in i ? i.id : i.from}.md`), [ + await fs.writeFile(path.join(problemPath, `problem_${i.name}_${i.lang}.md`), [ '---', yaml.dump({ name: i.name, lang: i.lang, }), '---', - c['id' in i ? i.id : i.from], + i.content, ].join('\n')); } if ((pdoc.data || []).length) {