From bae16fbdc2d793af18ca6c0442001b41e86d7571 Mon Sep 17 00:00:00 2001 From: nairobi <61069237+nyairobi@users.noreply.github.com> Date: Thu, 24 Apr 2025 07:31:41 +0000 Subject: [PATCH] fix: tiebreak ongeki scores based on p-score (#1282) * fix: tiebreak ongeki scores based on p-score * fix: add another test --- .../game-implementations/games/ongeki.test.ts | 121 +++++++++++++++++- .../framework/pb/create-pb-doc.ts | 39 ++++-- 2 files changed, 147 insertions(+), 13 deletions(-) diff --git a/server/src/game-implementations/games/ongeki.test.ts b/server/src/game-implementations/games/ongeki.test.ts index 362b14c5c..72fe2a0d6 100644 --- a/server/src/game-implementations/games/ongeki.test.ts +++ b/server/src/game-implementations/games/ongeki.test.ts @@ -1,13 +1,13 @@ import { ONGEKI_IMPL } from "./ongeki"; import db from "external/mongo/db"; import CreateLogCtx from "lib/logger/logger"; -import { CreatePBDoc } from "lib/score-import/framework/pb/create-pb-doc"; +import { CreatePBDoc, UpdateChartRanking } from "lib/score-import/framework/pb/create-pb-doc"; import { ONGEKI_BELL_LAMPS, ONGEKI_GRADES, ONGEKI_NOTE_LAMPS } from "tachi-common"; import t from "tap"; import { dmf, mkMockPB, mkMockScore } from "test-utils/misc"; import ResetDBState from "test-utils/resets"; import { TestingOngekiChart, TestingOngekiScorePB } from "test-utils/test-data"; -import type { ProvidedMetrics, ScoreData } from "tachi-common"; +import type { PBScoreDocument, ProvidedMetrics, ScoreData } from "tachi-common"; const baseMetrics: ProvidedMetrics["ongeki:Single"] = { noteLamp: "CLEAR", @@ -214,5 +214,122 @@ t.test("ONGEKI Implementation", (t) => { t.end(); }); + t.test("Ranking", (t) => { + t.beforeEach(ResetDBState); + + t.test("Should tiebreak according to platinum score", async (t) => { + await db["personal-bests"].insert({ + ...TestingOngekiScorePB, + scoreData: { + ...TestingOngekiScorePB.scoreData, + optional: { + ...TestingOngekiScorePB.scoreData.optional, + platScore: 1000, + }, + }, + timeAchieved: 3, + userID: 1, + }); + + await db["personal-bests"].insert({ + ...TestingOngekiScorePB, + scoreData: { + ...TestingOngekiScorePB.scoreData, + optional: { + ...TestingOngekiScorePB.scoreData.optional, + platScore: 1001, + }, + }, + timeAchieved: 2, + userID: 2, + }); + + await db["personal-bests"].insert({ + ...TestingOngekiScorePB, + scoreData: { + ...TestingOngekiScorePB.scoreData, + optional: { + ...TestingOngekiScorePB.scoreData.optional, + platScore: 999, + }, + }, + timeAchieved: 1, + userID: 3, + }); + + await UpdateChartRanking("ongeki", "Single", TestingOngekiChart.chartID); + + const pbs = (await db["personal-bests"].find({ + chartID: TestingOngekiChart.chartID, + })) as Array>; + + t.strictSame(pbs.length, 3); + + for (const pb of pbs) { + t.strictSame(pb.rankingData.outOf, 3); + if (pb.scoreData.optional.platScore === 999) { + t.strictSame(pb.rankingData.rank, 3); + } else if (pb.scoreData.optional.platScore === 1000) { + t.strictSame(pb.rankingData.rank, 2); + } else { + t.strictSame(pb.rankingData.rank, 1); + } + } + + t.end(); + }); + + t.test("Should not tiebreak if tech scores differ", async (t) => { + await db["personal-bests"].insert({ + ...TestingOngekiScorePB, + scoreData: { + ...TestingOngekiScorePB.scoreData, + score: 1010000, + optional: { + ...TestingOngekiScorePB.scoreData.optional, + platScore: 0, + }, + }, + userID: 1, + }); + + await db["personal-bests"].insert({ + ...TestingOngekiScorePB, + scoreData: { + ...TestingOngekiScorePB.scoreData, + score: 1009999, + optional: { + ...TestingOngekiScorePB.scoreData.optional, + platScore: 1001, + }, + }, + userID: 2, + }); + + await UpdateChartRanking("ongeki", "Single", TestingOngekiChart.chartID); + + const [pb1, pb2] = (await db["personal-bests"].find( + { + chartID: TestingOngekiChart.chartID, + }, + { + sort: { + [`rankingData.rank`]: 1, + }, + } + )) as Array>; + + t.strictSame(pb1?.rankingData.outOf, 2); + t.strictSame(pb1?.rankingData.rank, 1); + t.strictSame(pb2?.rankingData.rank, 2); + t.strictSame(pb1?.scoreData.optional.platScore, 0); + t.strictSame(pb2?.scoreData.optional.platScore, 1001); + + t.end(); + }); + + t.end(); + }); + t.end(); }); diff --git a/server/src/lib/score-import/framework/pb/create-pb-doc.ts b/server/src/lib/score-import/framework/pb/create-pb-doc.ts index d843fbca1..d3310446a 100644 --- a/server/src/lib/score-import/framework/pb/create-pb-doc.ts +++ b/server/src/lib/score-import/framework/pb/create-pb-doc.ts @@ -129,17 +129,7 @@ export async function CreatePBDoc( * Updates rankings on a given chart. */ export async function UpdateChartRanking(game: Game, playtype: Playtype, chartID: string) { - const gptConfig = GetGamePTConfig(game, playtype); - - const scores = await db["personal-bests"].find( - { chartID }, - { - sort: { - [`scoreData.${gptConfig.defaultMetric}`]: -1, - timeAchieved: 1, - }, - } - ); + const scores = await GetSortedPBs(game, playtype, chartID); const allRivals = await GetEveryonesRivalIDs(game, playtype); @@ -186,3 +176,30 @@ export async function UpdateChartRanking(game: Game, playtype: Playtype, chartID await db["personal-bests"].bulkWrite(bwrite, { ordered: false }); } + +async function GetSortedPBs(game: Game, playtype: Playtype, chartID: string) { + const gptConfig = GetGamePTConfig(game, playtype); + + if (game === "ongeki") { + return db["personal-bests"].find( + { chartID }, + { + sort: { + [`scoreData.score`]: -1, + [`scoreData.optional.platScore`]: -1, + timeAchieved: 1, + }, + } + ); + } + + return db["personal-bests"].find( + { chartID }, + { + sort: { + [`scoreData.${gptConfig.defaultMetric}`]: -1, + timeAchieved: 1, + }, + } + ); +}