fix(lr2hook): reject BP if user failed

LR2Hook sends invalid BP if the user ends up exiting the song early.
We need to handle this, and not accept it.
This commit is contained in:
zkldi
2022-10-27 19:46:33 +01:00
parent 7f5084b963
commit 7eaa8bc06b
4 changed files with 94 additions and 4 deletions
+2 -1
View File
@@ -1,5 +1,6 @@
import UGPTAddPreferredRanking from "./migrations/add-preferredRanking-to-ugpt";
import UGPTRivalsMigration from "./migrations/add-rivals-to-ugpt";
import NullLR2HookFailedBPs from "./migrations/null-lr2hook-failed-bps";
import RecalcBrokenIIDXNotecounts from "./migrations/recalc-broken-iidx-notecounts";
import RemoveIIDXBeginners from "./migrations/remove-iidx-beginners";
import RemoveMultifolderStats from "./migrations/remove-multifolder-stats";
@@ -44,7 +45,7 @@ if (Environment.nodeEnv !== "test") {
// bokutachi specific migrations
if (TachiConfig.TYPE !== "ktchi") {
// none, currently
REGISTERED_MIGRATIONS.push(NullLR2HookFailedBPs);
}
}
@@ -0,0 +1,31 @@
import db from "external/mongo/db";
import { UpdateAllPBs } from "utils/calculations/recalc-scores";
import type { Migration } from "utils/types";
const migration: Migration = {
id: "null-lr2hook-failed-bps",
up: async () => {
await db.scores.update(
{
importType: "ir/lr2hook",
"scoreMeta.gauge": "HARD",
lamp: { $in: ["FAILED", "NO PLAY"] },
},
{
$set: {
"scoreData.hitMeta.bp": null,
},
},
{
multi: true,
}
);
await UpdateAllPBs(undefined, { game: "bms" });
},
down: () => {
throw new Error(`Unable to revert transaction, some scores may have been nulled.`);
},
};
export default migration;
@@ -1,6 +1,7 @@
import { ConverterLR2Hook } from "./converter";
import CreateLogCtx from "lib/logger/logger";
import t from "tap";
import { dmf } from "test-utils/misc";
import ResetDBState from "test-utils/resets";
import { TestingLR2HookScore } from "test-utils/test-data";
@@ -30,6 +31,52 @@ t.test("#ConverterLR2Hook", (t) => {
dryScore: {
scoreData: {
score: TestingLR2HookScore.scoreData.exScore,
hitMeta: {
bp: 75,
},
},
game: "bms",
importType: "ir/lr2hook",
scoreMeta: {
client: "LR2",
},
},
});
t.end();
});
t.test("Should null BP if the score was a fail with hard-gauge.", async (t) => {
const res = await ConverterLR2Hook(
dmf(TestingLR2HookScore, {
playerData: {
gauge: "HARD",
},
scoreData: {
lamp: "FAIL",
},
} as any),
{ timeReceived: 10 },
"ir/lr2hook",
logger
);
t.hasStrict(res, {
song: {
id: 27339,
},
chart: {
chartID: "88eb6cc5683e2740cbd07f588a5f3db1db8d467b",
data: {
hashMD5: TestingLR2HookScore.md5,
},
},
dryScore: {
scoreData: {
score: TestingLR2HookScore.scoreData.exScore,
hitMeta: {
bp: null,
},
},
game: "bms",
importType: "ir/lr2hook",
@@ -36,6 +36,17 @@ export const ConverterLR2Hook: ConverterFunction<LR2HookScore, LR2HookContext> =
const { percent, grade } = GenericGetGradeAndPercent("bms", data.scoreData.exScore, chart);
const gauge = ConvertGauge(data.playerData.gauge);
const lamp = ConvertLamp(data.scoreData.lamp);
let bp: number | null = data.scoreData.bad + data.scoreData.poor;
// lr2hook doesn't send "max" BP so to speak. If you fail really early
// or quit out, you can have an early fail with like, 5 BP.
if ((lamp === "FAILED" || lamp === "NO PLAY") && gauge === "HARD") {
bp = null;
}
const dryScore: DryScore<"bms:7K" | "bms:14K"> = {
game: "bms",
service: "LR2Hook",
@@ -46,7 +57,7 @@ export const ConverterLR2Hook: ConverterFunction<LR2HookScore, LR2HookContext> =
score: data.scoreData.exScore,
percent,
grade,
lamp: ConvertLamp(data.scoreData.lamp),
lamp,
judgements: {
pgreat: data.scoreData.pgreat,
great: data.scoreData.great,
@@ -55,14 +66,14 @@ export const ConverterLR2Hook: ConverterFunction<LR2HookScore, LR2HookContext> =
poor: data.scoreData.poor,
},
hitMeta: {
bp: data.scoreData.bad + data.scoreData.poor,
bp,
maxCombo: data.scoreData.maxCombo,
gauge: data.scoreData.hpGraph[999] ?? 0,
gaugeHistory: data.scoreData.hpGraph,
},
},
scoreMeta: {
gauge: ConvertGauge(data.playerData.gauge),
gauge,
random: chart.playtype === "7K" ? ConvertRandom(data.playerData.random) : null,
client: "LR2",
},