XFE Git
XFE Studio Git
Git 首页 全局搜索
XFE 主站 文档 NuGet

SpaceNinjaServer

A simple server for a small space ninja game

公开
关注 0 Fork 1 Star 0
返回提交历史

XFEstudio/SpaceNinjaServer

feat(leaderboard): missions & guilds leaderboard (#1338)

Reviewed-on: https://onlyg.it/OpenWF/SpaceNinjaServer/pulls/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>

049f7097
AMelonInsideLemon <166175391+AMelonInsideLemon@users.noreply.github.com>
提交于

代码差异

5 个文件 +59 -11
Modified src/controllers/stats/leaderboardController.ts +9 -1
@@ -6,7 +6,14 @@ export const leaderboardController: RequestHandler = async (req, res) => {
6 6 logger.debug(`data provided to ${req.path}: ${String(req.body)}`);
7 7 const payload = JSON.parse(String(req.body)) as ILeaderboardRequest;
8 8 res.json({
9 results: await getLeaderboard(payload.field, payload.before, payload.after, payload.guildId, payload.pivotId)
9 results: await getLeaderboard(
10 payload.field,
11 payload.before,
12 payload.after,
13 payload.guildId,
14 payload.pivotId,
15 payload.guildTier
16 )
10 17 });
11 18 };
12 19
@@ -16,4 +23,5 @@ interface ILeaderboardRequest {
16 23 after: number;
17 24 guildId?: string;
18 25 pivotId?: string;
26 guildTier?: number;
19 27 }
Modified src/models/leaderboardModel.ts +2 -1
@@ -8,7 +8,8 @@ const leaderboardEntrySchema = new Schema<ILeaderboardEntryDatabase>(
8 8 displayName: { type: String, required: true },
9 9 score: { type: Number, required: true },
10 10 guildId: Schema.Types.ObjectId,
11 expiry: { type: Date, required: true }
11 expiry: { type: Date, required: true },
12 guildTier: Number
12 13 },
13 14 { id: false }
14 15 );
Modified src/services/leaderboardService.ts +17 -4
@@ -1,14 +1,15 @@
1 import { Guild } from "../models/guildModel";
1 2 import { Leaderboard, TLeaderboardEntryDocument } from "../models/leaderboardModel";
2 3 import { ILeaderboardEntryClient } from "../types/leaderboardTypes";
3 4
4 5 export const submitLeaderboardScore = async (
6 schedule: "weekly" | "daily",
5 7 leaderboard: string,
6 8 ownerId: string,
7 9 displayName: string,
8 10 score: number,
9 11 guildId?: string
10 12 ): Promise<void> => {
11 const schedule = leaderboard.split(".")[0] as "daily" | "weekly";
12 13 let expiry: Date;
13 14 if (schedule == "daily") {
14 15 expiry = new Date(Math.trunc(Date.now() / 86400000) * 86400000 + 86400000);
@@ -21,10 +22,18 @@ export const submitLeaderboardScore = async (
21 22 expiry = new Date(weekEnd);
22 23 }
23 24 await Leaderboard.findOneAndUpdate(
24 { leaderboard, ownerId },
25 { leaderboard: `${schedule}.accounts.${leaderboard}`, ownerId },
25 26 { $max: { score }, $set: { displayName, guildId, expiry } },
26 27 { upsert: true }
27 28 );
29 if (guildId) {
30 const guild = (await Guild.findById(guildId, "Name Tier"))!;
31 await Leaderboard.findOneAndUpdate(
32 { leaderboard: `${schedule}.guilds.${leaderboard}`, ownerId: guildId },
33 { $max: { score }, $set: { displayName: guild.Name, guildTier: guild.Tier, expiry } },
34 { upsert: true }
35 );
36 }
28 37 };
29 38
30 39 export const getLeaderboard = async (
@@ -32,12 +41,16 @@ export const getLeaderboard = async (
32 41 before: number,
33 42 after: number,
34 43 guildId?: string,
35 pivotId?: string
44 pivotId?: string,
45 guildTier?: number
36 46 ): Promise<ILeaderboardEntryClient[]> => {
37 const filter: { leaderboard: string; guildId?: string } = { leaderboard };
47 const filter: { leaderboard: string; guildId?: string; guildTier?: number } = { leaderboard };
38 48 if (guildId) {
39 49 filter.guildId = guildId;
40 50 }
51 if (guildTier) {
52 filter.guildTier = guildTier;
53 }
41 54
42 55 let entries: TLeaderboardEntryDocument[];
43 56 let r: number;
Modified src/services/statsService.ts +30 -5
@@ -286,6 +286,15 @@ export const updateStats = async (accountOwnerId: string, payload: IStatsUpdate)
286 286 } else {
287 287 playerStats.Missions.push({ type: type, highScore });
288 288 }
289 await submitLeaderboardScore(
290 "weekly",
291 type,
292 accountOwnerId,
293 payload.displayName,
294 highScore,
295 payload.guildId
296 );
297 break;
289 298 }
290 299 break;
291 300
@@ -304,27 +313,42 @@ export const updateStats = async (accountOwnerId: string, payload: IStatsUpdate)
304 313 }
305 314
306 315 await submitLeaderboardScore(
307 "daily.accounts." + race,
316 "daily",
317 race,
308 318 accountOwnerId,
309 319 payload.displayName,
310 highScore
320 highScore,
321 payload.guildId
311 322 );
312 323 }
313 324
314 325 break;
315 326
316 327 case "ZephyrScore":
317 case "SentinelGameScore":
318 328 case "CaliberChicksScore":
319 329 playerStats[category] ??= 0;
320 330 if (data > playerStats[category]) playerStats[category] = data as number;
321 331 break;
322 332
333 case "SentinelGameScore":
334 playerStats[category] ??= 0;
335 if (data > playerStats[category]) playerStats[category] = data as number;
336 await submitLeaderboardScore(
337 "weekly",
338 category,
339 accountOwnerId,
340 payload.displayName,
341 data as number,
342 payload.guildId
343 );
344 break;
345
323 346 case "DojoObstacleScore":
324 347 playerStats[category] ??= 0;
325 348 if (data > playerStats[category]) playerStats[category] = data as number;
326 349 await submitLeaderboardScore(
327 "weekly.accounts." + category,
350 "weekly",
351 category,
328 352 accountOwnerId,
329 353 payload.displayName,
330 354 data as number,
@@ -350,7 +374,8 @@ export const updateStats = async (accountOwnerId: string, payload: IStatsUpdate)
350 374 }
351 375 if (data > playerStats[category]) playerStats[category] = data as number;
352 376 await submitLeaderboardScore(
353 "weekly.accounts." + category,
377 "weekly",
378 category,
354 379 accountOwnerId,
355 380 payload.displayName,
356 381 data as number
Modified src/types/leaderboardTypes.ts +1 -0
@@ -7,6 +7,7 @@ export interface ILeaderboardEntryDatabase {
7 7 score: number;
8 8 guildId?: Types.ObjectId;
9 9 expiry: Date;
10 guildTier?: number;
10 11 }
11 12
12 13 export interface ILeaderboardEntryClient {