feat(leaderboard): missions & guilds leaderboard
All checks were successful
Build / build (22) (pull_request) Successful in 37s
Build / build (18) (pull_request) Successful in 1m13s
Build / build (20) (pull_request) Successful in 1m23s

Re #1165
This commit is contained in:
AMelonInsideLemon 2025-03-26 21:58:38 +01:00
parent 0f7866a575
commit 7bd8eccdf7
5 changed files with 59 additions and 11 deletions

View File

@ -6,7 +6,14 @@ 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.guildId, payload.pivotId)
results: await getLeaderboard(
payload.field,
payload.before,
payload.after,
payload.guildId,
payload.pivotId,
payload.guildTier
)
});
};
@ -16,4 +23,5 @@ interface ILeaderboardRequest {
after: number;
guildId?: string;
pivotId?: string;
guildTier?: number;
}

View File

@ -8,7 +8,8 @@ const leaderboardEntrySchema = new Schema<ILeaderboardEntryDatabase>(
displayName: { type: String, required: true },
score: { type: Number, required: true },
guildId: Schema.Types.ObjectId,
expiry: { type: Date, required: true }
expiry: { type: Date, required: true },
guildTier: Number
},
{ id: false }
);

View File

@ -1,14 +1,15 @@
import { Guild } from "../models/guildModel";
import { Leaderboard, TLeaderboardEntryDocument } from "../models/leaderboardModel";
import { ILeaderboardEntryClient } from "../types/leaderboardTypes";
export const submitLeaderboardScore = async (
schedule: "weekly" | "daily",
leaderboard: string,
ownerId: string,
displayName: string,
score: number,
guildId?: string
): Promise<void> => {
const schedule = leaderboard.split(".")[0] as "daily" | "weekly";
let expiry: Date;
if (schedule == "daily") {
expiry = new Date(Math.trunc(Date.now() / 86400000) * 86400000 + 86400000);
@ -21,10 +22,18 @@ export const submitLeaderboardScore = async (
expiry = new Date(weekEnd);
}
await Leaderboard.findOneAndUpdate(
{ leaderboard, ownerId },
{ leaderboard: `${schedule}.accounts.${leaderboard}`, ownerId },
{ $max: { score }, $set: { displayName, guildId, expiry } },
{ upsert: true }
);
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 }
);
}
};
export const getLeaderboard = async (
@ -32,12 +41,16 @@ export const getLeaderboard = async (
before: number,
after: number,
guildId?: string,
pivotId?: string
pivotId?: string,
guildTier?: number
): Promise<ILeaderboardEntryClient[]> => {
const filter: { leaderboard: string; guildId?: string } = { leaderboard };
const filter: { leaderboard: string; guildId?: string; guildTier?: number } = { leaderboard };
if (guildId) {
filter.guildId = guildId;
}
if (guildTier) {
filter.guildTier = guildTier;
}
let entries: TLeaderboardEntryDocument[];
let r: number;

View File

@ -286,6 +286,15 @@ export const updateStats = async (accountOwnerId: string, payload: IStatsUpdate)
} else {
playerStats.Missions.push({ type: type, highScore });
}
await submitLeaderboardScore(
"weekly",
type,
accountOwnerId,
payload.displayName,
highScore,
payload.guildId
);
break;
}
break;
@ -304,27 +313,42 @@ export const updateStats = async (accountOwnerId: string, payload: IStatsUpdate)
}
await submitLeaderboardScore(
"daily.accounts." + race,
"daily",
race,
accountOwnerId,
payload.displayName,
highScore
highScore,
payload.guildId
);
}
break;
case "ZephyrScore":
case "SentinelGameScore":
case "CaliberChicksScore":
playerStats[category] ??= 0;
if (data > playerStats[category]) playerStats[category] = data as number;
break;
case "SentinelGameScore":
playerStats[category] ??= 0;
if (data > playerStats[category]) playerStats[category] = data as number;
await submitLeaderboardScore(
"weekly",
category,
accountOwnerId,
payload.displayName,
data as number,
payload.guildId
);
break;
case "DojoObstacleScore":
playerStats[category] ??= 0;
if (data > playerStats[category]) playerStats[category] = data as number;
await submitLeaderboardScore(
"weekly.accounts." + category,
"weekly",
category,
accountOwnerId,
payload.displayName,
data as number,
@ -350,7 +374,8 @@ export const updateStats = async (accountOwnerId: string, payload: IStatsUpdate)
}
if (data > playerStats[category]) playerStats[category] = data as number;
await submitLeaderboardScore(
"weekly.accounts." + category,
"weekly",
category,
accountOwnerId,
payload.displayName,
data as number

View File

@ -7,6 +7,7 @@ export interface ILeaderboardEntryDatabase {
score: number;
guildId?: Types.ObjectId;
expiry: Date;
guildTier?: number;
}
export interface ILeaderboardEntryClient {