2025-03-26 14:21:22 -07:00
|
|
|
import { Guild } from "../models/guildModel";
|
2025-03-25 03:25:58 -07:00
|
|
|
import { Leaderboard, TLeaderboardEntryDocument } from "../models/leaderboardModel";
|
|
|
|
import { ILeaderboardEntryClient } from "../types/leaderboardTypes";
|
|
|
|
|
|
|
|
export const submitLeaderboardScore = async (
|
2025-03-26 14:21:22 -07:00
|
|
|
schedule: "weekly" | "daily",
|
2025-03-25 03:25:58 -07:00
|
|
|
leaderboard: string,
|
|
|
|
ownerId: string,
|
|
|
|
displayName: string,
|
|
|
|
score: number,
|
|
|
|
guildId?: string
|
|
|
|
): Promise<void> => {
|
|
|
|
let expiry: Date;
|
|
|
|
if (schedule == "daily") {
|
|
|
|
expiry = new Date(Math.trunc(Date.now() / 86400000) * 86400000 + 86400000);
|
|
|
|
} else {
|
|
|
|
const EPOCH = 1734307200 * 1000; // Monday
|
|
|
|
const day = Math.trunc((Date.now() - EPOCH) / 86400000);
|
|
|
|
const week = Math.trunc(day / 7);
|
|
|
|
const weekStart = EPOCH + week * 604800000;
|
|
|
|
const weekEnd = weekStart + 604800000;
|
|
|
|
expiry = new Date(weekEnd);
|
|
|
|
}
|
|
|
|
await Leaderboard.findOneAndUpdate(
|
2025-03-26 14:21:22 -07:00
|
|
|
{ leaderboard: `${schedule}.accounts.${leaderboard}`, ownerId },
|
2025-03-25 03:25:58 -07:00
|
|
|
{ $max: { score }, $set: { displayName, guildId, expiry } },
|
|
|
|
{ upsert: true }
|
|
|
|
);
|
2025-03-26 14:21:22 -07:00
|
|
|
if (guildId) {
|
|
|
|
const guild = (await Guild.findById(guildId, "Name Tier"))!;
|
|
|
|
await Leaderboard.findOneAndUpdate(
|
|
|
|
{ leaderboard: `${schedule}.guilds.${leaderboard}`, ownerId: guildId },
|
|
|
|
{ $max: { score }, $set: { displayName: guild.Name, guildTier: guild.Tier, expiry } },
|
|
|
|
{ upsert: true }
|
|
|
|
);
|
|
|
|
}
|
2025-03-25 03:25:58 -07:00
|
|
|
};
|
|
|
|
|
|
|
|
export const getLeaderboard = async (
|
|
|
|
leaderboard: string,
|
|
|
|
before: number,
|
|
|
|
after: number,
|
2025-03-26 14:21:22 -07:00
|
|
|
pivotId?: string,
|
2025-03-26 22:46:30 +01:00
|
|
|
guildId?: string,
|
2025-03-26 14:21:22 -07:00
|
|
|
guildTier?: number
|
2025-03-25 03:25:58 -07:00
|
|
|
): Promise<ILeaderboardEntryClient[]> => {
|
2025-03-26 14:21:22 -07:00
|
|
|
const filter: { leaderboard: string; guildId?: string; guildTier?: number } = { leaderboard };
|
2025-03-25 03:25:58 -07:00
|
|
|
if (guildId) {
|
|
|
|
filter.guildId = guildId;
|
|
|
|
}
|
2025-03-26 14:21:22 -07:00
|
|
|
if (guildTier) {
|
|
|
|
filter.guildTier = guildTier;
|
|
|
|
}
|
2025-03-25 03:25:58 -07:00
|
|
|
|
|
|
|
let entries: TLeaderboardEntryDocument[];
|
|
|
|
let r: number;
|
|
|
|
if (pivotId) {
|
|
|
|
const pivotDoc = await Leaderboard.findOne({ ...filter, ownerId: pivotId });
|
|
|
|
if (!pivotDoc) {
|
|
|
|
return [];
|
|
|
|
}
|
|
|
|
const beforeDocs = await Leaderboard.find({
|
|
|
|
...filter,
|
|
|
|
score: { $gt: pivotDoc.score }
|
|
|
|
})
|
|
|
|
.sort({ score: 1 })
|
|
|
|
.limit(before);
|
|
|
|
const afterDocs = await Leaderboard.find({
|
|
|
|
...filter,
|
|
|
|
score: { $lt: pivotDoc.score }
|
|
|
|
})
|
|
|
|
.sort({ score: -1 })
|
|
|
|
.limit(after);
|
|
|
|
entries = [...beforeDocs.reverse(), pivotDoc, ...afterDocs];
|
|
|
|
r =
|
|
|
|
(await Leaderboard.countDocuments({
|
|
|
|
...filter,
|
|
|
|
score: { $gt: pivotDoc.score }
|
|
|
|
})) - beforeDocs.length;
|
|
|
|
} else {
|
|
|
|
entries = await Leaderboard.find(filter)
|
|
|
|
.sort({ score: -1 })
|
|
|
|
.skip(before)
|
|
|
|
.limit(after - before);
|
|
|
|
r = before;
|
|
|
|
}
|
|
|
|
const res: ILeaderboardEntryClient[] = [];
|
|
|
|
for (const entry of entries) {
|
|
|
|
res.push({
|
|
|
|
_id: entry.ownerId.toString(),
|
|
|
|
s: entry.score,
|
|
|
|
r: ++r,
|
|
|
|
n: entry.displayName
|
|
|
|
});
|
|
|
|
}
|
|
|
|
return res;
|
|
|
|
};
|