From 05ff009eb6c8f8c2eba67c0948f4c23aedf8e6a3 Mon Sep 17 00:00:00 2001 From: zkldi <20380519+zkldi@users.noreply.github.com> Date: Tue, 13 Dec 2022 03:45:47 +0000 Subject: [PATCH] fix: jubility calc should fetch best charts but dedupe on hardmode this query might be expensive, who knows --- .../framework/user-game-stats/rating.ts | 90 ++++++++++++++++++- 1 file changed, 87 insertions(+), 3 deletions(-) diff --git a/server/src/lib/score-import/framework/user-game-stats/rating.ts b/server/src/lib/score-import/framework/user-game-stats/rating.ts index 8ba54f971..bfd689e80 100644 --- a/server/src/lib/score-import/framework/user-game-stats/rating.ts +++ b/server/src/lib/score-import/framework/user-game-stats/rating.ts @@ -275,7 +275,7 @@ export async function GetBestRatingOnSongs( userID: integer, game: Game, playtype: Playtype, - ratingProp: "jubility" | "skill", + ratingProp: "skill", limit: integer ): Promise> { const r: Array<{ doc: PBScoreDocument }> = await db["personal-bests"].aggregate([ @@ -314,6 +314,90 @@ export async function GetBestRatingOnSongs( return r.map((e) => e.doc); } +async function GetBestJubilityOnSongs( + songIDs: Array, + userID: integer, + game: Game, + playtype: Playtype, + limit: integer +): Promise> { + const r: Array<{ doc: PBScoreDocument }> = await db["personal-bests"].aggregate([ + { + $match: { + game, + playtype, + userID, + songID: { $in: songIDs }, + }, + }, + { + // we need to do stuff dependent on the chart difficulty, + // so we need the chart difficulty + $lookup: { + from: "charts-jubeat", + localField: "chartID", + foreignField: "chartID", + as: "chart", + }, + }, + { + // "chart" is an array unless we unwind it. + $unwind: { + path: "$chart", + }, + }, + { + // sort on jubility (so we get the best score) + $sort: { + [`calculatedData.jubility`]: -1, + }, + }, + { + $group: { + _id: { + songID: "$songID", + + // Jubility is unique upon songID + difficulty. However, you + // cannot have a PB on both a HARD BSC and a BSC counted for + // jubility. This query is awkward. Sorry! + difficulty: { + $switch: { + branches: [ + { + case: { $in: ["$difficulty", ["HARD BSC", "BSC"]] }, + then: "BSC", + }, + { + case: { $in: ["$difficulty", ["HARD ADV", "ADV"]] }, + then: "ADV", + }, + { + case: { $in: ["$difficulty", ["HARD EXT", "EXT"]] }, + then: "EXT", + }, + ], + }, + }, + }, + doc: { $first: "$$ROOT" }, + }, + }, + + // for some godforsaken reason you have to sort twice. after a grouping + // the sort order becomes nondeterministic + { + $sort: { + [`doc.calculatedData.jubility`]: -1, + }, + }, + { + $limit: limit, + }, + ]); + + return r.map((e) => e.doc); +} + const CURRENT_JUBEAT_HOT_VERSION: GPTSupportedVersions["jubeat:Single"] = "festo"; async function CalculateJubility( @@ -337,8 +421,8 @@ async function CalculateJubility( const coldSongIDs = coldSongs.map((e) => e.id); const [bestHotScores, bestScores] = await Promise.all([ - GetBestRatingOnSongs(hotSongIDs, userID, "jubeat", "Single", "jubility", 30), - GetBestRatingOnSongs(coldSongIDs, userID, "jubeat", "Single", "jubility", 30), + GetBestJubilityOnSongs(hotSongIDs, userID, "jubeat", "Single", 30), + GetBestJubilityOnSongs(coldSongIDs, userID, "jubeat", "Single", 30), ]); let jubility = 0;