From 99e04bbe99b9530f3d1d0c6e7ee1a2caa77b3a09 Mon Sep 17 00:00:00 2001 From: zkldi Date: Thu, 29 Apr 2021 17:47:33 +0100 Subject: [PATCH] RankingTests --- server/pnpm-lock.yaml | 6 +- .../framework/core/pb/create-pb-doc.test.ts | 83 +++++++++++++++++++ .../framework/core/pb/create-pb-doc.ts | 25 ++++-- server/src/test-utils/test-data.ts | 6 +- .../test-data/kamaitachi/iidx-scorepb.json | 40 +++++++++ 5 files changed, 148 insertions(+), 12 deletions(-) create mode 100644 server/src/score-import/framework/core/pb/create-pb-doc.test.ts create mode 100644 server/src/test-utils/test-data/kamaitachi/iidx-scorepb.json diff --git a/server/pnpm-lock.yaml b/server/pnpm-lock.yaml index 193c4d1de..e53563bf6 100644 --- a/server/pnpm-lock.yaml +++ b/server/pnpm-lock.yaml @@ -62,7 +62,7 @@ dependencies: express-async-errors: 3.1.1_express@4.17.1 express-session: 1.17.1 fast-json-stable-hash: 1.0.1 - kamaitachi-common: github.com/zkldi/Kamaitachi-common/6fa12357c7e4442e7452a1edff71fcc5c0840953 + kamaitachi-common: github.com/zkldi/Kamaitachi-common/5ef579cbd353a2211965f3a88915ced535766daf mongodb: 3.6.6 monk: 7.3.4 multer: 1.4.2 @@ -4638,8 +4638,8 @@ packages: '@types/yoga-layout': 1.9.2 dev: true - github.com/zkldi/Kamaitachi-common/6fa12357c7e4442e7452a1edff71fcc5c0840953: - resolution: {tarball: https://codeload.github.com/zkldi/Kamaitachi-common/tar.gz/6fa12357c7e4442e7452a1edff71fcc5c0840953} + github.com/zkldi/Kamaitachi-common/5ef579cbd353a2211965f3a88915ced535766daf: + resolution: {tarball: https://codeload.github.com/zkldi/Kamaitachi-common/tar.gz/5ef579cbd353a2211965f3a88915ced535766daf} name: kamaitachi-common version: 0.1.0 dependencies: diff --git a/server/src/score-import/framework/core/pb/create-pb-doc.test.ts b/server/src/score-import/framework/core/pb/create-pb-doc.test.ts new file mode 100644 index 000000000..fd1900c17 --- /dev/null +++ b/server/src/score-import/framework/core/pb/create-pb-doc.test.ts @@ -0,0 +1,83 @@ +import t from "tap"; +import db, { CloseMongoConnection } from "../../../../db/db"; +import ResetDBState from "../../../../test-utils/reset-db-state"; +import { Testing511SPA, TestingIIDXSPScorePB } from "../../../../test-utils/test-data"; +import { GetRankingInfo } from "./create-pb-doc"; +import deepmerge from "deepmerge"; + +t.test("#GetRankingInfo", (t) => { + t.beforeEach(ResetDBState); + + let chartID = Testing511SPA.chartID; + + t.test("Ranking info for one score", async (t) => { + await db["score-pbs"].insert([ + deepmerge(TestingIIDXSPScorePB, { scoreData: { percent: 50 }, userID: 1 }), + ]); + + let { outOf, ranking } = await GetRankingInfo(chartID, 1, 50); + + t.equal(outOf, 1, "Should correctly determine we're out of 1 score."); + t.equal(ranking, 1, "Should correctly determine we're #1."); + + t.end(); + }); + + t.test("Ranking info for multiple scores", async (t) => { + await db["score-pbs"].insert([ + deepmerge(TestingIIDXSPScorePB, { scoreData: { percent: 50 }, userID: 1 }), + deepmerge(TestingIIDXSPScorePB, { scoreData: { percent: 60 }, userID: 2 }), + deepmerge(TestingIIDXSPScorePB, { scoreData: { percent: 70 }, userID: 3 }), + deepmerge(TestingIIDXSPScorePB, { scoreData: { percent: 80 }, userID: 4 }), + deepmerge(TestingIIDXSPScorePB, { scoreData: { percent: 40 }, userID: 5 }), + ]); + + let { outOf, ranking } = await GetRankingInfo(chartID, 1, 50); + + t.equal(outOf, 5, "Should correctly determine we're out of 5 scores."); + t.equal(ranking, 4, "Should correctly determine we're #4/5."); + + t.end(); + }); + + t.test("#1 in Ranking Info for scores", async (t) => { + // insert some fake scores - our percent is 50. + + await db["score-pbs"].insert([ + deepmerge(TestingIIDXSPScorePB, { scoreData: { percent: 90 }, userID: 1 }), + deepmerge(TestingIIDXSPScorePB, { scoreData: { percent: 60 }, userID: 2 }), + deepmerge(TestingIIDXSPScorePB, { scoreData: { percent: 70 }, userID: 3 }), + deepmerge(TestingIIDXSPScorePB, { scoreData: { percent: 80 }, userID: 4 }), + deepmerge(TestingIIDXSPScorePB, { scoreData: { percent: 40 }, userID: 5 }), + ]); + + let { outOf, ranking } = await GetRankingInfo(chartID, 1, 90); + + t.equal(outOf, 5, "Should correctly determine we're out of 5 scores."); + t.equal(ranking, 1, "Should correctly determine we're #1/5."); + + t.end(); + }); + + t.test("#Last in Ranking Info for scores", async (t) => { + // insert some fake scores - our percent is 50. + + await db["score-pbs"].insert([ + deepmerge(TestingIIDXSPScorePB, { scoreData: { percent: 0 }, userID: 1 }), + deepmerge(TestingIIDXSPScorePB, { scoreData: { percent: 60 }, userID: 2 }), + deepmerge(TestingIIDXSPScorePB, { scoreData: { percent: 70 }, userID: 3 }), + deepmerge(TestingIIDXSPScorePB, { scoreData: { percent: 80 }, userID: 4 }), + deepmerge(TestingIIDXSPScorePB, { scoreData: { percent: 40 }, userID: 5 }), + ]); + + let { outOf, ranking } = await GetRankingInfo(chartID, 1, 0); + + t.equal(outOf, 5, "Should correctly determine we're out of 5 scores."); + t.equal(ranking, 5, "Should correctly determine we're #5/5."); + + t.end(); + }); + t.end(); +}); + +t.teardown(CloseMongoConnection); diff --git a/server/src/score-import/framework/core/pb/create-pb-doc.ts b/server/src/score-import/framework/core/pb/create-pb-doc.ts index c8a8402a0..845e3dcf5 100644 --- a/server/src/score-import/framework/core/pb/create-pb-doc.ts +++ b/server/src/score-import/framework/core/pb/create-pb-doc.ts @@ -37,7 +37,7 @@ export async function CreatePBDoc(userID: integer, chartID: string, logger: KtLo } )) as ScoreDocument; // guaranteed to not be null, but... - const pbDoc = await MergeScoreLampIntoPB(userID, scorePB, lampPB); + const pbDoc = await MergeScoreLampIntoPB(userID, scorePB, lampPB, logger); return pbDoc; } @@ -47,7 +47,7 @@ export async function GetRankingInfo( userID: integer, percent: number ): Promise<{ outOf: number; ranking: number }> { - let { outOf, ranking } = await db["score-pbs"].aggregate([ + let res = await db["score-pbs"].aggregate([ // exclude the requesting user because we cannot know whether they already have a pb on this chart // or not - this means we can exec the same logic regardless of whether they already have a pb or not. { $match: { chartID, userID: { $ne: userID } } }, @@ -55,16 +55,22 @@ export async function GetRankingInfo( $group: { _id: null, outOf: { $sum: 1 }, - ranking: { $sum: { $gte: ["$scoreData.percent", percent] } }, + ranking: { $sum: { $cond: [{ $gte: ["$scoreData.percent", percent] }, 1, 0] } }, }, }, - { $project: { outOf: 1, ranking: 1 } }, + // { $project: { outOf: 1, ranking: 1 } }, ]); + if (!res[0]) { + return { outOf: 1, ranking: 1 }; + } + + let { outOf, ranking } = res[0]; + // add one to both stats to account for not including the requesting user // if the field is undefined, there's no other scores to compare to. - outOf = outOf ? outOf++ : 1; - ranking = ranking ? ranking++ : 1; + outOf++; + ranking++; return { outOf, ranking }; } @@ -79,7 +85,8 @@ const GAME_SPECIFIC_MERGE_FNS: Record = { async function MergeScoreLampIntoPB( userID: integer, scorePB: ScoreDocument, - lampPB: ScoreDocument + lampPB: ScoreDocument, + logger: KtLogger ): Promise { let { outOf, ranking } = await GetRankingInfo( scorePB.chartID, @@ -99,6 +106,8 @@ async function MergeScoreLampIntoPB( outOf, ranking, highlight: scorePB.highlight || lampPB.highlight, + game: scorePB.game, + playtype: scorePB.playtype, scoreData: { score: scorePB.scoreData.score, percent: scorePB.scoreData.percent, @@ -119,7 +128,7 @@ async function MergeScoreLampIntoPB( let GameSpecificMergeFn = GAME_SPECIFIC_MERGE_FNS[scorePB.game]; if (GameSpecificMergeFn) { - await GameSpecificMergeFn(pbDoc, scorePB, lampPB); + await GameSpecificMergeFn(pbDoc, scorePB, lampPB, logger); } return pbDoc; diff --git a/server/src/test-utils/test-data.ts b/server/src/test-utils/test-data.ts index d8de5dc45..28ad7f1ca 100644 --- a/server/src/test-utils/test-data.ts +++ b/server/src/test-utils/test-data.ts @@ -1,5 +1,5 @@ import fs from "fs"; -import { ChartDocument } from "kamaitachi-common"; +import { ChartDocument, PBScoreDocument } from "kamaitachi-common"; import path from "path"; import { DryScore } from "../types"; @@ -12,6 +12,10 @@ export const TestingIIDXSPDryScore = GetKTDataJSON( "./kamaitachi/iidx-dryscore.json" ) as DryScore<"iidx:SP">; +export const TestingIIDXSPScorePB = GetKTDataJSON( + "./kamaitachi/iidx-scorepb.json" +) as PBScoreDocument<"iidx:SP">; + export const Testing511SPA = GetKTDataJSON( "./kamaitachi/iidx-511spa.json" ) as ChartDocument<"iidx:SP">; diff --git a/server/src/test-utils/test-data/kamaitachi/iidx-scorepb.json b/server/src/test-utils/test-data/kamaitachi/iidx-scorepb.json new file mode 100644 index 000000000..a203ab9ae --- /dev/null +++ b/server/src/test-utils/test-data/kamaitachi/iidx-scorepb.json @@ -0,0 +1,40 @@ +{ + "chartID": "c2311194e3897ddb5745b1760d2c0141f933e683", + "userID": 1, + "calculatedData": { + "rating": 0, + "lampRating": 0, + "gameSpecific": { + "BPI": 10.10, + "KESDC": 9.558413110870934, + "K%": null + } + }, + "comments": [], + "composedFrom": { + "scorePB": "R9a8d45b332a5ab18ef6f11f052defe2fa497596e69991a8b13ead3ecc3dd17d1", + "lampPB": "R9a8d45b332a5ab18ef6f11f052defe2fa497596e69991a8b13ead3ecc3dd17d1" + }, + "highlight": false, + "outOf": 1, + "ranking": 1, + "scoreData": { + "score": 1479, + "percent": 94.08396946564885, + "esd": 10.64453125, + "grade": "AAA", + "gradeIndex": -1, + "lamp": "EX HARD CLEAR", + "lampIndex": 6, + "hitData": { + "pgreat": 697, + "great": 85 + }, + "hitMeta": { + "bp": 2 + } + }, + "songID": 1, + "game": "iidx", + "playtype": "SP" +} \ No newline at end of file