diff --git a/src/controllers/stats/leaderboardController.ts b/src/controllers/stats/leaderboardController.ts index 7a292cfb..b76e5e16 100644 --- a/src/controllers/stats/leaderboardController.ts +++ b/src/controllers/stats/leaderboardController.ts @@ -6,7 +6,7 @@ export const leaderboardController: RequestHandler = async (req, res) => { logger.debug(`data provided to ${req.path}: ${String(req.body)}`); const payload = JSON.parse(String(req.body)) as ILeaderboardRequest; res.json({ - results: await getLeaderboard(payload.field, payload.before, payload.after, payload.pivotId) + results: await getLeaderboard(payload.field, payload.before, payload.after, payload.guildId, payload.pivotId) }); }; @@ -14,5 +14,6 @@ interface ILeaderboardRequest { field: string; before: number; after: number; + guildId?: string; pivotId?: string; } diff --git a/src/models/leaderboardModel.ts b/src/models/leaderboardModel.ts index 1dc50429..5de2f608 100644 --- a/src/models/leaderboardModel.ts +++ b/src/models/leaderboardModel.ts @@ -4,15 +4,17 @@ import { ILeaderboardEntryDatabase } from "../types/leaderboardTypes"; const leaderboardEntrySchema = new Schema( { leaderboard: { type: String, required: true }, - displayName: { type: String, required: true }, ownerId: { type: Schema.Types.ObjectId, required: true }, + displayName: { type: String, required: true }, score: { type: Number, required: true }, + guildId: Schema.Types.ObjectId, expiry: { type: Date, required: true } }, { id: false } ); leaderboardEntrySchema.index({ leaderboard: 1 }); +leaderboardEntrySchema.index({ leaderboard: 1, ownerId: 1 }, { unique: true }); leaderboardEntrySchema.index({ expiry: 1 }, { expireAfterSeconds: 0 }); // With this, MongoDB will automatically delete expired entries. export const Leaderboard = model("Leaderboard", leaderboardEntrySchema); diff --git a/src/services/leaderboardService.ts b/src/services/leaderboardService.ts index 5827bd6f..011a3f62 100644 --- a/src/services/leaderboardService.ts +++ b/src/services/leaderboardService.ts @@ -5,7 +5,8 @@ export const submitLeaderboardScore = async ( leaderboard: string, ownerId: string, displayName: string, - score: number + score: number, + guildId?: string ): Promise => { const schedule = leaderboard.split(".")[0] as "daily" | "weekly"; let expiry: Date; @@ -20,8 +21,8 @@ export const submitLeaderboardScore = async ( expiry = new Date(weekEnd); } await Leaderboard.findOneAndUpdate( - { leaderboard, displayName }, - { $max: { score }, $set: { ownerId, expiry } }, + { leaderboard, ownerId }, + { $max: { score }, $set: { displayName, guildId, expiry } }, { upsert: true } ); }; @@ -30,23 +31,26 @@ export const getLeaderboard = async ( leaderboard: string, before: number, after: number, - pivotId: string | undefined = undefined + guildId?: string, + pivotId?: string ): Promise => { let entries: TLeaderboardEntryDocument[]; let r: number; if (pivotId) { - const pivotDoc = await Leaderboard.findOne({ leaderboard, ownerId: pivotId }); + const pivotDoc = await Leaderboard.findOne({ leaderboard, guildId, ownerId: pivotId }); if (!pivotDoc) { return []; } const beforeDocs = await Leaderboard.find({ leaderboard, + guildId, score: { $gt: pivotDoc.score } }) .sort({ score: 1 }) .limit(before); const afterDocs = await Leaderboard.find({ leaderboard, + guildId, score: { $lt: pivotDoc.score } }) .sort({ score: -1 }) @@ -55,10 +59,11 @@ export const getLeaderboard = async ( r = (await Leaderboard.countDocuments({ leaderboard, + guildId, score: { $gt: pivotDoc.score } })) - beforeDocs.length; } else { - entries = await Leaderboard.find({ leaderboard }) + entries = await Leaderboard.find({ leaderboard, guildId }) .sort({ score: -1 }) .skip(before) .limit(after - before); diff --git a/src/services/statsService.ts b/src/services/statsService.ts index 153c98d4..2c34997a 100644 --- a/src/services/statsService.ts +++ b/src/services/statsService.ts @@ -327,7 +327,8 @@ export const updateStats = async (accountOwnerId: string, payload: IStatsUpdate) "weekly.accounts." + category, accountOwnerId, payload.displayName, - data as number + data as number, + payload.guildId ); break; diff --git a/src/types/leaderboardTypes.ts b/src/types/leaderboardTypes.ts index b769c1cd..5173a3a3 100644 --- a/src/types/leaderboardTypes.ts +++ b/src/types/leaderboardTypes.ts @@ -2,9 +2,10 @@ import { Types } from "mongoose"; export interface ILeaderboardEntryDatabase { leaderboard: string; - displayName: string; ownerId: Types.ObjectId; + displayName: string; score: number; + guildId?: Types.ObjectId; expiry: Date; }