core: rename interface props

This commit is contained in:
undefined committed 2021-05-11 23:56:20 +08:00
1 parent 8ea50bfafb
commit 808cb5d4a5
20 files changed
+148 -154

No files matched your search

+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "hydrooj",
"version": "2.25.10",
"version": "2.25.11",
"bin": "bin/hydrooj.js",
"main": "dist/loader.js",
"typings": "dist/loader.d.ts",
+2 -2
View File
@@ -6,7 +6,7 @@ import {
ContestNotLiveError, ValidationError, ProblemNotFoundError,
ContestNotAttendedError, PermissionError,
} from '../error';
import { Pdoc, Tdoc, User } from '../interface';
import { ProblemDoc, Tdoc, User } from '../interface';
import paginate from '../lib/paginate';
import { PERM, PRIV } from '../model/builtin';
import * as contest from '../model/contest';
@@ -240,7 +240,7 @@ class ContestEditHandler extends Handler {
class ContestProblemHandler extends Handler {
tdoc: Tdoc<30 | 60>;
pdoc: Pdoc;
pdoc: ProblemDoc;
tsdoc: any;
udoc: User;
attended: boolean;
+5 -5
View File
@@ -1,7 +1,7 @@
import { ObjectID } from 'mongodb';
import { isSafeInteger } from 'lodash';
import { DiscussionNotFoundError, DocumentNotFoundError, PermissionError } from '../error';
import { Drdoc, Ddoc, Drrdoc } from '../interface';
import { DiscussionReplyDoc, DiscussionDoc, DiscussionTailReplyDoc } from '../interface';
import paginate from '../lib/paginate';
import * as system from '../model/system';
import user from '../model/user';
@@ -23,9 +23,9 @@ export const typeMapper = {
};
class DiscussionHandler extends Handler {
ddoc?: Ddoc;
drdoc?: Drdoc;
drrdoc?: Drrdoc;
ddoc?: DiscussionDoc;
drdoc?: DiscussionReplyDoc;
drrdoc?: DiscussionTailReplyDoc;
vnode?: any;
@param('type', Types.Name, true)
@@ -214,7 +214,7 @@ class DiscussionDetailHandler extends DiscussionHandler {
await this.limitRate('add_discussion', 3600, 60);
// Notify related users
await discussion.addReply(domainId, did, this.user._id, content, this.request.ip);
const replies: Drdoc[] = await discussion.getMultiReply(domainId, did).toArray();
const replies: DiscussionReplyDoc[] = await discussion.getMultiReply(domainId, did).toArray();
const uids = new Set(replies.map((drdoc) => drdoc.owner));
uids.delete(this.user._id);
const str = JSON.stringify({ message: '{0} replied to discussion {1}/{2}.', params: [this.user._id, domainId, did] });
+2 -2
View File
@@ -5,7 +5,7 @@ import {
NotFoundError, UserNotFoundError, PermissionError,
DomainAlreadyExistsError, ValidationError, BlacklistedError,
} from '../error';
import { Mdoc, Setting, DomainDoc } from '../interface';
import { MessageDoc, Setting, DomainDoc } from '../interface';
import * as bus from '../service/bus';
import {
Route, Connection, Handler, ConnectionHandler, param, Types,
@@ -399,7 +399,7 @@ class HomeMessagesConnectionHandler extends ConnectionHandler {
this.dispose = bus.on('user/message', this.onMessageReceived.bind(this));
}
async onMessageReceived(uid: number, mdoc: Mdoc) {
async onMessageReceived(uid: number, mdoc: MessageDoc) {
if (uid !== this.user._id) return;
const udoc = await user.getById(this.domainId, mdoc.from);
udoc.avatarUrl = avatar(udoc.avatar, 64);
+2 -2
View File
@@ -7,7 +7,7 @@ import {
ValidationError, HomeworkNotLiveError, ProblemNotFoundError,
HomeworkNotAttendedError,
} from '../error';
import { PenaltyRules, Tdoc, Pdoc } from '../interface';
import { PenaltyRules, Tdoc, ProblemDoc } from '../interface';
import {
Route, Handler, Types, param,
} from '../service/server';
@@ -118,7 +118,7 @@ class HomeworkDetailHandler extends Handler {
class HomeworkDetailProblemHandler extends Handler {
tdoc: Tdoc<60>;
pdoc: Pdoc;
pdoc: ProblemDoc;
tsdoc: any;
@param('tid', Types.ObjectID)
+4 -4
View File
@@ -1,5 +1,5 @@
import { ObjectID } from 'mongodb';
import { JudgeResultBody, Rdoc, TestCase } from '../interface';
import { JudgeResultBody, RecordDoc, TestCase } from '../interface';
import { sleep } from '../utils';
import { Logger } from '../logger';
import difficultyAlgorithm from '../lib/difficulty';
@@ -20,7 +20,7 @@ import { updateJudge } from '../service/monitor';
const logger = new Logger('judge');
async function _postJudge(rdoc: Rdoc) {
async function _postJudge(rdoc: RecordDoc) {
if (typeof rdoc.input === 'string') return;
const accept = rdoc.status === builtin.STATUS.STATUS_ACCEPTED;
const updated = await problem.updateStatus(rdoc.domainId, rdoc.pid, rdoc.uid, rdoc._id, rdoc.status, rdoc.score);
@@ -45,7 +45,7 @@ async function _postJudge(rdoc: Rdoc) {
export async function next(body: JudgeResultBody) {
if (body.rid) body.rid = new ObjectID(body.rid);
let rdoc = await record.get(body.domainId, body.rid);
const $set: Partial<Rdoc> = {};
const $set: Partial<RecordDoc> = {};
const $push: any = {};
if (body.case) {
const c: TestCase = {
@@ -77,7 +77,7 @@ export async function next(body: JudgeResultBody) {
export async function end(body: JudgeResultBody) {
if (body.rid) body.rid = new ObjectID(body.rid);
let rdoc = await record.get(body.domainId, body.rid);
const $set: Partial<Rdoc> = {};
const $set: Partial<RecordDoc> = {};
const $push: any = {};
const $unset: any = { progress: '' };
if (body.message) {
+6 -6
View File
@@ -8,7 +8,7 @@ import {
ForbiddenError,
} from '../error';
import {
Pdoc, User, Rdoc, PathComponent, ProblemStatusDoc,
ProblemDoc, User, RecordDoc, PathComponent, ProblemStatusDoc,
} from '../interface';
import paginate from '../lib/paginate';
import { isPid } from '../lib/validator';
@@ -61,7 +61,7 @@ export class ProblemMainHandler extends ProblemHandler {
async get(domainId: string, page = 1, q = '', category = []) {
this.response.template = 'problem_main.html';
// eslint-disable-next-line @typescript-eslint/no-shadow
const query: FilterQuery<Pdoc> = {};
const query: FilterQuery<ProblemDoc> = {};
let psdict = {};
const path: PathComponent[] = [
['Hydro', 'homepage'],
@@ -161,7 +161,7 @@ export class ProblemMainHandler extends ProblemHandler {
export class ProblemRandomHandler extends ProblemHandler {
@param('category', Types.Name, true, null, parseCategory)
async get(domainId: string, category: string[] = []) {
const q: FilterQuery<Pdoc> = category.length ? { $and: [] } : {};
const q: FilterQuery<ProblemDoc> = category.length ? { $and: [] } : {};
for (const tag of category) q.$and.push({ tag });
if (!this.user.hasPerm(PERM.PERM_VIEW_PROBLEM_HIDDEN)) q.hidden = false;
await bus.serial('problem/list', q, this);
@@ -172,7 +172,7 @@ export class ProblemRandomHandler extends ProblemHandler {
}
}
export interface PdocWithPsdoc extends Pdoc {
export interface PdocWithPsdoc extends ProblemDoc {
psdoc?: ProblemStatusDoc
}
@@ -309,7 +309,7 @@ export class ProblemPretestConnectionHandler extends ConnectionHandler {
this.dispose = bus.on('record/change', this.onRecordChange.bind(this));
}
async onRecordChange(rdoc: Rdoc) {
async onRecordChange(rdoc: RecordDoc) {
if (
rdoc.uid !== this.user._id
|| rdoc.pid.toString() !== this.pid
@@ -366,7 +366,7 @@ export class ProblemEditHandler extends ProblemManageHandler {
newPid: string = '', hidden = false, tag: string[] = [],
) {
if (newPid !== this.pdoc.pid && await problem.get(domainId, newPid)) throw new BadRequestError('new pid exists');
const $update: Partial<Pdoc> = {
const $update: Partial<ProblemDoc> = {
title, content, pid: newPid, hidden, tag: tag ?? [],
};
let pdoc = await problem.get(domainId, pid);
+4 -4
View File
@@ -1,6 +1,6 @@
import { FilterQuery, ObjectID } from 'mongodb';
import { ContestNotFoundError, PermissionError, RecordNotFoundError } from '../error';
import { Rdoc } from '../interface';
import { RecordDoc } from '../interface';
import { PERM, STATUS, PRIV } from '../model/builtin';
import * as system from '../model/system';
import problem from '../model/problem';
@@ -24,7 +24,7 @@ class RecordListHandler extends Handler {
@param('allDomain', Types.Boolean, true)
async get(domainId: string, page = 1, pid?: string, tid?: ObjectID, uidOrName?: string, status?: number, all = false) {
this.response.template = 'record_main.html';
const q: FilterQuery<Rdoc> = { 'contest.tid': tid, hidden: false };
const q: FilterQuery<RecordDoc> = { 'contest.tid': tid, hidden: false };
if (tid) {
const tdoc = await contest.get(domainId, tid, -1);
if (!tdoc) throw new ContestNotFoundError(domainId, pid);
@@ -178,7 +178,7 @@ class RecordMainConnectionHandler extends ConnectionHandler {
if (this.dispose) this.dispose();
}
async onRecordChange(rdoc: Rdoc) {
async onRecordChange(rdoc: RecordDoc) {
if (rdoc.input) return;
if (rdoc.contest && rdoc.contest.tid.toString() !== this.tid) return;
if (rdoc.domainId !== this.domainId) return;
@@ -212,7 +212,7 @@ class RecordDetailConnectionHandler extends ConnectionHandler {
}
// eslint-disable-next-line
async onRecordChange(rdoc: Rdoc, $set?: any, $push?: any) {
async onRecordChange(rdoc: RecordDoc, $set?: any, $push?: any) {
if (rdoc._id.toString() !== this.rid) return;
// TODO: frontend doesn't support incremental update
// if ($set) this.send({ $set, $push });
+2 -2
View File
@@ -12,7 +12,7 @@ import user from '../model/user';
import oauth from '../model/oauth';
import token from '../model/token';
import record from '../model/record';
import problem, { Pdoc } from '../model/problem';
import problem, { ProblemDoc } from '../model/problem';
import task from '../model/task';
import * as system from '../model/system';
import { PERM, PRIV } from '../model/builtin';
@@ -196,7 +196,7 @@ class UserDetailHandler extends Handler {
1,
100,
)
: [[], 0, 0] as [Pdoc[], number, number],
: [[], 0, 0] as [ProblemDoc[], number, number],
]);
const pdict = this.user.hasPerm(PERM.PERM_VIEW_PROBLEM)
? await problem.getList(
+26 -35
View File
@@ -3,7 +3,7 @@ import type { Cursor, ObjectID } from 'mongodb';
import type fs from 'fs';
import type { Dictionary, NumericDictionary } from 'lodash';
import type * as Koa from 'koa';
import type { Pdoc } from './model/problem';
import type { ProblemDoc } from './model/problem';
type document = typeof import('./model/document');
@@ -187,7 +187,7 @@ export interface Document {
}
declare module './model/problem' {
interface Pdoc {
interface ProblemDoc {
docType: document['TYPE_PROBLEM'],
docId: number,
pid: string,
@@ -207,8 +207,8 @@ declare module './model/problem' {
config: string,
}
}
export type { Pdoc } from './model/problem';
export type Pdict = NumericDictionary<Pdoc>;
export type { ProblemDoc } from './model/problem';
export type ProblemDict = NumericDictionary<ProblemDoc>;
export interface StatusDoc {
_id: ObjectID,
@@ -241,7 +241,7 @@ export interface ContestInfo {
tid: ObjectID,
}
export interface Rdoc {
export interface RecordDoc {
_id: ObjectID,
domainId: string,
pid: number
@@ -318,7 +318,7 @@ export interface DomainDoc extends Record<string, any> {
}
// Message
export interface Mdoc {
export interface MessageDoc {
_id: ObjectID,
from: number,
to: number,
@@ -326,31 +326,25 @@ export interface Mdoc {
flag: number,
}
// Userfile
export interface Ufdoc {
_id: ObjectID,
secret: string,
md5?: string,
owner: number,
size?: number,
filename: string,
}
// Blacklist
export interface Bdoc {
_id: string, // ip
expireAt: Date,
export interface BlacklistDoc {
/**
* @example ip:1.1.1.1
* @example mail:foo.com
*/
_id: string;
expireAt: Date;
}
export interface HistoryDoc {
content: string,
time: Date,
content: string;
time: Date;
}
// Discussion
export type { Ddoc } from './model/discussion';
export type { DiscussionDoc } from './model/discussion';
declare module './model/discussion' {
interface Ddoc {
interface DiscussionDoc {
docType: document['TYPE_DISCUSSION'],
docId: ObjectID,
parentType: number,
@@ -367,20 +361,18 @@ declare module './model/discussion' {
}
}
// Discussion reply
export interface Drdoc extends Document {
export interface DiscussionReplyDoc extends Document {
docType: document['TYPE_DISCUSSION_REPLY'],
docId: ObjectID,
parentType: document['TYPE_DISCUSSION'],
parentId: ObjectID,
ip: string,
content: string,
reply: Drrdoc[],
reply: DiscussionTailReplyDoc[],
history: HistoryDoc[],
}
// Discussion Tail Reply
export interface Drrdoc {
export interface DiscussionTailReplyDoc {
_id: ObjectID,
owner: number,
content: string,
@@ -415,13 +407,13 @@ export interface ContestRule {
stat: (tdoc: Tdoc<30 | 60>, journal: any[]) => ContestStat;
scoreboard: (
isExport: boolean, _: (s: string) => string,
tdoc: Tdoc<30 | 60>, pdict: Pdict, cursor: Cursor<any>, page: number,
tdoc: Tdoc<30 | 60>, pdict: ProblemDict, cursor: Cursor<any>, page: number,
) => Promise<[board: ScoreboardRow[], udict: Udict, nPages: number]>;
ranked: (tdoc: Tdoc<30 | 60>, cursor: Cursor<any>) => Promise<any[]>;
}
export type ContestRules = Dictionary<ContestRule>;
export type ProblemImporter = (url: string, handler: any) => Promise<[Pdoc, fs.ReadStream?]> | [Pdoc, fs.ReadStream?];
export type ProblemImporter = (url: string, handler: any) => Promise<[ProblemDoc, fs.ReadStream?]> | [ProblemDoc, fs.ReadStream?];
export interface Script {
run: (args: any, report: Function) => any,
@@ -481,18 +473,17 @@ export interface BaseService {
}
export interface Collections {
'blacklist': Bdoc,
'blacklist': BlacklistDoc,
'contest': Tdoc,
'domain': DomainDoc,
'domain.user': any,
'record': Rdoc,
'record': RecordDoc,
'document': any,
'problem': Pdoc,
'problem': ProblemDoc,
'user': Udoc,
'check': any,
'message': Mdoc,
'message': MessageDoc,
'token': TokenDoc,
'file': Ufdoc,
'status': any,
'oauth': any,
'system': System,
+2 -2
View File
@@ -8,7 +8,7 @@ import {
ContestNotAttendedError, ContestScoreboardHiddenError,
} from '../error';
import {
ContestRule, ContestRules, Pdict,
ContestRule, ContestRules, ProblemDict,
ScoreboardNode, ScoreboardRow, Tdoc,
Udict,
} from '../interface';
@@ -564,7 +564,7 @@ export function canShowScoreboard(tdoc: Tdoc<30 | 60>, allowPermOverride = true)
export async function getScoreboard(
domainId: string, tid: ObjectID,
isExport = false, page: number, docType: 30 | 60 = document.TYPE_CONTEST,
): Promise<[Tdoc<30 | 60>, ScoreboardRow[], Udict, Pdict, number]> {
): Promise<[Tdoc<30 | 60>, ScoreboardRow[], Udict, ProblemDict, number]> {
const tdoc = await get(domainId, tid, docType);
if (!canShowScoreboard.call(this, tdoc)) throw new ContestScoreboardHiddenError(tid);
if (!canShowRecord.call(this, tdoc)) throw new ContestScoreboardHiddenError(tid);
+23 -22
View File
@@ -5,15 +5,15 @@ import * as contest from './contest';
import * as training from './training';
import * as document from './document';
import { DiscussionNodeNotFoundError, DocumentNotFoundError } from '../error';
import { Drdoc, Drrdoc, Document } from '../interface';
import { DiscussionReplyDoc, DiscussionTailReplyDoc, Document } from '../interface';
import { buildProjection } from '../utils';
import * as bus from '../service/bus';
export interface Ddoc extends Document { }
export namespace Ddoc {
export type Field = keyof Ddoc;
export interface DiscussionDoc extends Document { }
export namespace DiscussionDoc {
export type Field = keyof DiscussionDoc;
export const fields: Field[] = [];
type Getter = () => Partial<Ddoc>;
type Getter = () => Partial<DiscussionDoc>;
const getters: Getter[] = [];
export function extend(getter: Getter) {
getters.push(getter);
@@ -39,7 +39,7 @@ export namespace Ddoc {
}));
export function create() {
const result = {} as Ddoc;
const result = {} as DiscussionDoc;
for (const getter of getters) {
Object.assign(result, getter());
}
@@ -47,12 +47,12 @@ export namespace Ddoc {
}
}
export const PROJECTION_LIST: Ddoc.Field[] = [
export const PROJECTION_LIST: DiscussionDoc.Field[] = [
'_id', 'domainId', 'docType', 'docId', 'highlight',
'nReply', 'views', 'pin', 'updateAt', 'owner',
'parentId', 'parentType', 'title',
];
export const PROJECTION_PUBLIC: Ddoc.Field[] = [
export const PROJECTION_PUBLIC: DiscussionDoc.Field[] = [
...PROJECTION_LIST, 'content', 'history',
];
@@ -69,7 +69,7 @@ export async function add(
owner: number, title: string, content: string,
ip: string | null = null, highlight: boolean, pin: boolean,
): Promise<ObjectID> {
const payload: Partial<Ddoc> = {
const payload: Partial<DiscussionDoc> = {
domainId,
content,
owner,
@@ -93,15 +93,16 @@ export async function add(
return payload.docId;
}
// FIXME typings doesn't work
export async function get<T extends Ddoc.Field>(domainId: string, did: ObjectID, projection: T[] = PROJECTION_PUBLIC as any): Promise<Pick<Ddoc, T>> {
export async function get<T extends DiscussionDoc.Field>(
domainId: string, did: ObjectID, projection: T[] = PROJECTION_PUBLIC as any,
): Promise<Pick<DiscussionDoc, T>> {
return await document.get(domainId, document.TYPE_DISCUSSION, did, projection);
}
export function edit(
domainId: string, did: ObjectID,
title: string, content: string, highlight: boolean, pin: boolean,
): Promise<Ddoc | null> {
): Promise<DiscussionDoc | null> {
const payload = {
title, content, highlight, pin,
};
@@ -118,11 +119,11 @@ export function del(domainId: string, did: ObjectID): Promise<never> {
]) as any;
}
export function count(domainId: string, query: FilterQuery<Ddoc>) {
export function count(domainId: string, query: FilterQuery<DiscussionDoc>) {
return document.count(domainId, document.TYPE_DISCUSSION, query);
}
export function getMulti(domainId: string, query: FilterQuery<Ddoc> = {}, projection = PROJECTION_LIST) {
export function getMulti(domainId: string, query: FilterQuery<DiscussionDoc> = {}, projection = PROJECTION_LIST) {
return document.getMulti(domainId, document.TYPE_DISCUSSION, query)
.sort({ pin: -1, updateAt: -1 })
.project(buildProjection(projection));
@@ -142,13 +143,13 @@ export async function addReply(
return drid;
}
export function getReply(domainId: string, drid: ObjectID): Promise<Drdoc | null> {
export function getReply(domainId: string, drid: ObjectID): Promise<DiscussionReplyDoc | null> {
return document.get(domainId, document.TYPE_DISCUSSION_REPLY, drid);
}
export async function editReply(
domainId: string, drid: ObjectID, content: string,
): Promise<Drdoc | null> {
): Promise<DiscussionReplyDoc | null> {
return document.set(domainId, document.TYPE_DISCUSSION_REPLY, drid, { content });
}
@@ -168,14 +169,14 @@ export function getMultiReply(domainId: string, did: ObjectID) {
).sort('_id', -1);
}
export function getListReply(domainId: string, did: ObjectID): Promise<Drdoc[]> {
export function getListReply(domainId: string, did: ObjectID): Promise<DiscussionReplyDoc[]> {
return getMultiReply(domainId, did).toArray();
}
export async function addTailReply(
domainId: string, drid: ObjectID,
owner: number, content: string, ip: string,
): Promise<[Drdoc, ObjectID]> {
): Promise<[DiscussionReplyDoc, ObjectID]> {
const [drdoc, subId] = await document.push(
domainId, document.TYPE_DISCUSSION_REPLY, drid,
'reply', content, owner, { ip },
@@ -189,14 +190,14 @@ export async function addTailReply(
export function getTailReply(
domainId: string, drid: ObjectID, drrid: ObjectID,
): Promise<[Drdoc, Drrdoc] | [null, null]> {
): Promise<[DiscussionReplyDoc, DiscussionTailReplyDoc] | [null, null]> {
// @ts-ignore
return document.getSub(domainId, document.TYPE_DISCUSSION_REPLY, drid, 'reply', drrid);
}
export function editTailReply(
domainId: string, drid: ObjectID, drrid: ObjectID, content: string,
): Promise<Drrdoc> {
): Promise<DiscussionTailReplyDoc> {
return document.setSub(domainId, document.TYPE_DISCUSSION_REPLY, drid, 'reply', drrid, { content });
}
@@ -249,7 +250,7 @@ export function getNodes(domainId: string) {
export async function getListVnodes(domainId: string, ddocs: any, getHidden: boolean) {
const tasks = [];
const res = {};
async function task(ddoc: Ddoc) {
async function task(ddoc: DiscussionDoc) {
const vnode = await getVnode(domainId, ddoc.parentType, ddoc.parentId.toString());
if (!res[ddoc.parentType]) res[ddoc.parentType] = {};
if (vnode.hidden && !getHidden) return;
@@ -278,7 +279,7 @@ bus.on('problem/delete', async (domainId, docId) => {
global.Hydro.model.discussion = {
typeDisplay,
Ddoc,
DiscussionDoc,
PROJECTION_LIST,
PROJECTION_PUBLIC,
+4 -4
View File
@@ -4,7 +4,7 @@ import {
ObjectID, Cursor, FilterQuery, UpdateQuery, OnlyFieldsOfType,
} from 'mongodb';
import {
Pdoc, Ddoc, Drdoc, Tdoc, TrainingDoc,
ProblemDoc, DiscussionDoc, DiscussionReplyDoc, Tdoc, TrainingDoc,
ProblemStatusDoc, Content,
} from '../interface';
import { buildProjection } from '../utils';
@@ -28,12 +28,12 @@ export const TYPE_TRAINING: 40 = 40;
export const TYPE_HOMEWORK: 60 = 60;
export interface DocType {
[TYPE_PROBLEM]: Pdoc,
[TYPE_PROBLEM]: ProblemDoc,
[TYPE_PROBLEM_SOLUTION]: any,
[TYPE_PROBLEM_LIST]: any,
[TYPE_DISCUSSION_NODE]: any,
[TYPE_DISCUSSION]: Ddoc,
[TYPE_DISCUSSION_REPLY]: Drdoc,
[TYPE_DISCUSSION]: DiscussionDoc,
[TYPE_DISCUSSION_REPLY]: DiscussionReplyDoc,
[TYPE_CONTEST]: Tdoc,
[TYPE_TRAINING]: TrainingDoc,
[TYPE_HOMEWORK]: Tdoc,
+7 -7
View File
@@ -1,6 +1,6 @@
import { FilterQuery, ObjectID } from 'mongodb';
import user from './user';
import { Mdoc } from '../interface';
import { MessageDoc } from '../interface';
import { ArgMethod } from '../utils';
import db from '../service/db';
import * as bus from '../service/bus';
@@ -15,7 +15,7 @@ class MessageModel {
static async send(
from: number, to: number,
content: string, flag: number = MessageModel.FLAG_UNREAD,
): Promise<Mdoc> {
): Promise<MessageDoc> {
const res = await coll.insertOne({
from, to, content, flag,
});
@@ -27,22 +27,22 @@ class MessageModel {
return mdoc;
}
static async get(_id: ObjectID): Promise<Mdoc | null> {
static async get(_id: ObjectID): Promise<MessageDoc | null> {
return await coll.findOne({ _id });
}
@ArgMethod
static async getByUser(uid: number): Promise<Mdoc[]> {
static async getByUser(uid: number): Promise<MessageDoc[]> {
return await coll.find({ $or: [{ from: uid }, { to: uid }] }).sort('_id', 1).toArray();
}
static async getMany(query: FilterQuery<Mdoc>, sort: any, page: number, limit: number): Promise<Mdoc[]> {
static async getMany(query: FilterQuery<MessageDoc>, sort: any, page: number, limit: number): Promise<MessageDoc[]> {
return await coll.find(query).sort(sort)
.skip((page - 1) * limit).limit(limit)
.toArray();
}
static async setFlag(messageId: ObjectID, flag: number): Promise<Mdoc | null> {
static async setFlag(messageId: ObjectID, flag: number): Promise<MessageDoc | null> {
const result = await coll.findOneAndUpdate(
{ _id: messageId },
{ $bit: { flag: { xor: flag } } },
@@ -56,7 +56,7 @@ class MessageModel {
}
@ArgMethod
static count(query: FilterQuery<Mdoc> = {}) {
static count(query: FilterQuery<MessageDoc> = {}) {
return coll.find(query).count();
}
+17 -17
View File
@@ -5,7 +5,7 @@ import { streamToBuffer } from '@hydrooj/utils/lib/utils';
import * as document from './document';
import { STATUS } from './builtin';
import { buildProjection } from '../utils';
import type { ProblemStatusDoc, Pdict, Document } from '../interface';
import type { ProblemStatusDoc, ProblemDict, Document } from '../interface';
import {
ArrayKeys, MaybeArray, NumberKeys, Projection,
} from '../typeutils';
@@ -13,10 +13,10 @@ import { ProblemNotFoundError, ValidationError } from '../error';
import storage from '../service/storage';
import * as bus from '../service/bus';
export interface Pdoc extends Document { }
export type Field = keyof Pdoc;
export interface ProblemDoc extends Document { }
export type Field = keyof ProblemDoc;
const fields: Field[] = [];
export type Getter = (docId?: number, pid?: string) => Partial<Pdoc>;
export type Getter = (docId?: number, pid?: string) => Partial<ProblemDoc>;
const getters: Getter[] = [];
export class ProblemModel {
@@ -37,7 +37,7 @@ export class ProblemModel {
}
static create(docId?: number, pid?: string) {
const result = {} as Pdoc;
const result = {} as ProblemDoc;
for (const getter of getters) {
Object.assign(result, getter(docId, pid));
}
@@ -59,7 +59,7 @@ export class ProblemModel {
domainId: string, docId: number, pid: string = null, title: string,
content: string, owner: number, tag: string[] = [], hidden = false,
) {
const args: Partial<Pdoc> = {
const args: Partial<ProblemDoc> = {
title, tag, hidden, nSubmit: 0, nAccept: 0,
};
if (pid) args.pid = pid;
@@ -74,8 +74,8 @@ export class ProblemModel {
static async get(
domainId: string, pid: string | number,
uid: number = null, projection: Projection<Pdoc> = ProblemModel.PROJECTION_PUBLIC,
): Promise<Pdoc> {
uid: number = null, projection: Projection<ProblemDoc> = ProblemModel.PROJECTION_PUBLIC,
): Promise<ProblemDoc> {
if (typeof pid !== 'number') {
if (Number.isSafeInteger(parseInt(pid, 10))) pid = parseInt(pid, 10);
}
@@ -89,15 +89,15 @@ export class ProblemModel {
return pdoc;
}
static getMulti(domainId: string, query: FilterQuery<Pdoc>, projection = ProblemModel.PROJECTION_LIST) {
static getMulti(domainId: string, query: FilterQuery<ProblemDoc>, projection = ProblemModel.PROJECTION_LIST) {
return document.getMulti(domainId, document.TYPE_PROBLEM, query, projection);
}
static getMultiStatus(domainId: string, query: FilterQuery<Pdoc>) {
static getMultiStatus(domainId: string, query: FilterQuery<ProblemDoc>) {
return document.getMultiStatus(domainId, document.TYPE_PROBLEM, query);
}
static async edit(domainId: string, _id: number, $set: Partial<Pdoc>): Promise<Pdoc> {
static async edit(domainId: string, _id: number, $set: Partial<ProblemDoc>): Promise<ProblemDoc> {
const delpid = $set.pid === '';
if (delpid) delete $set.pid;
await bus.serial('problem/before-edit', $set);
@@ -106,19 +106,19 @@ export class ProblemModel {
return result;
}
static push<T extends ArrayKeys<Pdoc>>(domainId: string, _id: number, key: ArrayKeys<Pdoc>, value: Pdoc[T][0]) {
static push<T extends ArrayKeys<ProblemDoc>>(domainId: string, _id: number, key: ArrayKeys<ProblemDoc>, value: ProblemDoc[T][0]) {
return document.push(domainId, document.TYPE_PROBLEM, _id, key, value);
}
static pull<T extends ArrayKeys<Pdoc>>(domainId: string, pid: number, key: ArrayKeys<Pdoc>, values: Pdoc[T][0][]) {
static pull<T extends ArrayKeys<ProblemDoc>>(domainId: string, pid: number, key: ArrayKeys<ProblemDoc>, values: ProblemDoc[T][0][]) {
return document.deleteSub(domainId, document.TYPE_PROBLEM, pid, key, values);
}
static inc(domainId: string, _id: number, field: NumberKeys<Pdoc>, n: number): Promise<Pdoc> {
static inc(domainId: string, _id: number, field: NumberKeys<ProblemDoc>, n: number): Promise<ProblemDoc> {
return document.inc(domainId, document.TYPE_PROBLEM, _id, field, n);
}
static count(domainId: string, query: FilterQuery<Pdoc>) {
static count(domainId: string, query: FilterQuery<ProblemDoc>) {
return document.count(domainId, document.TYPE_PROBLEM, query);
}
@@ -174,7 +174,7 @@ export class ProblemModel {
await bus.emit('problem/delAdditionalFile', domainId, pid, names);
}
static async random(domainId: string, query: FilterQuery<Pdoc>): Promise<string | null> {
static async random(domainId: string, query: FilterQuery<ProblemDoc>): Promise<string | null> {
const cursor = document.getMulti(domainId, document.TYPE_PROBLEM, query);
const pcount = await cursor.count();
if (pcount) {
@@ -186,7 +186,7 @@ export class ProblemModel {
static async getList(
domainId: string, pids: Array<number | string>,
getHidden = false, doThrow = true, projection = ProblemModel.PROJECTION_PUBLIC,
): Promise<Pdict> {
): Promise<ProblemDict> {
pids = Array.from(new Set(pids)).map((i) => (+i ? +i : i));
const r = {};
const l = {};
+18 -18
View File
@@ -8,15 +8,15 @@ import moment from 'moment';
import { STATUS } from './builtin';
import task from './task';
import problem from './problem';
import { Rdoc, ContestInfo, ProblemConfig } from '../interface';
import { RecordDoc, ContestInfo, ProblemConfig } from '../interface';
import { ArgMethod, buildProjection, Time } from '../utils';
import { MaybeArray } from '../typeutils';
import * as bus from '../service/bus';
import db from '../service/db';
class RecordModel {
static coll: Collection<Rdoc> = db.collection('record');
static PROJECTION_LIST: (keyof Rdoc)[] = [
static coll: Collection<RecordDoc> = db.collection('record');
static PROJECTION_LIST: (keyof RecordDoc)[] = [
'_id', 'score', 'time', 'memory', 'lang',
'uid', 'pid', 'rejudged', 'hidden', 'progress',
'contest', 'effective', 'judger', 'judgeAt', 'status',
@@ -29,7 +29,7 @@ class RecordModel {
return base - ((pending + 0.5) * (sum(timeRecent.map((i) => i.time || 0)) / 10000));
}
static async get(domainId: string, _id: ObjectID): Promise<Rdoc | null> {
static async get(domainId: string, _id: ObjectID): Promise<RecordDoc | null> {
const res = await RecordModel.coll.findOne({ _id });
if (res && res.domainId === domainId) return res;
return null;
@@ -74,7 +74,7 @@ class RecordModel {
domainId: string, pid: number, uid: number,
lang: string, code: string, addTask: boolean, contestOrConfig?: ContestInfo | string,
) {
const data: Rdoc = {
const data: RecordDoc = {
status: STATUS.STATUS_WAITING,
_id: new ObjectID(),
uid,
@@ -116,11 +116,11 @@ class RecordModel {
static async update(
domainId: string, _id: MaybeArray<ObjectID>,
$set?: MatchKeysAndValues<Rdoc>,
$push?: PushOperator<Rdoc>,
$unset?: OnlyFieldsOfType<Rdoc, any, true | '' | 1>,
): Promise<Rdoc | null> {
const $update: UpdateQuery<Rdoc> = {};
$set?: MatchKeysAndValues<RecordDoc>,
$push?: PushOperator<RecordDoc>,
$unset?: OnlyFieldsOfType<RecordDoc, any, true | '' | 1>,
): Promise<RecordDoc | null> {
const $update: UpdateQuery<RecordDoc> = {};
if ($set && Object.keys($set).length) $update.$set = $set;
if ($push && Object.keys($push).length) $update.$push = $push;
if ($unset && Object.keys($unset).length) $update.$unset = $unset;
@@ -140,12 +140,12 @@ class RecordModel {
}
static async updateMulti(
domainId: string, $match: FilterQuery<Rdoc>,
$set?: MatchKeysAndValues<Rdoc>,
$push?: PushOperator<Rdoc>,
$unset?: OnlyFieldsOfType<Rdoc, any, true | '' | 1>,
domainId: string, $match: FilterQuery<RecordDoc>,
$set?: MatchKeysAndValues<RecordDoc>,
$push?: PushOperator<RecordDoc>,
$unset?: OnlyFieldsOfType<RecordDoc, any, true | '' | 1>,
) {
const $update: UpdateQuery<Rdoc> = {};
const $update: UpdateQuery<RecordDoc> = {};
if ($set && Object.keys($set).length) $update.$set = $set;
if ($push && Object.keys($push).length) $update.$push = $push;
if ($unset && Object.keys($unset).length) $update.$unset = $unset;
@@ -174,8 +174,8 @@ class RecordModel {
}
static async getList(
domainId: string, rids: ObjectID[], showHidden: boolean, fields?: (keyof Rdoc)[],
): Promise<Record<string, Partial<Rdoc>>> {
domainId: string, rids: ObjectID[], showHidden: boolean, fields?: (keyof RecordDoc)[],
): Promise<Record<string, Partial<RecordDoc>>> {
const r = {};
rids = Array.from(new Set(rids));
let cursor = RecordModel.coll.find({ domainId, _id: { $in: rids } });
@@ -202,7 +202,7 @@ class RecordModel {
}
@ArgMethod
static getByUid(domainId: string, uid: number, limit: number): Promise<Rdoc[]> {
static getByUid(domainId: string, uid: number, limit: number): Promise<RecordDoc[]> {
return RecordModel.coll.find({ domainId, uid, hidden: false }).sort({ _id: -1 }).limit(limit).toArray();
}
}
+4 -4
View File
@@ -4,7 +4,7 @@ import type { DomainDoc, Udoc, ProblemStatusDoc } from './interface';
import domain from './model/domain';
import * as document from './model/document';
import user from './model/user';
import problem, { Field, Pdoc } from './model/problem';
import problem, { Field, ProblemDoc } from './model/problem';
export async function iterateAllDomain(cb: (ddoc: DomainDoc, current?: number, total?: number) => Promise<any>) {
const ddocs = await domain.getMulti().toArray();
@@ -26,14 +26,14 @@ export async function iterateAllPsdoc(filter: FilterQuery<ProblemStatusDoc>, cb:
});
}
interface PartialPdoc extends Pdoc {
interface PartialProblemDoc extends ProblemDoc {
[key: string]: any,
}
export async function iterateAllProblemInDomain(
domainId: string,
fields: (Field | string)[],
cb: (pdoc: PartialPdoc, current?: number, total?: number) => Promise<any>,
cb: (pdoc: PartialProblemDoc, current?: number, total?: number) => Promise<any>,
) {
if (!fields.includes('domainId')) fields.push('domainId');
if (!fields.includes('docId')) fields.push('docId');
@@ -50,7 +50,7 @@ export async function iterateAllProblemInDomain(
export async function iterateAllProblem(
fields: (Field | string)[],
cb: (pdoc: PartialPdoc, current?: number, total?: number) => Promise<any>,
cb: (pdoc: PartialProblemDoc, current?: number, total?: number) => Promise<any>,
) {
await iterateAllDomain(async (d) => {
await iterateAllProblemInDomain(d._id, fields, cb);
+3 -3
View File
@@ -1,7 +1,7 @@
/* eslint-disable no-await-in-loop */
import { NumericDictionary } from 'lodash';
import { ObjectID, FilterQuery } from 'mongodb';
import { Tdoc, Pdoc, Udoc } from '../interface';
import { Tdoc, ProblemDoc, Udoc } from '../interface';
import domain from '../model/domain';
import * as contest from '../model/contest';
import problem from '../model/problem';
@@ -14,10 +14,10 @@ export const description = 'Calculate rp of a domain, or all domains';
type ND = NumericDictionary<number>;
async function runProblem(pdoc: Pdoc, udict: ND): Promise<void>;
async function runProblem(pdoc: ProblemDoc, udict: ND): Promise<void>;
async function runProblem(domainId: string, pid: number, udict: ND): Promise<void>;
async function runProblem(...arg: any[]) {
const pdoc: Pdoc = (typeof arg[0] === 'string')
const pdoc: ProblemDoc = (typeof arg[0] === 'string')
? await problem.get(arg[0], arg[1], -1)
: arg[0];
const udict: ND = (typeof arg[0] === 'string') ? arg[2] : arg[1];
+14 -12
View File
@@ -6,7 +6,9 @@ import { argv } from 'yargs';
import type { Handler } from './server';
import { Logger } from '../logger';
import type {
Mdoc, Pdoc, Rdoc, TrainingDoc, User, Ddoc, DomainDoc, FileInfo,
MessageDoc, ProblemDoc, RecordDoc,
TrainingDoc, User, DiscussionDoc,
DomainDoc, FileInfo,
} from '../interface';
import type { DocType } from '../model/document';
import type { ProblemSolutionHandler } from '../handler/problem';
@@ -45,7 +47,7 @@ export interface EventMap extends Record<string, any> {
'monitor/update': (type: 'server' | 'judge', $set: any) => VoidReturn
'user/message': (uid: number, mdoc: Mdoc) => void
'user/message': (uid: number, mdoc: MessageDoc) => void
'user/get': (udoc: User) => void
'domain/create': (ddoc: DomainDoc) => VoidReturn
@@ -68,17 +70,17 @@ export interface EventMap extends Record<string, any> {
'handler/finish/UserRegister': (thisArg: UserRegisterHandler) => VoidReturn
'handler/solution/get': (thisArg: ProblemSolutionHandler) => VoidReturn
'discussion/before-add': (payload: Partial<Ddoc>) => VoidReturn
'discussion/add': (payload: Partial<Ddoc>) => VoidReturn
'discussion/before-add': (payload: Partial<DiscussionDoc>) => VoidReturn
'discussion/add': (payload: Partial<DiscussionDoc>) => VoidReturn
'problem/before-add': (doc: Partial<Pdoc>) => VoidReturn
'problem/add': (doc: Partial<Pdoc>, docId: number) => VoidReturn
'problem/before-edit': (doc: Partial<Pdoc>) => VoidReturn
'problem/edit': (doc: Pdoc) => VoidReturn
'problem/before-add': (doc: Partial<ProblemDoc>) => VoidReturn
'problem/add': (doc: Partial<ProblemDoc>, docId: number) => VoidReturn
'problem/before-edit': (doc: Partial<ProblemDoc>) => VoidReturn
'problem/edit': (doc: ProblemDoc) => VoidReturn
'problem/before-del': (domainId: string, docId: number) => VoidReturn
'problem/del': (domainId: string, docId: number) => VoidReturn
'problem/list': (query: FilterQuery<Pdoc>, handler: any) => VoidReturn
'problem/get': (doc: Pdoc, handler: any) => VoidReturn
'problem/list': (query: FilterQuery<ProblemDoc>, handler: any) => VoidReturn
'problem/get': (doc: ProblemDoc, handler: any) => VoidReturn
'problem/delete': (domainId: string, docId: number) => VoidReturn
'problem/addTestdata': (domainId: string, docId: number, name: string, payload: Omit<FileInfo, '_id'>) => VoidReturn
'problem/delTestdata': (domainId: string, docId: number, name: string[]) => VoidReturn
@@ -88,8 +90,8 @@ export interface EventMap extends Record<string, any> {
'training/list': (query: FilterQuery<TrainingDoc>, handler: any) => VoidReturn
'training/get': (tdoc: TrainingDoc, handler: any) => VoidReturn
'record/change': (rdoc: Rdoc, $set?: any, $push?: any) => void
'record/judge': (rdoc: Rdoc, updated: boolean) => VoidReturn
'record/change': (rdoc: RecordDoc, $set?: any, $push?: any) => void
'record/judge': (rdoc: RecordDoc, updated: boolean) => VoidReturn
}
function getHooks<K extends keyof EventMap>(name: K) {
+2 -2
View File
@@ -7,7 +7,7 @@ import yaml from 'js-yaml';
import { pick } from 'lodash';
import { convertIniConfig } from '@hydrooj/utils/lib/cases';
import { Progress } from './ui';
import { Rdoc } from './interface';
import { RecordDoc } from './interface';
import { Logger } from './logger';
import { streamToBuffer } from './utils';
import {
@@ -254,7 +254,7 @@ const scripts: UpgradeScript[] = [
while (await data.hasNext()) {
const d: any = await data.next();
logger.info('%o', d);
const filter: FilterQuery<Rdoc> = { domainId: d._id.domainId, pid: d._id.pid, uid: d._id.uid };
const filter: FilterQuery<RecordDoc> = { domainId: d._id.domainId, pid: d._id.pid, uid: d._id.uid };
if (d.nAccept) {
const [first] = await db.collection('record')
.find({ ...filter, status: STATUS.STATUS_ACCEPTED })