Merge pull request #152 from zkldi:zkldi/52-SDVX-Badge-thingy-support

zkldi/52-SDVX-Badge-thingy-support
This commit is contained in:
zkldi
2021-05-31 14:14:20 +01:00
committed by GitHub
7 changed files with 333 additions and 57 deletions
+3 -3
View File
@@ -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:
+161
View File
@@ -0,0 +1,161 @@
export enum IIDXClasses {
KYU_7,
KYU_6,
KYU_5,
KYU_4,
KYU_3,
KYU_2,
KYU_1,
DAN_1,
DAN_2,
DAN_3,
DAN_4,
DAN_5,
DAN_6,
DAN_7,
DAN_8,
DAN_9,
DAN_10,
CHUUDEN,
KAIDEN,
}
export enum GitadoraColours {
WHITE,
ORANGE,
ORANGE_GRADIENT,
YELLOW,
YELLOW_GRADIENT,
GREEN,
GREEN_GRADIENT,
BLUE,
BLUE_GRADIENT,
PURPLE,
PURPLE_GRADIENT,
RED,
RED_GRADIENT,
BRONZE,
SILVER,
GOLD,
RAINBOW,
}
export enum BMSGenocideDans {
NORMAL_1,
NORMAL_2,
NORMAL_3,
NORMAL_4,
NORMAL_5,
NORMAL_6,
NORMAL_7,
NORMAL_8,
NORMAL_9,
NORMAL_10,
INSANE_1,
INSANE_2,
INSANE_3,
INSANE_4,
INSANE_5,
INSANE_6,
INSANE_7,
INSANE_8,
INSANE_9,
INSANE_10,
INSANE_KAIDEN,
OVERJOY,
}
export enum BMSStSlDans {
SL_0,
SL_1,
SL_2,
SL_3,
SL_4,
SL_5,
SL_6,
SL_7,
SL_8,
SL_9,
SL_10,
SL_11,
SL_12,
ST_0,
ST_1,
ST_2,
ST_3,
ST_4,
ST_5,
ST_6,
ST_7,
ST_8,
ST_9,
ST_10,
ST_11,
ST_12,
}
export enum SDVXDans {
DAN_1,
DAN_2,
DAN_3,
DAN_4,
DAN_5,
DAN_6,
DAN_7,
DAN_8,
DAN_9,
DAN_10,
DAN_11,
INF,
}
// ewww
export enum SDVXVFClasses {
SIENNA_I,
SIENNA_II,
SIENNA_III,
SIENNA_IV,
COBALT_I,
COBALT_II,
COBALT_III,
COBALT_IV,
DANDELION_I,
DANDELION_II,
DANDELION_III,
DANDELION_IV,
CYAN_I,
CYAN_II,
CYAN_III,
CYAN_IV,
SCARLET_I,
SCARLET_II,
SCARLET_III,
SCARLET_IV,
CORAL_I,
CORAL_II,
CORAL_III,
CORAL_IV,
ARGENTO_I,
ARGENTO_II,
ARGENTO_III,
ARGENTO_IV,
ELDORA_I,
ELDORA_II,
ELDORA_III,
ELDORA_IV,
CRIMSON_I,
CRIMSON_II,
CRIMSON_III,
CRIMSON_IV,
IMPERIAL_I,
IMPERIAL_II,
IMPERIAL_III,
IMPERIAL_IV,
}
@@ -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();
});
@@ -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<Record<GameSpecificCalcLookup["sdvx:Single"], number>>,
logger: KtLogger
): Partial<GameClasses<"sdvx:Single">> {
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<string, number>
): Record<string, string> {
const skillColour = GitadoraSkillToColour(customRatings.skill);
customRatings: Record<string, number>,
logger: KtLogger
): Partial<GameClasses<"gitadora:Dora" | "gitadora:Gita">> {
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<string, number>
): Promise<Record<string, string>> {
): GameClasses<"jubeat:Single"> {
throw new Error("Not implemented.");
}
@@ -4,6 +4,7 @@ import CreateLogCtx from "../../../logger/logger";
import ResetDBState from "../../../../test-utils/reset-db-state";
import { CalculateClassDeltas, UpdateUGSClasses } from "./classes";
import { CloseAllConnections } from "../../../../test-utils/close-connections";
import { GitadoraColours } from "../../../constants/classes";
const logger = CreateLogCtx(__filename);
@@ -36,7 +37,7 @@ t.test("#UpdateUGSClasses", (t) => {
logger
);
t.strictSame(res, { skillColour: "rainbow" });
t.strictSame(res, { colour: GitadoraColours.RAINBOW });
t.end();
});
@@ -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
);
}
@@ -324,9 +324,3 @@ t.test("POST /api/v1/import/file", async (t) => {
});
t.teardown(CloseAllConnections);
import winr from "why-is-node-running";
setTimeout(() => {
winr();
}, 80_000);