From 80dc55099e906b27083c61dcdb348b9bfaa83676 Mon Sep 17 00:00:00 2001 From: zkldi Date: Mon, 31 May 2021 13:55:29 +0100 Subject: [PATCH] Fixes #52 --- server/pnpm-lock.yaml | 6 +- .../builtin-class-handlers.test.ts | 112 ++++++++++++++---- .../user-game-stats/builtin-class-handlers.ts | 89 ++++++++++---- .../framework/user-game-stats/classes.ts | 13 +- 4 files changed, 170 insertions(+), 50 deletions(-) diff --git a/server/pnpm-lock.yaml b/server/pnpm-lock.yaml index aa68ace92..856d5355e 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/6f1ca95f0432ae61eef586bb3535ac5a159ad764 + kamaitachi-common: github.com/zkldi/Kamaitachi-common/309bc3610aca940ceeb5244ff7d337770cf27201 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/6f1ca95f0432ae61eef586bb3535ac5a159ad764: - resolution: {tarball: https://codeload.github.com/zkldi/Kamaitachi-common/tar.gz/6f1ca95f0432ae61eef586bb3535ac5a159ad764} + github.com/zkldi/Kamaitachi-common/309bc3610aca940ceeb5244ff7d337770cf27201: + resolution: {tarball: https://codeload.github.com/zkldi/Kamaitachi-common/tar.gz/309bc3610aca940ceeb5244ff7d337770cf27201} name: kamaitachi-common version: 0.1.0 dependencies: diff --git a/server/src/lib/score-import/framework/user-game-stats/builtin-class-handlers.test.ts b/server/src/lib/score-import/framework/user-game-stats/builtin-class-handlers.test.ts index 22c178e93..e852d5013 100644 --- a/server/src/lib/score-import/framework/user-game-stats/builtin-class-handlers.test.ts +++ b/server/src/lib/score-import/framework/user-game-stats/builtin-class-handlers.test.ts @@ -1,11 +1,20 @@ import t from "tap"; -import { CalculateGitadoraColour, GitadoraSkillToColour } from "./builtin-class-handlers"; +import { GitadoraColours, SDVXVFClasses } from "../../../constants/classes"; +import CreateLogCtx from "../../../logger/logger"; +import { + CalculateGitadoraColour, + GitadoraSkillToColour, + CalculateSDVXClass, + SDVXVF5ToClass, +} from "./builtin-class-handlers"; + +const logger = CreateLogCtx(__filename); t.test("#CalculateGitadoraColour", (t) => { t.strictSame( - CalculateGitadoraColour("gitadora", "Gita", 1, { skill: 1500 }), + CalculateGitadoraColour("gitadora", "Gita", 1, { skill: 1500 }, logger), { - skillColour: "orangegradient", + colour: GitadoraColours.ORANGE_GRADIENT, }, "Should wrap the skill colour." ); @@ -14,24 +23,85 @@ t.test("#CalculateGitadoraColour", (t) => { }); t.test("#GitadoraSkillToColour", (t) => { - t.equal(GitadoraSkillToColour(0), "white"); - t.equal(GitadoraSkillToColour(999), "white"); - t.equal(GitadoraSkillToColour(1000), "orange"); - t.equal(GitadoraSkillToColour(1500), "orangegradient"); - t.equal(GitadoraSkillToColour(2000), "yellow"); - t.equal(GitadoraSkillToColour(2500), "yellowgradient"); - t.equal(GitadoraSkillToColour(3000), "green"); - t.equal(GitadoraSkillToColour(3500), "greengradient"); - t.equal(GitadoraSkillToColour(4000), "blue"); - t.equal(GitadoraSkillToColour(4500), "bluegradient"); - t.equal(GitadoraSkillToColour(5000), "purple"); - t.equal(GitadoraSkillToColour(5500), "purplegradient"); - t.equal(GitadoraSkillToColour(6000), "red"); - t.equal(GitadoraSkillToColour(6500), "redgradient"); - t.equal(GitadoraSkillToColour(7000), "bronze"); - t.equal(GitadoraSkillToColour(7500), "silver"); - t.equal(GitadoraSkillToColour(8000), "gold"); - t.equal(GitadoraSkillToColour(8500), "rainbow"); + t.equal(GitadoraSkillToColour(0), GitadoraColours.WHITE); + t.equal(GitadoraSkillToColour(999), GitadoraColours.WHITE); + t.equal(GitadoraSkillToColour(1000), GitadoraColours.ORANGE); + t.equal(GitadoraSkillToColour(1500), GitadoraColours.ORANGE_GRADIENT); + t.equal(GitadoraSkillToColour(2000), GitadoraColours.YELLOW); + t.equal(GitadoraSkillToColour(2500), GitadoraColours.YELLOW_GRADIENT); + t.equal(GitadoraSkillToColour(3000), GitadoraColours.GREEN); + t.equal(GitadoraSkillToColour(3500), GitadoraColours.GREEN_GRADIENT); + t.equal(GitadoraSkillToColour(4000), GitadoraColours.BLUE); + t.equal(GitadoraSkillToColour(4500), GitadoraColours.BLUE_GRADIENT); + t.equal(GitadoraSkillToColour(5000), GitadoraColours.PURPLE); + t.equal(GitadoraSkillToColour(5500), GitadoraColours.PURPLE_GRADIENT); + t.equal(GitadoraSkillToColour(6000), GitadoraColours.RED); + t.equal(GitadoraSkillToColour(6500), GitadoraColours.RED_GRADIENT); + t.equal(GitadoraSkillToColour(7000), GitadoraColours.BRONZE); + t.equal(GitadoraSkillToColour(7500), GitadoraColours.SILVER); + t.equal(GitadoraSkillToColour(8000), GitadoraColours.GOLD); + t.equal(GitadoraSkillToColour(8500), GitadoraColours.RAINBOW); + + t.end(); +}); + +t.test("#CalculateSDVXClass", (t) => { + t.strictSame(CalculateSDVXClass("sdvx", "Single", 1, { VF5: 10 }, logger), { + vfClass: SDVXVFClasses.COBALT_I, + }); + + t.end(); +}); + +t.test("#SDVXVF5ToClass", (t) => { + function f(vf: number) { + return SDVXVF5ToClass(vf, logger); + } + + t.equal(f(0), SDVXVFClasses.SIENNA_I); + t.equal(f(2.5), SDVXVFClasses.SIENNA_II); + t.equal(f(5), SDVXVFClasses.SIENNA_III); + t.equal(f(7.5), SDVXVFClasses.SIENNA_IV); + t.equal(f(10), SDVXVFClasses.COBALT_I); + t.equal(f(10.5), SDVXVFClasses.COBALT_II); + t.equal(f(11), SDVXVFClasses.COBALT_III); + t.equal(f(11.5), SDVXVFClasses.COBALT_IV); + t.equal(f(12), SDVXVFClasses.DANDELION_I); + t.equal(f(12.5), SDVXVFClasses.DANDELION_II); + t.equal(f(13), SDVXVFClasses.DANDELION_III); + t.equal(f(13.5), SDVXVFClasses.DANDELION_IV); + + t.equal(f(14), SDVXVFClasses.CYAN_I); + t.equal(f(14.25), SDVXVFClasses.CYAN_II); + t.equal(f(14.5), SDVXVFClasses.CYAN_III); + t.equal(f(14.75), SDVXVFClasses.CYAN_IV); + t.equal(f(15), SDVXVFClasses.SCARLET_I); + t.equal(f(15.25), SDVXVFClasses.SCARLET_II); + t.equal(f(15.5), SDVXVFClasses.SCARLET_III); + t.equal(f(15.75), SDVXVFClasses.SCARLET_IV); + t.equal(f(16), SDVXVFClasses.CORAL_I); + t.equal(f(16.25), SDVXVFClasses.CORAL_II); + t.equal(f(16.5), SDVXVFClasses.CORAL_III); + t.equal(f(16.75), SDVXVFClasses.CORAL_IV); + t.equal(f(17), SDVXVFClasses.ARGENTO_I); + t.equal(f(17.25), SDVXVFClasses.ARGENTO_II); + t.equal(f(17.5), SDVXVFClasses.ARGENTO_III); + t.equal(f(17.75), SDVXVFClasses.ARGENTO_IV); + t.equal(f(18), SDVXVFClasses.ELDORA_I); + t.equal(f(18.25), SDVXVFClasses.ELDORA_II); + t.equal(f(18.5), SDVXVFClasses.ELDORA_III); + t.equal(f(18.75), SDVXVFClasses.ELDORA_IV); + t.equal(f(19), SDVXVFClasses.CRIMSON_I); + t.equal(f(19.25), SDVXVFClasses.CRIMSON_II); + t.equal(f(19.5), SDVXVFClasses.CRIMSON_III); + t.equal(f(19.75), SDVXVFClasses.CRIMSON_IV); + + t.equal(f(20), SDVXVFClasses.IMPERIAL_I); + t.equal(f(21), SDVXVFClasses.IMPERIAL_II); + t.equal(f(22), SDVXVFClasses.IMPERIAL_III); + t.equal(f(23), SDVXVFClasses.IMPERIAL_IV); + t.equal(f(24), SDVXVFClasses.IMPERIAL_IV); + t.equal(f(1000), SDVXVFClasses.IMPERIAL_IV); t.end(); }); diff --git a/server/src/lib/score-import/framework/user-game-stats/builtin-class-handlers.ts b/server/src/lib/score-import/framework/user-game-stats/builtin-class-handlers.ts index 54d8796d7..363db75b8 100644 --- a/server/src/lib/score-import/framework/user-game-stats/builtin-class-handlers.ts +++ b/server/src/lib/score-import/framework/user-game-stats/builtin-class-handlers.ts @@ -1,54 +1,97 @@ -import { Game, Playtypes, integer } from "kamaitachi-common"; +import { Game, Playtypes, integer, GameSpecificCalcLookup } from "kamaitachi-common"; +import { GameClasses } from "kamaitachi-common/js/game-classes"; +import { GitadoraColours, SDVXVFClasses } from "../../../constants/classes"; +import { KtLogger } from "../../../logger/logger"; + +export function CalculateSDVXClass( + game: Game, + playtype: Playtypes[Game], + userID: integer, + customRatings: Partial>, + logger: KtLogger +): Partial> { + if (!customRatings.VF5) { + return {}; + } + + return { vfClass: SDVXVF5ToClass(customRatings.VF5, logger) }; +} + +/** + * Converts a user's profile VF5 to a class. There are almost 40 classes, and writing + * if statements for all of them is a painful endeavour. This function returns an index + * derived from the gaps between classes, to avoid writing out all those statements. + * @see https://bemaniwiki.com/index.php?SOUND%20VOLTEX%20VIVID%20WAVE/VOLFORCE + */ +export function SDVXVF5ToClass(vf: number, logger: KtLogger) { + // This is impossible, but a failsafe regardless + if (vf >= 24) { + logger.warn(`User has excessive VF5 of ${vf}. Defaulting to Imperial IV.`); + return SDVXVFClasses.IMPERIAL_IV; + } else if (vf >= 20) { + // imperial i -> iv has gaps of 1 + return SDVXVFClasses.IMPERIAL_I + Math.floor(vf - 20); + } else if (vf >= 14) { + // cyan i -> crimson iv has gaps of 0.25 + return SDVXVFClasses.CYAN_I + Math.floor(4 * (vf - 14)); + } else if (vf >= 10) { + // cobalt i -> dandelion iv have gaps of 0.5 + return SDVXVFClasses.COBALT_I + Math.floor(2 * (vf - 10)); + } + + return Math.floor(vf / 2.5); +} export function CalculateGitadoraColour( game: Game, playtype: Playtypes[Game], userID: integer, - customRatings: Record -): Record { - const skillColour = GitadoraSkillToColour(customRatings.skill); + customRatings: Record, + logger: KtLogger +): Partial> { + const colour = GitadoraSkillToColour(customRatings.skill); return { - skillColour, + colour, }; } export function GitadoraSkillToColour(sk: number) { if (sk >= 8500) { - return "rainbow"; + return GitadoraColours.RAINBOW; } else if (sk >= 8000) { - return "gold"; + return GitadoraColours.GOLD; } else if (sk >= 7500) { - return "silver"; + return GitadoraColours.SILVER; } else if (sk >= 7000) { - return "bronze"; + return GitadoraColours.BRONZE; } else if (sk >= 6500) { - return "redgradient"; + return GitadoraColours.RED_GRADIENT; } else if (sk >= 6000) { - return "red"; + return GitadoraColours.RED; } else if (sk >= 5500) { - return "purplegradient"; + return GitadoraColours.PURPLE_GRADIENT; } else if (sk >= 5000) { - return "purple"; + return GitadoraColours.PURPLE; } else if (sk >= 4500) { - return "bluegradient"; + return GitadoraColours.BLUE_GRADIENT; } else if (sk >= 4000) { - return "blue"; + return GitadoraColours.BLUE; } else if (sk >= 3500) { - return "greengradient"; + return GitadoraColours.GREEN_GRADIENT; } else if (sk >= 3000) { - return "green"; + return GitadoraColours.GREEN; } else if (sk >= 2500) { - return "yellowgradient"; + return GitadoraColours.YELLOW_GRADIENT; } else if (sk >= 2000) { - return "yellow"; + return GitadoraColours.YELLOW; } else if (sk >= 1500) { - return "orangegradient"; + return GitadoraColours.ORANGE_GRADIENT; } else if (sk >= 1000) { - return "orange"; + return GitadoraColours.ORANGE; } - return "white"; + return GitadoraColours.WHITE; } export function CalculateJubeatColour( @@ -56,7 +99,7 @@ export function CalculateJubeatColour( playtype: Playtypes[Game], userID: integer, customRatings: Record -): Promise> { +): GameClasses<"jubeat:Single"> { throw new Error("Not implemented."); } 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 f1aa06564..28c21c14e 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,7 +1,11 @@ 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 { + CalculateGitadoraColour, + CalculateJubeatColour, + CalculateSDVXClass, +} from "./builtin-class-handlers"; import { ReturnClassIfGreater } from "../../../../utils/class"; import { GameClasses } from "kamaitachi-common/js/game-classes"; import { RedisPub } from "../../../../external/redis/redis-IPC"; @@ -50,7 +54,9 @@ const STATIC_CLASS_HANDLERS: ClassHandlerMap = { maimai: null, museca: null, popn: null, - sdvx: null, + sdvx: { + Single: CalculateSDVXClass, + }, usc: null, }; @@ -92,7 +98,8 @@ export async function UpdateUGSClasses( game, playtype, userID, - customRatings + customRatings, + logger ); }