diff --git a/packages/geoip/lib.ts b/packages/geoip/lib.ts index ca325cc4c..0ceecc87a 100644 --- a/packages/geoip/lib.ts +++ b/packages/geoip/lib.ts @@ -14,7 +14,7 @@ export interface Result { display: string } -export function lookup(ip: string, locale: string): any { +export function lookup(ip: string, locale: string) { const res: any = reader.get(ip); if (!res) return {}; const ret: Result = { display: '' }; diff --git a/packages/geoip/package.json b/packages/geoip/package.json index dfd5d11e8..f33b6c06f 100644 --- a/packages/geoip/package.json +++ b/packages/geoip/package.json @@ -1,6 +1,6 @@ { "name": "@hydrooj/geoip", - "version": "1.1.11", + "version": "1.1.12", "main": "package.json", "repository": "git@github.com:hydro-dev/Hydro.git", "author": "undefined ", diff --git a/packages/hydrooj/package.json b/packages/hydrooj/package.json index c7a3f93d9..949d886f8 100644 --- a/packages/hydrooj/package.json +++ b/packages/hydrooj/package.json @@ -1,6 +1,6 @@ { "name": "hydrooj", - "version": "2.12.26", + "version": "2.12.27", "bin": "bin/hydrooj.js", "main": "dist/loader.js", "typings": "dist/loader.d.ts", diff --git a/packages/hydrooj/src/check.ts b/packages/hydrooj/src/check.ts index 343f2167e..c2e62047d 100644 --- a/packages/hydrooj/src/check.ts +++ b/packages/hydrooj/src/check.ts @@ -43,7 +43,7 @@ const checks: Dictionary = { }, }; -export async function start(ctx, log, warn, error, cb) { +export async function start(ctx, log, warn, error, cb: (id: string) => any) { const id = String.random(6); cb(id); for (const name in checks) { diff --git a/packages/hydrooj/src/handler/domain.ts b/packages/hydrooj/src/handler/domain.ts index 59602f9ba..412e2b41c 100644 --- a/packages/hydrooj/src/handler/domain.ts +++ b/packages/hydrooj/src/handler/domain.ts @@ -14,6 +14,7 @@ import paginate from '../lib/paginate'; import { Route, Handler, Types, param, } from '../service/server'; +import { DomainDoc } from '../interface'; class DomainRankHandler extends Handler { @param('page', Types.PositiveInt, true) @@ -40,7 +41,7 @@ class DomainRankHandler extends Handler { } class ManageHandler extends Handler { - domain: any; + domain: DomainDoc; async prepare({ domainId }) { this.checkPerm(PERM.PERM_EDIT_DOMAIN); diff --git a/packages/hydrooj/src/handler/manage.ts b/packages/hydrooj/src/handler/manage.ts index 388a0c7e5..5edf4f3ca 100644 --- a/packages/hydrooj/src/handler/manage.ts +++ b/packages/hydrooj/src/handler/manage.ts @@ -51,7 +51,7 @@ class SystemMainHandler extends SystemHandler { } class SystemCheckConnHandler extends ConnectionHandler { - id: any; + id: string; async prepare() { this.checkPriv(PRIV.PRIV_EDIT_SYSTEM); diff --git a/packages/hydrooj/src/handler/training.ts b/packages/hydrooj/src/handler/training.ts index d2320366f..a18c01560 100644 --- a/packages/hydrooj/src/handler/training.ts +++ b/packages/hydrooj/src/handler/training.ts @@ -102,8 +102,8 @@ class TrainingDetailHandler extends Handler { problem.getList(domainId, pids, this.user.hasPerm(PERM.PERM_VIEW_PROBLEM_HIDDEN)), ]); const psdict = await problem.getListStatus(domainId, this.user._id, pids); - const donePids = new Set(); - const progPids = new Set(); + const donePids = new Set(); + const progPids = new Set(); for (const pid in psdict) { const psdoc = psdict[pid]; if (psdoc.status) { @@ -114,7 +114,7 @@ class TrainingDetailHandler extends Handler { } const nsdict = {}; const ndict = {}; - const doneNids = new Set(); + const doneNids = new Set(); for (const node of tdoc.dag) { ndict[node._id] = node; const totalCount = node.pids.length; @@ -174,13 +174,9 @@ class TrainingCreateHandler extends Handler { _dag: string, description: string, ) { const dag = await _parseDagJson(domainId, _dag); - const pids = training.getPids({ dag }); + const pids = training.getPids(dag); assert(pids.length, new ValidationError('dag')); - const pdocs = await problem.getMulti(domainId, { - // TODO - // @ts-ignore - $or: [{ docId: { $in: pids } }, { pid: { $in: pids } }], - }).sort('_id', 1).toArray(); + const pdocs = await problem.getMulti(domainId, { docId: { $in: pids } }).sort('_id', 1).toArray(); const existPids = pdocs.map((pdoc) => pdoc.docId); const existPnames = pdocs.map((pdoc) => pdoc.pid); if (pids.length !== existPids.length) { @@ -235,7 +231,7 @@ class TrainingEditHandler extends Handler { _dag: string, description: string, ) { const dag = await _parseDagJson(domainId, _dag); - const pids = training.getPids({ dag }); + const pids = training.getPids(dag); assert(pids.length, new ValidationError('dag')); const pdocs = await problem.getMulti(domainId, { $or: [ diff --git a/packages/hydrooj/src/interface.ts b/packages/hydrooj/src/interface.ts index 39241e121..928ec384e 100644 --- a/packages/hydrooj/src/interface.ts +++ b/packages/hydrooj/src/interface.ts @@ -31,7 +31,7 @@ export interface Udoc extends Dictionary { } export interface User extends Dictionary { - udoc: () => any, + udoc: () => Udoc, dudoc: () => any, _id: number, mail: string, @@ -211,6 +211,13 @@ export interface ScoreboardNode { export type PenaltyRules = Dictionary; +export interface TrainingNode { + _id: number, + title: string, + requireNids: number[], + pids: number[], +} + export interface Tdoc { _id: ObjectID, domainId: string, @@ -230,7 +237,13 @@ export interface Tdoc { penaltyRules?: PenaltyRules, // For training - dag: any + description?: string, + dag?: TrainingNode[], +} + +export interface TrainingDoc extends Tdoc { + description: string, + dag: TrainingNode[], } export interface DomainDoc extends Dictionary { @@ -365,7 +378,7 @@ export interface JudgeResultBody { stderr?: string, } -export type PathComponent = [string, string, any?, boolean?]; +export type PathComponent = [string, string, Dictionary?, boolean?]; export interface Model { blacklist: typeof import('./model/blacklist'), diff --git a/packages/hydrooj/src/model/builtin.ts b/packages/hydrooj/src/model/builtin.ts index 78d703aba..a1c1b8fd4 100644 --- a/packages/hydrooj/src/model/builtin.ts +++ b/packages/hydrooj/src/model/builtin.ts @@ -533,6 +533,11 @@ export const LANG_HIGHLIGHT_ID = { rb: 'ruby', }; +export function registerLanguage(id: string, display: string, highlight: string) { + LANG_TEXTS[id] = display; + LANG_HIGHLIGHT_ID[id] = highlight; +} + export const STATUS = { STATUS_WAITING: 0, STATUS_ACCEPTED: 1, @@ -618,6 +623,7 @@ export const CONSTANT = { global.Hydro.model.builtin = { Permission, + registerLanguage, PERM, PERMS, PERMS_BY_FAMILY, diff --git a/packages/hydrooj/src/model/discussion.ts b/packages/hydrooj/src/model/discussion.ts index ce6423894..2d93a7df6 100644 --- a/packages/hydrooj/src/model/discussion.ts +++ b/packages/hydrooj/src/model/discussion.ts @@ -183,7 +183,7 @@ export async function getVnode(domainId: string, type: number, id: string) { }; } if (type === document.TYPE_TRAINING) { - const tdoc = await training.get(domainId, id); + const tdoc = await training.get(domainId, new ObjectID(id)); return { ...tdoc, type, id }; } if (type === document.TYPE_HOMEWORK) { diff --git a/packages/hydrooj/src/model/training.ts b/packages/hydrooj/src/model/training.ts index 64f3b8125..c01244576 100644 --- a/packages/hydrooj/src/model/training.ts +++ b/packages/hydrooj/src/model/training.ts @@ -1,6 +1,8 @@ -import { ObjectID } from 'mongodb'; +import { FilterQuery, ObjectID } from 'mongodb'; +import { flatten } from 'lodash'; import * as document from './document'; import { TrainingNotFoundError, TrainingAlreadyEnrollError } from '../error'; +import { TrainingDoc, TrainingNode } from '../interface'; export function getStatus(domainId: string, tid: ObjectID, uid: number) { return document.getStatus(domainId, document.TYPE_TRAINING, tid, uid); @@ -34,7 +36,7 @@ export function setStatus(domainId: string, tid: ObjectID, uid: number, $set: an export function add( domainId: string, title: string, content: string, - owner: number, dag = [], description = '', + owner: number, dag: TrainingNode[] = [], description = '', ) { return document.add(domainId, content, owner, document.TYPE_TRAINING, null, null, null, { dag, @@ -44,24 +46,20 @@ export function add( }); } -export function edit(domainId: string, tid: ObjectID, $set) { +export function edit(domainId: string, tid: ObjectID, $set: Partial) { return document.set(domainId, document.TYPE_TRAINING, tid, $set); } -export function getPids(tdoc): number[] { - const pids: Set = new Set(); - for (const node of tdoc.dag) { - for (const pid of node.pids) pids.add(pid); - } - return Array.from(pids); +export function getPids(dag: TrainingNode[]) { + return Array.from(new Set(flatten(dag.map((node) => node.pids)))); } -export function isDone(node, doneNids, donePids) { +export function isDone(node: TrainingNode, doneNids: Set | number[], donePids: Set | number[]) { return (Set.isSuperset(new Set(doneNids), new Set(node.requireNids)) && Set.isSuperset(new Set(donePids), new Set(node.pids))); } -export function isProgress(node, doneNids, donePids, progPids) { +export function isProgress(node: TrainingNode, doneNids: Set | number[], donePids: Set | number[], progPids: Set | number[]) { return (Set.isSuperset(new Set(doneNids), new Set(node.requireNids)) && !Set.isSuperset(new Set(donePids), new Set(node.pids)) && Set.intersection( @@ -70,7 +68,7 @@ export function isProgress(node, doneNids, donePids, progPids) { ).size); } -export function isOpen(node, doneNids, donePids, progPids) { +export function isOpen(node: TrainingNode, doneNids: Set | number[], donePids: Set | number[], progPids: Set | number[]) { return (Set.isSuperset(new Set(doneNids), new Set(node.requireNids)) && !Set.isSuperset(new Set(donePids), new Set(node.pids)) && !Set.intersection( @@ -79,13 +77,14 @@ export function isOpen(node, doneNids, donePids, progPids) { ).size); } -export const isInvalid = (node, doneNids) => +export const isInvalid = (node: TrainingNode, doneNids: Set | number[]) => !Set.isSuperset(new Set(doneNids), new Set(node.requireNids)); -export const count = (domainId: string, query: any) => - document.count(domainId, document.TYPE_TRAINING, query); +export async function count(domainId: string, query: FilterQuery) { + return await document.count(domainId, document.TYPE_TRAINING, query); +} -export async function get(domainId, tid) { +export async function get(domainId: string, tid: ObjectID) { const tdoc = await document.get(domainId, document.TYPE_TRAINING, tid); if (!tdoc) throw new TrainingNotFoundError(tid); for (const i in tdoc.dag) { @@ -107,7 +106,7 @@ export async function getList(domainId: string, tids: ObjectID[]) { return r; } -export const getMulti = (domainId: string, query: any = {}) => +export const getMulti = (domainId: string, query: FilterQuery = {}) => document.getMulti(domainId, document.TYPE_TRAINING, query).sort('_id', 1); global.Hydro.model.training = {