From 5f0796c97da4ba6562da06933f00a721c6e125b6 Mon Sep 17 00:00:00 2001 From: zkldi Date: Thu, 27 May 2021 13:50:03 +0100 Subject: [PATCH] Fixes Poor Code and Data Structures in common/class and ugs-class #88 --- server/pnpm-lock.yaml | 6 +- .../framework/user-game-stats/classes.test.ts | 32 +++++----- .../framework/user-game-stats/classes.ts | 57 ++++++++---------- .../user-game-stats/update-ugs.test.ts | 16 ++--- .../framework/user-game-stats/update-ugs.ts | 2 +- server/src/utils/class.ts | 58 ++++--------------- 6 files changed, 60 insertions(+), 111 deletions(-) diff --git a/server/pnpm-lock.yaml b/server/pnpm-lock.yaml index 87814277d..378b7ddb5 100644 --- a/server/pnpm-lock.yaml +++ b/server/pnpm-lock.yaml @@ -61,7 +61,7 @@ dependencies: express-session: 1.17.1 fast-json-stable-hash: 1.0.2 fast-xml-parser: 3.19.0 - kamaitachi-common: github.com/zkldi/Kamaitachi-common/dc01eb5b4759ce1e228b1aa204c4cc445954b70f + kamaitachi-common: github.com/zkldi/Kamaitachi-common/5d9c31ce0b9b309182d40191ae3000a3e9083336 mongodb: 3.6.6 monk: 7.3.4 multer: 1.4.2 @@ -4344,8 +4344,8 @@ packages: engines: {node: '>=6'} dev: true - github.com/zkldi/Kamaitachi-common/dc01eb5b4759ce1e228b1aa204c4cc445954b70f: - resolution: {tarball: https://codeload.github.com/zkldi/Kamaitachi-common/tar.gz/dc01eb5b4759ce1e228b1aa204c4cc445954b70f} + github.com/zkldi/Kamaitachi-common/5d9c31ce0b9b309182d40191ae3000a3e9083336: + resolution: {tarball: https://codeload.github.com/zkldi/Kamaitachi-common/tar.gz/5d9c31ce0b9b309182d40191ae3000a3e9083336} name: kamaitachi-common version: 0.1.0 dependencies: diff --git a/server/src/lib/score-import/framework/user-game-stats/classes.test.ts b/server/src/lib/score-import/framework/user-game-stats/classes.test.ts index ccda4f8e7..2958dfdcc 100644 --- a/server/src/lib/score-import/framework/user-game-stats/classes.test.ts +++ b/server/src/lib/score-import/framework/user-game-stats/classes.test.ts @@ -17,9 +17,9 @@ t.test("#UpdateUGSClasses", (t) => { }); t.test("Should call and merge the ClassHandler", async (t) => { - const res = await UpdateUGSClasses("iidx", "SP", 1, {}, () => ({ foo: "bar" }), logger); + const res = await UpdateUGSClasses("iidx", "SP", 1, {}, () => ({ dan: 2 }), logger); - t.strictSame(res, { foo: "bar" }); + t.strictSame(res, { dan: 2 }); t.end(); }); @@ -48,14 +48,14 @@ t.test("#CalculateClassDeltas", (t) => { t.beforeEach(ResetDBState); t.test("Should return improved classes from null", (t) => { - const res = CalculateClassDeltas("iidx", "SP", { dan: "kaiden" }, null, logger); + const res = CalculateClassDeltas("SP", { dan: 18 }, null, logger); t.strictSame(res, [ { set: "dan", playtype: "SP", old: null, - new: "kaiden", + new: 18, }, ]); @@ -64,9 +64,8 @@ t.test("#CalculateClassDeltas", (t) => { t.test("Should return improved classes from null class", (t) => { const res = CalculateClassDeltas( - "iidx", "SP", - { dan: "kaiden" }, + { dan: 18 }, { classes: {} } as UserGameStats, logger ); @@ -76,7 +75,7 @@ t.test("#CalculateClassDeltas", (t) => { set: "dan", playtype: "SP", old: null, - new: "kaiden", + new: 18, }, ]); @@ -85,10 +84,9 @@ t.test("#CalculateClassDeltas", (t) => { t.test("Should return improved classes", (t) => { const res = CalculateClassDeltas( - "iidx", "SP", - { dan: "kaiden" }, - ({ classes: { dan: "chuuden" } } as unknown) as UserGameStats, + { dan: 18 }, + ({ classes: { dan: 17 } } as unknown) as UserGameStats, logger ); @@ -96,8 +94,8 @@ t.test("#CalculateClassDeltas", (t) => { { set: "dan", playtype: "SP", - old: "chuuden", - new: "kaiden", + old: 17, + new: 18, }, ]); @@ -106,10 +104,9 @@ t.test("#CalculateClassDeltas", (t) => { t.test("Should not return identical classes", (t) => { const res = CalculateClassDeltas( - "iidx", "SP", - { dan: "kaiden" }, - ({ classes: { dan: "kaiden" } } as unknown) as UserGameStats, + { dan: 18 }, + ({ classes: { dan: 18 } } as unknown) as UserGameStats, logger ); @@ -120,10 +117,9 @@ t.test("#CalculateClassDeltas", (t) => { t.test("Should not return worse classes", (t) => { const res = CalculateClassDeltas( - "iidx", "SP", - { dan: "10" }, - ({ classes: { dan: "kaiden" } } as unknown) as UserGameStats, + { dan: 16 }, + ({ classes: { dan: 18 } } as unknown) as UserGameStats, logger ); diff --git a/server/src/lib/score-import/framework/user-game-stats/classes.ts b/server/src/lib/score-import/framework/user-game-stats/classes.ts index 8007c08ce..14fc32036 100644 --- a/server/src/lib/score-import/framework/user-game-stats/classes.ts +++ b/server/src/lib/score-import/framework/user-game-stats/classes.ts @@ -1,9 +1,11 @@ -import { Game, Playtypes, integer, UserGameStats, ClassDelta } from "kamaitachi-common"; -import { gameClassValues } from "kamaitachi-common/js/game-classes"; +import { Game, Playtypes, integer, UserGameStats, ClassDelta, IDStrings } from "kamaitachi-common"; import deepmerge from "deepmerge"; import { KtLogger } from "../../../logger/logger"; import { CalculateGitadoraColour, CalculateJubeatColour } from "./builtin-class-handlers"; import { ReturnClassIfGreater } from "../../../../utils/class"; +import { GameClasses } from "kamaitachi-common/js/game-classes"; + +type ScoreClasses = Partial>; export interface ClassHandler { ( @@ -12,7 +14,7 @@ export interface ClassHandler { userID: integer, customRatings: Record, logger: KtLogger - ): Promise> | Record | undefined; + ): Promise | ScoreClasses | undefined; } type ClassHandlerMap = { @@ -79,8 +81,8 @@ export async function UpdateUGSClasses( customRatings: Record, ClassHandler: ClassHandler | null, logger: KtLogger -): Promise> { - let classes: Record = {}; +): Promise { + let classes: ScoreClasses = {}; // @ts-expect-error This one sucks - I need to look into a better way of representing these types if (STATIC_CLASS_HANDLERS[game] && STATIC_CLASS_HANDLERS[game][playtype]) { @@ -112,55 +114,42 @@ export async function UpdateUGSClasses( * so that other services can listen for it. In the future we might allow webhooks, too. */ export function CalculateClassDeltas( - game: Game, playtype: Playtypes[Game], - classes: Record, + classes: ScoreClasses, userGameStats: UserGameStats | null, logger: KtLogger ): ClassDelta[] { - // @ts-expect-error It's complaining about Game+PT permutations instead of Game->PT permutations. - const gcv = gameClassValues[game]?.[playtype]; - - if (Object.keys(classes).length !== 0 && !gcv) { - logger.severe( - `Classes were attempted to be processed for ${game} ${playtype}, but no class values exist for this.`, - { - classes, - } - ); - - return []; - } - const deltas = []; - for (const setName in classes) { + for (const s in classes) { + const classSet = s as keyof GameClasses; + const classVal = classes[classSet]; + + if (classVal === undefined) { + logger.debug(`Skipped deltaing-class ${classSet}.`); + continue; + } + try { - const isGreater = ReturnClassIfGreater( - game, - playtype, - setName, - classes[setName], - userGameStats - ); + const isGreater = ReturnClassIfGreater(classSet, classVal, userGameStats); if (isGreater === false) { continue; } else if (isGreater === null) { // @todo #99 REDISIPC-New Class Achieved deltas.push({ - set: setName, + set: classSet, playtype, old: null, - new: classes[setName], + new: classVal, }); } else { // @todo #99 REDISIPC-Class Improved! deltas.push({ - set: setName, + set: classSet, playtype, - old: userGameStats!.classes[setName], - new: classes[setName], + old: userGameStats!.classes[classSet]!, + new: classVal, }); } } catch (err) { diff --git a/server/src/lib/score-import/framework/user-game-stats/update-ugs.test.ts b/server/src/lib/score-import/framework/user-game-stats/update-ugs.test.ts index f93af4b82..429688e30 100644 --- a/server/src/lib/score-import/framework/user-game-stats/update-ugs.test.ts +++ b/server/src/lib/score-import/framework/user-game-stats/update-ugs.test.ts @@ -110,7 +110,7 @@ t.test("#UpdateUsersGamePlaytypeStats", (t) => { "iidx", "SP", 1, - () => ({ dan: "kaiden" }), // lmao + () => ({ dan: 18 }), // lmao logger ); @@ -121,7 +121,7 @@ t.test("#UpdateUsersGamePlaytypeStats", (t) => { set: "dan", playtype: "SP", old: null, - new: "kaiden", + new: 18, }, ], "Should return the class delta" @@ -141,7 +141,7 @@ t.test("#UpdateUsersGamePlaytypeStats", (t) => { BPI: 0, }, classes: { - dan: "kaiden", + dan: 18, }, } as any, "Should update the game-stats object" @@ -161,7 +161,7 @@ t.test("#UpdateUsersGamePlaytypeStats", (t) => { BPI: 0, }, classes: { - dan: "chuuden", + dan: 17, }, }); @@ -169,7 +169,7 @@ t.test("#UpdateUsersGamePlaytypeStats", (t) => { "iidx", "SP", 1, - () => ({ dan: "kaiden" }), // lmao + () => ({ dan: 18 }), // lmao logger ); @@ -179,8 +179,8 @@ t.test("#UpdateUsersGamePlaytypeStats", (t) => { { set: "dan", playtype: "SP", - old: "chuuden", - new: "kaiden", + old: 17, + new: 18, }, ], "Should return the updated class delta" @@ -200,7 +200,7 @@ t.test("#UpdateUsersGamePlaytypeStats", (t) => { BPI: 0, }, classes: { - dan: "kaiden", + dan: 18, }, } as any, "Should update the game-stats object" diff --git a/server/src/lib/score-import/framework/user-game-stats/update-ugs.ts b/server/src/lib/score-import/framework/user-game-stats/update-ugs.ts index 6c1ae851d..7c1645321 100644 --- a/server/src/lib/score-import/framework/user-game-stats/update-ugs.ts +++ b/server/src/lib/score-import/framework/user-game-stats/update-ugs.ts @@ -41,7 +41,7 @@ export async function UpdateUsersGamePlaytypeStats( logger.debug(`Calculating Class Deltas...`); - const deltas = CalculateClassDeltas(game, playtype, classes, userGameStats, logger); + const deltas = CalculateClassDeltas(playtype, classes, userGameStats, logger); logger.debug(`Had ${deltas.length} deltas.`); diff --git a/server/src/utils/class.ts b/server/src/utils/class.ts index 8b2b10467..bae725de0 100644 --- a/server/src/utils/class.ts +++ b/server/src/utils/class.ts @@ -1,61 +1,25 @@ -import { Game, integer, Playtypes, UserGameStats } from "kamaitachi-common"; -import { ClassData, gameClassValues } from "kamaitachi-common/js/game-classes"; +import { Game, integer, IDStrings, Playtypes, UserGameStats } from "kamaitachi-common"; import db from "../external/mongo/db"; import CreateLogCtx from "../lib/logger/logger"; +import { GameClassSets } from "kamaitachi-common/js/game-classes"; const logger = CreateLogCtx(__filename); -export function GetClassSetsForGamePT(game: Game, playtype: Playtypes[Game]) { - // @ts-expect-error its confused about game+pt permutations - return gameClassValues[game]?.[playtype] as Record | undefined; -} - /** * Returns the provided class if it is greater than the one in userGameStats * @returns The provided class if it is greater, NULL if there is nothing * to compare to, and FALSE if it is worse or equal. */ export function ReturnClassIfGreater( - game: Game, - playtype: Playtypes[Game], - setName: string, - newClass: string, + classSet: GameClassSets[IDStrings], + classVal: integer, userGameStats?: UserGameStats | null ) { - const classSets = GetClassSetsForGamePT(game, playtype); - - if (!classSets) { - logger.error(`${game} ${playtype} Does not have any classes.`); - throw new Error(`${game} ${playtype} Does not have any classes.`); - } - - const gcv: ClassData = classSets[setName]; - - if (gcv === undefined) { - logger.error(`Invalid classKey ${setName}. Cannot process class.`); - throw new Error(`Invalid classKey ${setName}. Cannot process class.`); - } - - const newClassInfo = gcv[newClass]; - - if (!userGameStats) { + if (!userGameStats || userGameStats.classes[classSet] === undefined) { return null; } - const val = newClassInfo.index; - const pastClass = userGameStats.classes[setName]; - - if (!pastClass) { - return null; - } - - const pastVal = gcv[pastClass].index; - - if (val > pastVal) { - return newClass; - } - - return false; + return classVal > userGameStats.classes[classSet]!; } /** @@ -70,11 +34,11 @@ export async function UpdateClassIfGreater( userID: integer, game: Game, playtype: Playtypes[Game], - classKey: string, - newClass: string + classSet: GameClassSets[IDStrings], + classVal: integer ) { const userGameStats = await db["game-stats"].findOne({ userID, game, playtype }); - const isGreater = ReturnClassIfGreater(game, playtype, classKey, newClass, userGameStats); + const isGreater = ReturnClassIfGreater(classSet, classVal, userGameStats); if (isGreater === false) { return false; @@ -83,7 +47,7 @@ export async function UpdateClassIfGreater( if (userGameStats) { await db["game-stats"].update( { userID, game, playtype }, - { $set: { [`classes.${classKey}`]: newClass } } + { $set: { [`classes.${classSet}`]: classVal } } ); } else { // insert new game stats for this user - this is an awkward place @@ -96,7 +60,7 @@ export async function UpdateClassIfGreater( lampRating: 0, rating: 0, classes: { - classKey: newClass, + [classSet]: classVal, }, }); logger.info(`Created new player gamestats for ${userID} ${game} (${playtype})`);