diff --git a/packages/hydrooj/src/model/document.ts b/packages/hydrooj/src/model/document.ts index 12b5f8329..647984ade 100644 --- a/packages/hydrooj/src/model/document.ts +++ b/packages/hydrooj/src/model/document.ts @@ -317,14 +317,14 @@ export async function setMultiStatus( ); } -export async function setStatusIfNotCondition( +export async function setStatusIfCondition( domainId: string, docType: T, docId: DocStatusType[T]['docId'], uid: number, filter: Filter, args: Partial = {}, returnDocument: 'before' | 'after' = 'after', ): Promise { try { return await collStatus.findOneAndUpdate( - { domainId, docType, docId, uid, $nor: [filter] }, + { domainId, docType, docId, uid, ...filter }, { $set: args }, { upsert: true, returnDocument }, ); @@ -338,8 +338,8 @@ export async function setIfNotStatus, returnDocument: 'before' | 'after' = 'after', ): Promise { - return await setStatusIfNotCondition( - domainId, docType, docId, uid, { [key]: ifNot } as any, + return await setStatusIfCondition( + domainId, docType, docId, uid, { [key]: { $ne: ifNot } } as any, { [key]: value, ...args }, returnDocument, ); } @@ -474,7 +474,7 @@ global.Hydro.model.document = { revSetStatus, set, setIfNotStatus, - setStatusIfNotCondition, + setStatusIfCondition, setStatus, setMultiStatus, setSub, diff --git a/packages/hydrooj/src/model/problem.ts b/packages/hydrooj/src/model/problem.ts index 8f73353b2..e90c1aabd 100644 --- a/packages/hydrooj/src/model/problem.ts +++ b/packages/hydrooj/src/model/problem.ts @@ -420,10 +420,10 @@ export class ProblemModel { domainId: string, pid: number, uid: number, rid: ObjectId, status: number, score: number, ) { - const filter: Filter = { rid: { $ne: rid }, status: STATUS.STATUS_ACCEPTED }; - const res = await document.setStatusIfNotCondition( + const condition = status === STATUS.STATUS_ACCEPTED ? {} : { status: { $ne: STATUS.STATUS_ACCEPTED } }; + const res = await document.setStatusIfCondition( domainId, document.TYPE_PROBLEM, pid, uid, - filter, { rid, status, score }, + condition, { rid, status, score }, ); return !!res; } diff --git a/packages/hydrooj/src/model/record.ts b/packages/hydrooj/src/model/record.ts index a1114a8fb..da19759e8 100644 --- a/packages/hydrooj/src/model/record.ts +++ b/packages/hydrooj/src/model/record.ts @@ -15,6 +15,7 @@ import { ArgMethod, buildProjection, Time } from '../utils'; import { STATUS } from './builtin'; import DomainModel from './domain'; import problem from './problem'; +import * as SystemModel from './system'; import task from './task'; export default class RecordModel { @@ -291,6 +292,14 @@ export async function apply(ctx: Context) { ctx.on('domain/delete', (domainId) => RecordModel.coll.deleteMany({ domainId })); ctx.on('record/judge', async (rdoc, updated) => { if (rdoc.status === STATUS.STATUS_ACCEPTED && updated) { + if (SystemModel.get('record.statMode') === 'unique') { + await RecordModel.collStat.deleteMany({ + _id: { $ne: rdoc._id }, + uid: rdoc.uid, + pid: rdoc.pid, + domainId: rdoc.domainId, + }); + } await RecordModel.collStat.updateOne({ _id: rdoc._id, }, { diff --git a/packages/hydrooj/src/model/setting.ts b/packages/hydrooj/src/model/setting.ts index a4d2de59b..1c869829d 100644 --- a/packages/hydrooj/src/model/setting.ts +++ b/packages/hydrooj/src/model/setting.ts @@ -334,6 +334,7 @@ SystemSetting( Setting('setting_basic', 'discussion.nodes', builtin.DEFAULT_NODES, 'yaml', 'discussion.nodes', 'Discussion Nodes'), Setting('setting_basic', 'problem.categories', builtin.CATEGORIES, 'yaml', 'problem.categories', 'Problem Categories'), Setting('setting_basic', 'training.enrolled-users', true, 'boolean', 'training.enrolled-users', 'Show enrolled users for training'), + Setting('setting_basic', 'record.statMode', 'unique', 'text', 'record.statMode', 'Record stat mode'), Setting('setting_basic', 'pagination.problem', 100, 'number', 'pagination.problem', 'Problems per page'), Setting('setting_basic', 'pagination.contest', 20, 'number', 'pagination.contest', 'Contests per page'), Setting('setting_basic', 'pagination.discussion', 50, 'number', 'pagination.discussion', 'Discussions per page'),