Fixes Poor Code and Data Structures in common/class and ugs-class #88

This commit is contained in:
zkldi
2021-05-27 13:50:03 +01:00
parent 0467b21d09
commit 5f0796c97d
6 changed files with 60 additions and 111 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/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:
@@ -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
);
@@ -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<GameClasses<IDStrings>>;
export interface ClassHandler {
(
@@ -12,7 +14,7 @@ export interface ClassHandler {
userID: integer,
customRatings: Record<string, number>,
logger: KtLogger
): Promise<Record<string, string>> | Record<string, string> | undefined;
): Promise<ScoreClasses> | ScoreClasses | undefined;
}
type ClassHandlerMap = {
@@ -79,8 +81,8 @@ export async function UpdateUGSClasses(
customRatings: Record<string, number>,
ClassHandler: ClassHandler | null,
logger: KtLogger
): Promise<Record<string, string>> {
let classes: Record<string, string> = {};
): Promise<ScoreClasses> {
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<string, string>,
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<IDStrings>;
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) {
@@ -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"
@@ -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.`);
+11 -47
View File
@@ -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<string, ClassData> | 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})`);