mirror of
https://github.com/zkldi/Tachi.git
synced 2026-10-12 17:28:31 +03:00
Class refactor - This is really hard
This commit is contained in:
@@ -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,
|
||||
};
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user