Class refactor - This is really hard

This commit is contained in:
zkldi
2021-05-14 07:03:38 +01:00
parent 20e6153fa7
commit de04eee33c
9 changed files with 148 additions and 55 deletions
+103
View File
@@ -0,0 +1,103 @@
import { Game, integer, Playtypes, UserGameStats } from "kamaitachi-common";
import { ClassData, gameClassValues } from "kamaitachi-common/js/game-classes";
import db from "../db/db";
import CreateLogCtx from "../logger";
const logger = CreateLogCtx("class.ts");
/**
* 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,
userGameStats?: UserGameStats | null
) {
// @ts-expect-error It's complaining about Game+PT permutations instead of Game->PT permutations.
let gcv: ClassData = gameClassValues[game][playtype][setName];
if (gcv === undefined) {
logger.error(`Invalid classKey ${setName}. Cannot process class.`);
throw new Error(`Invalid classKey ${setName}. Cannot process class.`);
}
let newClassInfo = gcv[newClass];
if (!userGameStats) {
return null;
}
let val = newClassInfo.index;
let pastClass = userGameStats.classes[setName];
if (!pastClass) {
return null;
}
let pastVal = gcv[pastClass].index;
if (val > pastVal) {
return newClass;
}
return false;
}
/**
* Updates a user's class value if it is greater than the one in their
* UserGameStats.
* @returns False if nothing was updated.
* Null if it was updated because there was nothing in UserGameStats to
* compare to.
* True if it was updated because it was better than UserGameStats.
*/
export async function UpdateClassIfGreater(
userID: integer,
game: Game,
playtype: Playtypes[Game],
classKey: string,
newClass: string,
userGameStats?: UserGameStats
) {
let isGreater = ReturnClassIfGreater(game, playtype, classKey, newClass, userGameStats);
if (isGreater === false) {
return false;
}
if (userGameStats) {
await db["game-stats"].update(
{ userID, game, playtype },
{ $set: { [`classes.${classKey}`]: newClass } }
);
} else {
// insert new game stats for this user - this is an awkward place
// to call this - maybe we should call it elsewhere.
await db["game-stats"].insert({
userID,
game,
playtype,
customRatings: {},
lampRating: 0,
rating: 0,
classes: {
classKey: newClass,
},
});
logger.info(`Created new player gamestats for ${userID} ${game} (${playtype})`);
}
if (isGreater === null) {
// @todo REDIS-IPC new class achieved
return null;
} else {
// @todo REDIS-IPC class improved
return true;
}
}
@@ -3,6 +3,7 @@ import { gameClassValues, ClassData } from "kamaitachi-common/js/game-classes";
import deepmerge from "deepmerge";
import { KtLogger } from "../../../types";
import { CalculateGitadoraColour, CalculateJubeatColour } from "./builtin-class-handlers";
import { ReturnClassIfGreater } from "../../../common/class";
export interface ClassHandler {
(
@@ -111,13 +112,12 @@ export async function UpdateUGSClasses(
export function CalculateClassDeltas(
game: Game,
playtype: Playtypes[Game],
userID: integer,
classes: Record<string, string>,
userGameStats: UserGameStats | null,
logger: KtLogger
): ClassDelta[] {
// @ts-expect-error It's complaining about Game+PT permutations instead of Game->PT permutations.
let gcv = gameClassValues[game][playtype] as ClassData;
let gcv = gameClassValues[game]?.[playtype];
if (Object.keys(classes).length !== 0 && !gcv) {
logger.severe(
@@ -132,52 +132,37 @@ export function CalculateClassDeltas(
let deltas = [];
for (const type in classes) {
const gameClass = classes[type];
let classInfo = gcv[gameClass];
if (!classInfo) {
logger.severe(
`Class ${type}:${gameClass} was assigned, but this does not exist for ${game} ${playtype}? Unassigning this and continuing.`
);
delete classes[type];
continue;
}
if (!userGameStats) {
// @todo REDISIPC-New Class Achieved
deltas.push({
for (const setName in classes) {
try {
let isGreater = ReturnClassIfGreater(
game,
playtype,
old: null,
new: gameClass,
});
} else {
let pastClass = userGameStats.classes[type];
let pastVal = gcv[pastClass];
setName,
classes[setName],
userGameStats
);
let thisIndex = classInfo.index;
let pastIndex;
if (!pastVal) {
logger.severe(
`UserID ${userID} has an invalid class of ${type} - This does not exist in GCV. Ignoring??`
);
pastIndex = -1;
} else {
pastIndex = pastVal.index;
}
if (thisIndex > pastIndex) {
// @todo REDISIPC-Class Improved!
if (isGreater === false) {
continue;
} else if (isGreater === null) {
// @todo REDISIPC-New Class Achieved
deltas.push({
game,
playtype,
old: userGameStats.classes[pastClass],
new: gameClass,
old: null,
new: classes[setName],
});
}
// @todo REDISIPC-Class Improved!
deltas.push({
game,
playtype,
old: userGameStats!.classes[setName],
new: classes[setName],
});
} catch (err) {
logger.error(err);
}
}
@@ -41,20 +41,10 @@ export async function UpdateUsersGamePlaytypeStats(
logger.debug(`Calculating Class Deltas...`);
let deltas = CalculateClassDeltas(game, playtype, userID, classes, userGameStats, logger);
let deltas = CalculateClassDeltas(game, playtype, classes, userGameStats, logger);
logger.debug(`Had ${deltas.length} deltas.`);
let newStats: UserGameStats = {
game,
playtype,
userID,
rating,
lampRating,
customRatings,
classes,
};
if (userGameStats) {
logger.debug(`Updated player gamestats for ${game} (${playtype})`);
await db["game-stats"].update(
@@ -73,6 +63,16 @@ export async function UpdateUsersGamePlaytypeStats(
}
);
} else {
let newStats: UserGameStats = {
game,
playtype,
userID,
rating,
lampRating,
customRatings,
classes,
};
logger.info(`Created new player gamestats for ${game} (${playtype})`);
await db["game-stats"].insert(newStats);
}
@@ -332,8 +332,8 @@ t.test("#ConverterFn", (t) => {
scoreData: {
lamp: "HARD CLEAR",
score: 500,
grade: "B",
// percent: 63, -- ish, FPA is hard.
grade: "E",
// percent: 31.5, -- ish, FPA is hard.
hitData: {},
hitMeta: {},
},
@@ -349,12 +349,12 @@ t.test("#ConverterFn", (t) => {
() =>
ConverterBatchManual(
// @ts-expect-error broken deepmerge
deepmerge(baseBatchManualScore, { score: 1000 }),
deepmerge(baseBatchManualScore, { score: 2000 }),
{ game: "iidx", service: "foo", version: null },
importType,
logger
),
{ message: /Invalid score of 1000, produced percent of 127/u } as any
{ message: /Invalid score of 2000, produced percent of 127/u } as any
);
t.end();
@@ -172,5 +172,6 @@ export function ParseBatchManualFromObject(
},
iterable: batchManual.body,
ConverterFunction: ConverterBatchManual,
classHandler: null,
};
}
@@ -270,6 +270,7 @@ function ParseEamusementCSV(
context,
ConverterFunction: ConverterFn,
game: "iidx",
classHandler: null,
};
}
@@ -39,5 +39,6 @@ export function ParseBarbatosSingle(
game: "sdvx",
iterable: ([body] as unknown) as BarbatosScore[],
ConverterFunction: ConverterIRBarbatos,
classHandler: null,
};
}
@@ -78,5 +78,6 @@ export function ParseFervidexStatic(
game: "iidx",
iterable: scores,
ConverterFunction: ConverterIRFervidexStatic,
classHandler: null, //@todo
};
}
@@ -95,5 +95,6 @@ export function ParseFervidexSingle(
game: "iidx",
iterable: ([body] as unknown) as FervidexScore[],
ConverterFunction: ConverterIRFervidex,
classHandler: null,
};
}