feat(leaderboard): missions & guilds leaderboard (#1338)
Reviewed-on: #1338 Reviewed-by: Sainan <sainan@calamity.inc> Co-authored-by: AMelonInsideLemon <166175391+AMelonInsideLemon@users.noreply.github.com> Co-committed-by: AMelonInsideLemon <166175391+AMelonInsideLemon@users.noreply.github.com>
This commit is contained in:
		
							parent
							
								
									0f7866a575
								
							
						
					
					
						commit
						049f709713
					
				@ -6,7 +6,14 @@ 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.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;
 | 
					    after: number;
 | 
				
			||||||
    guildId?: string;
 | 
					    guildId?: string;
 | 
				
			||||||
    pivotId?: string;
 | 
					    pivotId?: string;
 | 
				
			||||||
 | 
					    guildTier?: number;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -8,7 +8,8 @@ const leaderboardEntrySchema = new Schema<ILeaderboardEntryDatabase>(
 | 
				
			|||||||
        displayName: { type: String, required: true },
 | 
					        displayName: { type: String, required: true },
 | 
				
			||||||
        score: { type: Number, required: true },
 | 
					        score: { type: Number, required: true },
 | 
				
			||||||
        guildId: Schema.Types.ObjectId,
 | 
					        guildId: Schema.Types.ObjectId,
 | 
				
			||||||
        expiry: { type: Date, required: true }
 | 
					        expiry: { type: Date, required: true },
 | 
				
			||||||
 | 
					        guildTier: Number
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    { id: false }
 | 
					    { id: false }
 | 
				
			||||||
);
 | 
					);
 | 
				
			||||||
 | 
				
			|||||||
@ -1,14 +1,15 @@
 | 
				
			|||||||
 | 
					import { Guild } from "../models/guildModel";
 | 
				
			||||||
import { Leaderboard, TLeaderboardEntryDocument } from "../models/leaderboardModel";
 | 
					import { Leaderboard, TLeaderboardEntryDocument } from "../models/leaderboardModel";
 | 
				
			||||||
