diff --git a/.typo-ci.yml b/.typo-ci.yml index cc81123a8..1ba556565 100644 --- a/.typo-ci.yml +++ b/.typo-ci.yml @@ -2,4 +2,4 @@ excluded_words: - hydrooj excluded_files: - package.json - - .typo-ci.yml \ No newline at end of file + - .typo-ci.yml diff --git a/jest.config.js b/jest.config.js index b9dea98c2..9725f81d9 100644 --- a/jest.config.js +++ b/jest.config.js @@ -1,7 +1,7 @@ module.exports = { preset: '@shelf/jest-mongodb', transform: { - '^.+\\.ts?$': 'ts-jest' + '^.+\\.ts?$': 'ts-jest', }, moduleFileExtensions: ['ts', 'js', 'json'], collectCoverage: true, diff --git a/packages/hydrooj/src/interface.ts b/packages/hydrooj/src/interface.ts index 40fc0f9d5..95bfad782 100644 --- a/packages/hydrooj/src/interface.ts +++ b/packages/hydrooj/src/interface.ts @@ -95,7 +95,11 @@ export interface User extends Dictionary { export type Udict = NumericDictionary; export interface FileInfo { + /** duplicate to filename */ + _id: string, + /** filename */ name: string, + /** file size (in bytes) */ size: number, etag: string, lastModified: Date, @@ -139,6 +143,7 @@ export interface ProblemConfig { interactor?: string, user_extra_files?: string[], judge_extra_files?: string[], + outputs?: [string, number][], cases?: TestCaseConfig[], subtasks?: SubtaskConfig[], } @@ -189,8 +194,8 @@ declare module './model/problem' { difficulty?: number, /** @deprecated */ category?: string[], - /** @deprecated */ - config: any, + + config: string, } } export type { Pdoc } from './model/problem'; diff --git a/packages/hydrooj/src/model/problem.ts b/packages/hydrooj/src/model/problem.ts index 07f3d52d5..bcd4fc8b4 100644 --- a/packages/hydrooj/src/model/problem.ts +++ b/packages/hydrooj/src/model/problem.ts @@ -142,12 +142,14 @@ export class ProblemModel { const payload = { name, ...pick(meta, ['size', 'lastModified', 'etag']) }; if (!fileinfo) await ProblemModel.push(domainId, pid, 'data', { _id: name, ...payload }); else await document.setSub(domainId, document.TYPE_PROBLEM, pid, 'data', name, payload); + await bus.emit('problem/addTestdata', domainId, pid, name, payload); } static async delTestdata(domainId: string, pid: number, name: string | string[]) { const names = (name instanceof Array) ? name : [name]; await storage.del(names.map((t) => `problem/${domainId}/${pid}/testdata/${t}`)); await ProblemModel.pull(domainId, pid, 'data', names); + await bus.emit('problem/delTestdata', domainId, pid, name); } static async addAdditionalFile(domainId: string, pid: number, name: string, f: Readable | Buffer | string) { @@ -159,12 +161,14 @@ export class ProblemModel { const payload = { name, ...pick(meta, ['size', 'lastModified', 'etag']) }; if (!fileinfo) await ProblemModel.push(domainId, pid, 'additional_file', { _id: name, ...payload }); else await document.setSub(domainId, document.TYPE_PROBLEM, pid, 'additional_file', name, payload); + await bus.emit('problem/addAdditionalFile', domainId, pid, name, payload); } static async delAdditionalFile(domainId: string, pid: number, name: string | string[]) { const names = (name instanceof Array) ? name : [name]; await storage.del(names.map((t) => `problem/${domainId}/${pid}/additional_file/${t}`)); await ProblemModel.pull(domainId, pid, 'additional_file', names); + await bus.emit('problem/delAdditionalFile', domainId, pid, name); } static async random(domainId: string, query: FilterQuery): Promise { diff --git a/packages/hydrooj/src/service/bus.ts b/packages/hydrooj/src/service/bus.ts index 088937a51..7bf119ca7 100644 --- a/packages/hydrooj/src/service/bus.ts +++ b/packages/hydrooj/src/service/bus.ts @@ -5,9 +5,8 @@ import { argv } from 'yargs'; import type { Handler } from './server'; import { Logger } from '../logger'; import type { - Mdoc, Pdoc, Rdoc, TrainingDoc, User, + Mdoc, Pdoc, Rdoc, TrainingDoc, User, Ddoc, DomainDoc, FileInfo, } from '../interface'; -import type { Ddoc, DomainDoc } from '../loader'; import type { DocType } from '../model/document'; import type { ProblemSolutionHandler } from '../handler/problem'; import type { UserRegisterHandler } from '../handler/user'; @@ -80,6 +79,10 @@ export interface EventMap extends Record { 'problem/list': (query: FilterQuery, handler: any) => VoidReturn 'problem/get': (doc: Pdoc, handler: any) => VoidReturn 'problem/delete': (domainId: string, docId: number) => VoidReturn + 'problem/addTestdata': (domainId: string, docId: number, name: string, payload: FileInfo) => VoidReturn + 'problem/delTestdata': (domainId: string, docId: number, name: string) => VoidReturn + 'problem/addAdditionalFile': (domainId: string, docId: number, name: string, payload: FileInfo) => VoidReturn + 'problem/delAdditionalFile': (domainId: string, docId: number, name: string) => VoidReturn 'training/list': (query: FilterQuery, handler: any) => VoidReturn 'training/get': (tdoc: TrainingDoc, handler: any) => VoidReturn