From 0194ab4eb052188ee502747207066f529e332d9a Mon Sep 17 00:00:00 2001 From: undefined Date: Sat, 1 Aug 2020 11:49:42 +0800 Subject: [PATCH] =?UTF-8?q?=E9=99=90=E5=88=B6=E7=94=A8=E6=88=B7=E8=AF=A6?= =?UTF-8?q?=E6=83=85=E5=8D=95=E9=A1=B5=E6=8F=90=E4=BA=A4=E8=AE=B0=E5=BD=95?= =?UTF-8?q?=E6=95=B0=E9=87=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- hydro/handler/contest.ts | 2 +- hydro/handler/problem.ts | 6 ++++-- hydro/handler/user.ts | 24 ++++++++++++++++-------- hydro/interface.ts | 13 +++++++++++++ hydro/model/problem.ts | 32 +++++++++++--------------------- hydro/model/record.ts | 4 ++-- package.json | 2 +- 7 files changed, 48 insertions(+), 35 deletions(-) diff --git a/hydro/handler/contest.ts b/hydro/handler/contest.ts index 3374a006d..7ff894b61 100644 --- a/hydro/handler/contest.ts +++ b/hydro/handler/contest.ts @@ -37,7 +37,7 @@ class ContestListHandler extends ContestHandler { } else { if (!contest.RULES[rule]) throw new ValidationError('rule'); tdocs = contest.getMulti(domainId, { rule }).sort({ beginAt: -1 }); - qs = 'rule={0}'.format(rule); + qs = `rule=${rule}`; } // eslint-disable-next-line prefer-const [tdocs, tpcount] = await paginate(tdocs, page, await system.get('CONTEST_PER_PAGE')); diff --git a/hydro/handler/problem.ts b/hydro/handler/problem.ts index f14d5cf36..232113870 100644 --- a/hydro/handler/problem.ts +++ b/hydro/handler/problem.ts @@ -6,7 +6,9 @@ import { SolutionNotFoundError, ProblemNotFoundError, ValidationError, PermissionError, } from '../error'; -import { Pdoc, User, Rdoc } from '../interface'; +import { + Pdoc, User, Rdoc, PathComponent, +} from '../interface'; import paginate from '../lib/paginate'; import { checkPid, isTitle, isContent, isPid, @@ -62,7 +64,7 @@ class ProblemMainHandler extends ProblemHandler { this.response.template = 'problem_main.html'; const query: any = {}; let psdict = {}; - const path: any = [ + const path: PathComponent[] = [ ['Hydro', 'homepage'], ['problem_main', null], ]; diff --git a/hydro/handler/user.ts b/hydro/handler/user.ts index e412fe200..292e3691d 100644 --- a/hydro/handler/user.ts +++ b/hydro/handler/user.ts @@ -1,5 +1,10 @@ import superagent from 'superagent'; import moment from 'moment-timezone'; +import { + UserAlreadyExistError, InvalidTokenError, VerifyPasswordError, + UserNotFoundError, SystemError, BlacklistedError, + UserFacingError, +} from '../error'; import { Route, Handler, Types, param, } from '../service/server'; @@ -13,11 +18,7 @@ import { PERM, PRIV } from '../model/builtin'; import { isEmail, isPassword, isUname } from '../lib/validator'; import { sendMail } from '../lib/mail'; import * as misc from '../lib/misc'; -import { - UserAlreadyExistError, InvalidTokenError, VerifyPasswordError, - UserNotFoundError, SystemError, BlacklistedError, - UserFacingError, -} from '../error'; +import paginate from '../lib/paginate'; class UserLoginHandler extends Handler { async get() { @@ -158,8 +159,15 @@ class UserDetailHandler extends Handler { const isSelfProfile = this.user._id === uid; const udoc = await user.getById(domainId, uid); if (!udoc) throw new UserNotFoundError(uid); - const sdoc = await token.getMostRecentSessionByUid(uid); - const rdocs = await record.getByUid(domainId, uid); + const [sdoc, rdocs, [pdocs, pcount]] = await Promise.all([ + token.getMostRecentSessionByUid(uid), + record.getByUid(domainId, uid, 30), + paginate( + problem.getMulti(domainId, { owner: this.user._id }), + 1, + 100, + ), + ]); const pdict = await problem.getList( domainId, rdocs.map((rdoc) => rdoc.pid), this.user.hasPerm(PERM.PERM_VIEW_PROBLEM_HIDDEN), false, @@ -176,7 +184,7 @@ class UserDetailHandler extends Handler { ]; this.response.template = 'user_detail.html'; this.response.body = { - isSelfProfile, udoc, sdoc, rdocs, pdict, path, + isSelfProfile, udoc, sdoc, rdocs, pdocs, pcount, pdict, path, }; } } diff --git a/hydro/interface.ts b/hydro/interface.ts index bd8cf5113..16fa9ac44 100644 --- a/hydro/interface.ts +++ b/hydro/interface.ts @@ -144,6 +144,17 @@ export interface Pdoc { export type Pdict = NumericDictionary; +export interface ProblemStatusDoc { + _id: ObjectID, + docId: number, + docType: number, + domainId: string, + uid: number, + rid?: ObjectID, + status?: number, + star?: boolean, +} + export interface TestCase { time: number, memory: number, @@ -338,6 +349,8 @@ export interface JudgeResultBody { stderr?: string, } +export type PathComponent = [string, string, any?, boolean?]; + declare global { namespace NodeJS { interface Global { diff --git a/hydro/model/problem.ts b/hydro/model/problem.ts index 66a05e2d0..9fe020534 100644 --- a/hydro/model/problem.ts +++ b/hydro/model/problem.ts @@ -1,9 +1,12 @@ import { ObjectID } from 'mongodb'; +import { Dictionary } from 'lodash'; import { STATUS } from './builtin'; import * as file from './file'; import * as document from './document'; import * as domain from './domain'; -import { Pdoc, Pdict, ProblemDataSource } from '../interface'; +import { + Pdoc, Pdict, ProblemDataSource, ProblemStatusDoc, +} from '../interface'; import { ProblemNotFoundError } from '../error'; import * as testdataConfig from '../lib/testdataConfig'; @@ -46,7 +49,7 @@ export async function get( uid: number = null, ): Promise { if (typeof pid !== 'number') { - if (!Number.isNaN(parseInt(pid, 10))) pid = parseInt(pid, 10); + if (!Number.isSafeInteger(parseInt(pid, 10))) pid = parseInt(pid, 10); } const pdoc = Number.isInteger(pid) ? await document.get(domainId, document.TYPE_PROBLEM, pid) @@ -58,14 +61,6 @@ export async function get( return pdoc; } -export function getMany( - domainId: string, query: any, sort: any, page: number, limit: number, -): Promise { - return document.getMulti(domainId, query) - .sort(sort).skip((page - 1) * limit).limit(limit) - .toArray(); -} - export function getMulti(domainId: string, query: object) { return document.getMulti(domainId, document.TYPE_PROBLEM, query); } @@ -128,7 +123,7 @@ export async function getListStatus(domainId: string, uid: number, pids: number[ const psdocs = await getMultiStatus( domainId, { uid, docId: { $in: Array.from(new Set(pids)) } }, ).toArray(); - const r = {}; + const r: Dictionary = {}; for (const psdoc of psdocs) r[psdoc.docId] = psdoc; return r; } @@ -137,15 +132,11 @@ export async function updateStatus( domainId: string, pid: number, uid: number, rid: ObjectID, status: number, ) { - try { - await document.setIfNotStatus( - domainId, document.TYPE_PROBLEM, pid, uid, - 'status', status, STATUS.STATUS_ACCEPTED, { rid }, - ); - } catch (e) { - return false; - } - return true; + const res = await document.setIfNotStatus( + domainId, document.TYPE_PROBLEM, pid, uid, + 'status', status, STATUS.STATUS_ACCEPTED, { rid }, + ); + return !!res; } export function setStar(domainId: string, pid: number, uid: number, star: boolean) { @@ -165,7 +156,6 @@ global.Hydro.model.problem = { add, inc, get, - getMany, edit, count, random, diff --git a/hydro/model/record.ts b/hydro/model/record.ts index b1ae22cf4..a4fb98f58 100644 --- a/hydro/model/record.ts +++ b/hydro/model/record.ts @@ -171,8 +171,8 @@ export function getUserInProblemMulti( return coll.find({ domainId, uid, pid }); } -export function getByUid(domainId: string, uid: number): Promise { - return coll.find({ domainId, uid }).toArray(); +export function getByUid(domainId: string, uid: number, limit: number): Promise { + return coll.find({ domainId, uid }).limit(limit).toArray(); } global.Hydro.model.record = { diff --git a/package.json b/package.json index 279f7276c..61d7dd8f6 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "hydrooj", - "version": "2.11.4", + "version": "2.11.5", "main": "dist/loader.js", "bin": "bin/hydrooj.js", "repository": "https://github.com/hydro-dev/Hydro.git",