import { ILeaderboardEntryClient } from "../types/leaderboardTypes";
 | 
					import { ILeaderboardEntryClient } from "../types/leaderboardTypes";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export const submitLeaderboardScore = async (
 | 
					export const submitLeaderboardScore = async (
 | 
				
			||||||
 | 
					    schedule: "weekly" | "daily",
 | 
				
			||||||
    leaderboard: string,
 | 
					    leaderboard: string,
 | 
				
			||||||
    ownerId: string,
 | 
					    ownerId: string,
 | 
				
			||||||
    displayName: string,
 | 
					    displayName: string,
 | 
				
			||||||
    score: number,
 | 
					    score: number,
 | 
				
			||||||
    guildId?: string
 | 
					    guildId?: string
 | 
				
			||||||
): Promise<void> => {
 | 
					): Promise<void> => {
 | 
				
			||||||
    const schedule = leaderboard.split(".")[0] as "daily" | "weekly";
 | 
					 | 
				
			||||||
    let expiry: Date;
 | 
					    let expiry: Date;
 | 
				
			||||||
    if (schedule == "daily") {
 | 
					    if (schedule == "daily") {
 | 
				
			||||||
        expiry = new Date(Math.trunc(Date.now() / 86400000) * 86400000 + 86400000);
 | 
					        expiry = new Date(Math.trunc(Date.now() / 86400000) * 86400000 + 86400000);
 | 
				
			||||||
@ -21,10 +22,18 @@ export const submitLeaderboardScore = async (
 | 
				
			|||||||
        expiry = new Date(weekEnd);
 | 
					        expiry = new Date(weekEnd);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    await Leaderboard.findOneAndUpdate(
 | 
					    await Leaderboard.findOneAndUpdate(
 | 
				
			||||||
        { leaderboard, ownerId },
 | 
					        { leaderboard: `${schedule}.accounts.${leaderboard}`, ownerId },
 | 
				
			||||||
        { $max: { score }, $set: { displayName, guildId, expiry } },
 | 
					        { $max: { score }, $set: { displayName, guildId, expiry } },
 | 
				
			||||||
        { upsert: true }
 | 
					        { 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 (
 | 
					export const getLeaderboard = async (
 | 
				
			||||||
@ -32,12 +41,16 @@ export const getLeaderboard = async (
 | 
				
			|||||||
    before: number,
 | 
					    before: number,
 | 
				
			||||||
    after: number,
 | 
					    after: number,
 | 
				
			||||||
    guildId?: string,
 | 
					    guildId?: string,
 | 
				
			||||||
    pivotId?: string
 | 
					    pivotId?: string,
 | 
				
			||||||
 | 
					    guildTier?: number
 | 
				
			||||||
): Promise<ILeaderboardEntryClient[]> => {
 | 
					): Promise<ILeaderboardEntryClient[]> => {
 | 
				
			||||||
    const filter: { leaderboard: string; guildId?: string } = { leaderboard };
 | 
					    const filter: { leaderboard: string; guildId?: string; guildTier?: number } = { leaderboard };
 | 
				
			||||||
    if (guildId) {
 | 
					    if (guildId) {
 | 
				
			||||||
        filter.guildId = guildId;
 | 
					        filter.guildId = guildId;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					    if (guildTier) {
 | 
				
			||||||
 | 
					        filter.guildTier = guildTier;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    let entries: TLeaderboardEntryDocument[];
 | 
					    let entries: TLeaderboardEntryDocument[];
 | 
				
			||||||
    let r: number;
 | 
					    let r: number;
 | 
				
			||||||
 | 
				
			|||||||
@ -286,6 +286,15 @@ export const updateStats = async (accountOwnerId: string, payload: IStatsUpdate)
 | 
				
			|||||||
                                } else {
 | 
					                                } else {
 | 
				
			||||||
                                    playerStats.Missions.push({ type: type, highScore });
 | 
					                                    playerStats.Missions.push({ type: type, highScore });
 | 
				
			||||||
                                }
 | 
					                                }
 | 
				
			||||||
 | 
					                                await submitLeaderboardScore(
 | 
				
			||||||
 | 
					                                    "weekly",
 | 
				
			||||||
 | 
					                                    type,
 | 
				
			||||||
 | 
					                                    accountOwnerId,
 | 
				
			||||||
 | 
					                                    payload.displayName,
 | 
				
			||||||
 | 
					                                    highScore,
 | 
				
			||||||
 | 
					                                    payload.guildId
 | 
				
			||||||
 | 
					                                );
 | 
				
			||||||
 | 
					                                break;
 | 
				
			||||||
                            }
 | 
					                            }
 | 
				
			||||||
                            break;
 | 
					                            break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -304,27 +313,42 @@ export const updateStats = async (accountOwnerId: string, payload: IStatsUpdate)
 | 
				
			|||||||
                                }
 | 
					                                }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                                await submitLeaderboardScore(
 | 
					                                await submitLeaderboardScore(
 | 
				
			||||||
                                    "daily.accounts." + race,
 | 
					                                    "daily",
 | 
				
			||||||
 | 
					                                    race,
 | 
				
			||||||
                                    accountOwnerId,
 | 
					                                    accountOwnerId,
 | 
				
			||||||
                                    payload.displayName,
 | 
					                                    payload.displayName,
 | 
				
			||||||
                                    highScore
 | 
					                                    highScore,
 | 
				
			||||||
 | 
					                                    payload.guildId
 | 
				
			||||||
                                );
 | 
					                                );
 | 
				
			||||||
                            }
 | 
					                            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                            break;
 | 
					                            break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                        case "ZephyrScore":
 | 
					                        case "ZephyrScore":
 | 
				
			||||||
                        case "SentinelGameScore":
 | 
					 | 
				
			||||||
                        case "CaliberChicksScore":
 | 
					                        case "CaliberChicksScore":
 | 
				
			||||||
                            playerStats[category] ??= 0;
 | 
					                            playerStats[category] ??= 0;
 | 
				
			||||||
                            if (data > playerStats[category]) playerStats[category] = data as number;
 | 
					                            if (data > playerStats[category]) playerStats[category] = data as number;
 | 
				
			||||||
                            break;
 | 
					                            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":
 | 
					                        case "DojoObstacleScore":
 | 
				
			||||||
                            playerStats[category] ??= 0;
 | 
					                            playerStats[category] ??= 0;
 | 
				
			||||||
                            if (data > playerStats[category]) playerStats[category] = data as number;
 | 
					                            if (data > playerStats[category]) playerStats[category] = data as number;
 | 
				
			||||||
                            await submitLeaderboardScore(
 | 
					                            await submitLeaderboardScore(
 | 
				
			||||||
                                "weekly.accounts." + category,
 | 
					                                "weekly",
 | 
				
			||||||
 | 
					                                category,
 | 
				
			||||||
                                accountOwnerId,
 | 
					                                accountOwnerId,
 | 
				
			||||||
                                payload.displayName,
 | 
					                                payload.displayName,
 | 
				
			||||||
                                data as number,
 | 
					                                data as number,
 | 
				
			||||||
@ -350,7 +374,8 @@ export const updateStats = async (accountOwnerId: string, payload: IStatsUpdate)
 | 
				
			|||||||
                            }
 | 
					                            }
 | 
				
			||||||
                            if (data > playerStats[category]) playerStats[category] = data as number;
 | 
					                            if (data > playerStats[category]) playerStats[category] = data as number;
 | 
				
			||||||
                            await submitLeaderboardScore(
 | 
					                            await submitLeaderboardScore(
 | 
				
			||||||
                                "weekly.accounts." + category,
 | 
					                                "weekly",
 | 
				
			||||||
 | 
					                                category,
 | 
				
			||||||
                                accountOwnerId,
 | 
					                                accountOwnerId,
 | 
				
			||||||
                                payload.displayName,
 | 
					                                payload.displayName,
 | 
				
			||||||
                                data as number
 | 
					                                data as number
 | 
				
			||||||
 | 
				
			|||||||
@ -7,6 +7,7 @@ export interface ILeaderboardEntryDatabase {
 | 
				
			|||||||
    score: number;
 | 
					    score: number;
 | 
				
			||||||
    guildId?: Types.ObjectId;
 | 
					    guildId?: Types.ObjectId;
 | 
				
			||||||
    expiry: Date;
 | 
					    expiry: Date;
 | 
				
			||||||
 | 
					    guildTier?: number;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export interface ILeaderboardEntryClient {
 | 
					export interface ILeaderboardEntryClient {
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user