From cb80038ca5a135a81b930967420e22f61fc6eb11 Mon Sep 17 00:00:00 2001 From: AnthonyFuller <24512050+AnthonyFuller@users.noreply.github.com> Date: Tue, 27 Aug 2024 00:26:52 +0100 Subject: [PATCH] fea(h6): support Statistics page And it's better than official, because we fixed IOI's mistake by flipping the difficulty when passing it to the scaleform class! This took me a whole hour to realise. --- components/2016/legacyMenuData.ts | 188 +++++++++++++++++++++++++- components/candle/challengeService.ts | 5 +- 2 files changed, 189 insertions(+), 4 deletions(-) diff --git a/components/2016/legacyMenuData.ts b/components/2016/legacyMenuData.ts index 6e45fc7f..560156b1 100644 --- a/components/2016/legacyMenuData.ts +++ b/components/2016/legacyMenuData.ts @@ -17,10 +17,21 @@ */ import { Router } from "express" -import { RequestWithJwt } from "../types/types" -import { getConfig } from "../configSwizzleManager" +import { + type ChallengeCategoryCompletion, + ChallengeCompletion, + CompletionData, + type PeacockLocationsData, + RequestWithJwt, + Unlockable, +} from "../types/types" +import { getConfig, getVersionedConfig } from "../configSwizzleManager" import { controller } from "../controller" -import { getParentLocationByName } from "../contracts/dataGen" +import { + generateCompletionData, + getParentLocationByName, +} from "../contracts/dataGen" +import { ChallengeFilterType, Pro1FilterType } from "../candle/challengeHelpers" const legacyMenuDataRouter = Router() @@ -69,4 +80,175 @@ legacyMenuDataRouter.get( }, ) +type StatisticsData = { + DifficultyLevelData: { + Name: "normal" | "pro1" + SubLocationData: { + ParentLocation: Unlockable + Location: Unlockable + CompletionData: CompletionData + ChallengeCategoryCompletion: ChallengeCategoryCompletion[] + ChallengeCompletion: ChallengeCompletion + }[] + }[] +} + +legacyMenuDataRouter.get( + "/Statistics", + // @ts-expect-error Has jwt props. + (req: RequestWithJwt, res) => { + const data: StatisticsData = { + DifficultyLevelData: [ + { + Name: "normal", + SubLocationData: [], + }, + { + Name: "pro1", + SubLocationData: [], + }, + ], + } + + // This is essentially a rewrite of getPlayerProfileData except without + // the player profile data + const locationData = getVersionedConfig( + "LocationsData", + req.gameVersion, + false, + ) + + // Contains the parent ids of ones that have had their pro1 data + // added. It's a hacky workaround. + const processedParents: string[] = [] + + for (const subLocation of Object.values(locationData.children)) { + const parentLocation = + locationData.parents[ + subLocation.Properties.ParentLocation || "" + ] + + const normalChallenges = + controller.challengeService.getGroupedChallengeLists( + { + type: ChallengeFilterType.ParentLocation, + parent: parentLocation.Id, + pro1Filter: Pro1FilterType.Exclude, + }, + parentLocation.Id, + req.gameVersion, + ) + + const normalCompletion: ChallengeCategoryCompletion[] = [] + + for (const challengeGroup in normalChallenges) { + const challengeCompletion = + controller.challengeService.countTotalNCompletedChallenges( + { + challengeGroup: normalChallenges[challengeGroup], + }, + req.jwt.unique_name, + req.gameVersion, + ) + + normalCompletion.push({ + Name: normalChallenges[challengeGroup][0].CategoryName, + ...challengeCompletion, + }) + } + + data.DifficultyLevelData[0].SubLocationData.push({ + ParentLocation: parentLocation, + Location: subLocation, + ChallengeCategoryCompletion: normalCompletion, + CompletionData: { + ...generateCompletionData( + subLocation.Id, + req.jwt.unique_name, + req.gameVersion, + "mission", + "normal", + ), + ...{ + HideProgression: + subLocation.Properties.ProgressionKey !== + subLocation.Id || + parentLocation.Id === + "LOCATION_PARENT_ICA_FACILITY", + }, + }, + ChallengeCompletion: + controller.challengeService.countTotalNCompletedChallenges( + normalChallenges, + req.jwt.unique_name, + req.gameVersion, + 100, + ), + }) + + if ( + parentLocation.Id === "LOCATION_PARENT_ICA_FACILITY" || + processedParents.includes(parentLocation.Id) + ) + continue + + processedParents.push(parentLocation.Id) + + const pro1Challenges = + controller.challengeService.getGroupedChallengeLists( + { + type: ChallengeFilterType.ParentLocation, + parent: parentLocation.Id, + pro1Filter: Pro1FilterType.Only, + }, + parentLocation.Id, + req.gameVersion, + ) + + const pro1Completion: ChallengeCategoryCompletion[] = [] + + for (const challengeGroup in pro1Challenges) { + const challengeCompletion = + controller.challengeService.countTotalNCompletedChallenges( + { + challengeGroup: pro1Challenges[challengeGroup], + }, + req.jwt.unique_name, + req.gameVersion, + ) + + pro1Completion.push({ + Name: pro1Challenges[challengeGroup][0].CategoryName, + ...challengeCompletion, + }) + } + + data.DifficultyLevelData[1].SubLocationData.push({ + ParentLocation: parentLocation, + Location: subLocation, + ChallengeCategoryCompletion: pro1Completion, + CompletionData: generateCompletionData( + subLocation.Id, + req.jwt.unique_name, + req.gameVersion, + "mission", + "pro1", + ), + ChallengeCompletion: + controller.challengeService.countTotalNCompletedChallenges( + pro1Challenges, + req.jwt.unique_name, + req.gameVersion, + 100, + ), + }) + } + + res.json({ + template: getConfig("LegacyStatisticsTemplate", false), + data, + }) + }, +) + export { legacyMenuDataRouter } diff --git a/components/candle/challengeService.ts b/components/candle/challengeService.ts index 193118b6..6ed3839e 100644 --- a/components/candle/challengeService.ts +++ b/components/candle/challengeService.ts @@ -1614,12 +1614,14 @@ export class ChallengeService extends ChallengeRegistry { * @param challengeLists A GroupIndexedChallengeLists object, holding some challenges to be counted * @param userId The userId of the user to acquire completion information * @param gameVersion The version of the game + * @param multiplier What to multiply the final completion percentage by * @returns An object with two properties: ChallengesCount and CompletedChallengesCount. */ countTotalNCompletedChallenges( challengeLists: GroupIndexedChallengeLists, userId: string, gameVersion: GameVersion, + multiplier = 1, ): ChallengeCompletion { const userData = getUserData(userId, gameVersion) @@ -1642,7 +1644,8 @@ export class ChallengeService extends ChallengeRegistry { return { ChallengesCount: challengesCount, CompletedChallengesCount: completedChallengesCount, - CompletionPercent: completedChallengesCount / challengesCount, + CompletionPercent: + (completedChallengesCount / challengesCount) * multiplier, } }