add guildId to optionally narrow results
All checks were successful
Build / build (22) (push) Successful in 38s
Build / build (20) (push) Successful in 1m11s
Build / build (18) (push) Successful in 1m18s
Build / build (18) (pull_request) Successful in 41s
Build / build (20) (pull_request) Successful in 1m8s
Build / build (22) (pull_request) Successful in 1m18s

This commit is contained in:
Sainan 2025-03-24 23:00:23 +01:00
parent 46cdb44f59
commit 942f062e90
5 changed files with 20 additions and 10 deletions

View File

@ -6,7 +6,7 @@ export const leaderboardController: RequestHandler = async (req, res) => {
logger.debug(`data provided to ${req.path}: ${String(req.body)}`); logger.debug(`data provided to ${req.path}: ${String(req.body)}`);
const payload = JSON.parse(String(req.body)) as ILeaderboardRequest; const payload = JSON.parse(String(req.body)) as ILeaderboardRequest;
res.json({ 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; field: string;
before: number; before: number;
after: number; after: number;
guildId?: string;
pivotId?: string; pivotId?: string;
} }

View File

@ -4,15 +4,17 @@ import { ILeaderboardEntryDatabase } from "../types/leaderboardTypes";
const leaderboardEntrySchema = new Schema<ILeaderboardEntryDatabase>( const leaderboardEntrySchema = new Schema<ILeaderboardEntryDatabase>(
{ {
leaderboard: { type: String, required: true }, leaderboard: { type: String, required: true },
displayName: { type: String, required: true },
ownerId: { type: Schema.Types.ObjectId, required: true }, ownerId: { type: Schema.Types.ObjectId, required: true },
displayName: { type: String, required: true },
score: { type: Number, required: true }, score: { type: Number, required: true },
guildId: Schema.Types.ObjectId,
expiry: { type: Date, required: true } expiry: { type: Date, required: true }
}, },
{ id: false } { id: false }
); );
leaderboardEntrySchema.index({ leaderboard: 1 }); 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. leaderboardEntrySchema.index({ expiry: 1 }, { expireAfterSeconds: 0 }); // With this, MongoDB will automatically delete expired entries.
export const Leaderboard = model<ILeaderboardEntryDatabase>("Leaderboard", leaderboardEntrySchema); export const Leaderboard = model<ILeaderboardEntryDatabase>("Leaderboard", leaderboardEntrySchema);

View File

@ -5,7 +5,8 @@ export const submitLeaderboardScore = async (
leaderboard: string, leaderboard: string,
ownerId: string, ownerId: string,
displayName: string, displayName: string,
score: number score: number,
guildId?: string
): Promise<void> => { ): Promise<void> => {
const schedule = leaderboard.split(".")[0] as "daily" | "weekly"; const schedule = leaderboard.split(".")[0] as "daily" | "weekly";
let expiry: Date; let expiry: Date;
@ -20,8 +21,8 @@ export const submitLeaderboardScore = async (
expiry = new Date(weekEnd); expiry = new Date(weekEnd);
} }
await Leaderboard.findOneAndUpdate( await Leaderboard.findOneAndUpdate(
{ leaderboard, displayName }, { leaderboard, ownerId },
{ $max: { score }, $set: { ownerId, expiry } }, { $max: { score }, $set: { displayName, guildId, expiry } },
{ upsert: true } { upsert: true }
); );
}; };
@ -30,23 +31,26 @@ export const getLeaderboard = async (
leaderboard: string, leaderboard: string,
before: number, before: number,
after: number, after: number,
pivotId: string | undefined = undefined guildId?: string,
pivotId?: string
): Promise<ILeaderboardEntryClient[]> => { ): Promise<ILeaderboardEntryClient[]> => {
let entries: TLeaderboardEntryDocument[]; let entries: TLeaderboardEntryDocument[];
let r: number; let r: number;
if (pivotId) { if (pivotId) {
const pivotDoc = await Leaderboard.findOne({ leaderboard, ownerId: pivotId }); const pivotDoc = await Leaderboard.findOne({ leaderboard, guildId, ownerId: pivotId });
if (!pivotDoc) { if (!pivotDoc) {
return []; return [];
} }
const beforeDocs = await Leaderboard.find({ const beforeDocs = await Leaderboard.find({
leaderboard, leaderboard,
guildId,
score: { $gt: pivotDoc.score } score: { $gt: pivotDoc.score }
}) })
.sort({ score: 1 }) .sort({ score: 1 })
.limit(before); .limit(before);
const afterDocs = await Leaderboard.find({ const afterDocs = await Leaderboard.find({
leaderboard, leaderboard,
guildId,
score: { $lt: pivotDoc.score } score: { $lt: pivotDoc.score }
}) })
.sort({ score: -1 }) .sort({ score: -1 })
@ -55,10 +59,11 @@ export const getLeaderboard = async (
r = r =
(await Leaderboard.countDocuments({ (await Leaderboard.countDocuments({
leaderboard, leaderboard,
guildId,
score: { $gt: pivotDoc.score } score: { $gt: pivotDoc.score }
})) - beforeDocs.length; })) - beforeDocs.length;
} else { } else {
entries = await Leaderboard.find({ leaderboard }) entries = await Leaderboard.find({ leaderboard, guildId })
.sort({ score: -1 }) .sort({ score: -1 })
.skip(before) .skip(before)
.limit(after - before); .limit(after - before);

View File

@ -327,7 +327,8 @@ export const updateStats = async (accountOwnerId: string, payload: IStatsUpdate)
"weekly.accounts." + category, "weekly.accounts." + category,
accountOwnerId, accountOwnerId,
payload.displayName, payload.displayName,
data as number data as number,
payload.guildId
); );
break; break;

View File

@ -2,9 +2,10 @@ import { Types } from "mongoose";
export interface ILeaderboardEntryDatabase { export interface ILeaderboardEntryDatabase {
leaderboard: string; leaderboard: string;
displayName: string;
ownerId: Types.ObjectId; ownerId: Types.ObjectId;
displayName: string;
score: number; score: number;
guildId?: Types.ObjectId;
expiry: Date; expiry: Date;
} }