From 9aa3aee2a759782854178bbca7e735286754c788 Mon Sep 17 00:00:00 2001 From: zk Date: Sat, 28 Mar 2026 22:18:25 +0000 Subject: [PATCH] feat: migrate old scoreDerivers --- docs/docs/game-support/server-impl.md | 16 +++++---- .../src/game-implementations/games/_common.ts | 25 ++------------ .../games/arcaea.oldtest.ts | 3 +- .../src/game-implementations/games/arcaea.ts | 5 +-- .../games/bms-pms.oldtest.ts | 8 ++--- .../src/game-implementations/games/bms-pms.ts | 6 ++-- .../games/chunithm.oldtest.ts | 2 +- .../game-implementations/games/chunithm.ts | 5 +-- .../game-implementations/games/ddr.oldtest.ts | 2 +- .../src/game-implementations/games/ddr.ts | 11 +----- .../games/gitadora.oldtest.ts | 3 +- .../game-implementations/games/gitadora.ts | 5 +-- .../games/iidx.oldtest.ts | 8 ++--- .../src/game-implementations/games/iidx.ts | 9 ++--- .../src/game-implementations/games/itg.ts | 22 +----------- .../games/jubeat.oldtest.ts | 2 +- .../src/game-implementations/games/jubeat.ts | 5 +-- .../games/maimai.oldtest.ts | 2 +- .../src/game-implementations/games/maimai.ts | 11 +----- .../games/maimaidx.oldtest.ts | 3 +- .../game-implementations/games/maimaidx.ts | 5 +-- .../games/museca.oldtest.ts | 2 +- .../src/game-implementations/games/museca.ts | 5 +-- .../games/ongeki.oldtest.ts | 8 ++--- .../src/game-implementations/games/ongeki.ts | 7 +--- .../games/popn.oldtest.ts | 5 +-- .../src/game-implementations/games/popn.ts | 18 +--------- .../games/sdvx.oldtest.ts | 2 +- .../src/game-implementations/games/sdvx.ts | 6 ++-- .../game-implementations/games/usc.oldtest.ts | 2 +- .../src/game-implementations/games/usc.ts | 6 ++-- .../games/wacca.oldtest.ts | 2 +- .../src/game-implementations/games/wacca.ts | 5 +-- .../server/src/game-implementations/types.ts | 34 +++---------------- .../framework/score-importing/derivers.ts | 29 +++------------- 35 files changed, 70 insertions(+), 219 deletions(-) diff --git a/docs/docs/game-support/server-impl.md b/docs/docs/game-support/server-impl.md index ce48dfb14..0a18ced15 100644 --- a/docs/docs/game-support/server-impl.md +++ b/docs/docs/game-support/server-impl.md @@ -36,16 +36,18 @@ return p.isBetween(0, 100)(rate); }, ``` -## `derivers` +## `scoreDeriver` -Any derived metrics you declared need derivers implemented here. This is a function -that takes in the provided metrics and the chart for this score and should return -the metric value we expect. +Any derived metrics you declared are produced by a single function +`(scoreData, chart) => derivedMetrics` that returns all derived fields at once. !!! example -`ts - percent: (metrics, chart) => (100 * metrics.score) / (chart.data.notecount * 2); - ` +```ts +(scoreData, chart) => ({ + percent: (100 * scoreData.score) / (chart.data.notecount * 2), + grade: GetGrade(G, scoreData.score), +}); +``` ## `scoreCalcs`, `sessionCalcs`, `profileCalcs` diff --git a/typescript/server/src/game-implementations/games/_common.ts b/typescript/server/src/game-implementations/games/_common.ts index 9357be823..0191665d6 100644 --- a/typescript/server/src/game-implementations/games/_common.ts +++ b/typescript/server/src/game-implementations/games/_common.ts @@ -1,12 +1,11 @@ import type { - __OLD_KILL_GPTDerivers, ChartSpecificMetricValidator, GPTChartSpecificMetricValidators, GPTClassDerivers, GPTGoalFormatters, GPTGoalProgressFormatters, GPTNewCalcs, - GPTNewDeriver, + GPTScoreDeriver, GPTNewProfileCalcs, GPTNewSessionCalcs, GPTProfileCalculators, @@ -58,21 +57,7 @@ function calculateIIDXLikePercent(exScore: integer, notecount: integer) { type IIDXLikes = GPTStrings["bms" | "iidx" | "pms"]; -/** - * Derivers for both IIDX SP and DP. - * - * and BMS. and PMS. They use the same things. - */ -export const IIDXLIKE_DERIVERS: __OLD_KILL_GPTDerivers = { - percent: ({ score }, chart) => calculateIIDXLikePercent(score, chart.data.notecount), - grade: ({ score }, chart) => { - const percent = calculateIIDXLikePercent(score, chart.data.notecount); - - return GetGrade(IIDXLIKE_GBOUNDARIES, percent); - }, -}; - -export const IIDXLIKE_NEW_DERIVER: GPTNewDeriver = (scoreData, chart) => ({ +export const IIDXLIKE_SCORE_DERIVER: GPTScoreDeriver = (scoreData, chart) => ({ percent: calculateIIDXLikePercent(scoreData.score, chart.data.notecount), grade: IIDXLikeGetGrade(scoreData.score, chart.data.notecount), }); @@ -97,11 +82,7 @@ export const IIDXLIKE_SCORE_VALIDATORS: Array> = [ type SDVXLikes = GPTStrings["sdvx" | "usc"]; -export const SDVXLIKE_DERIVERS: __OLD_KILL_GPTDerivers = { - grade: ({ score }) => GetGrade(SDVXLIKE_GBOUNDARIES, score), -}; - -export const SDVXLIKE_NEW_DERIVER: GPTNewDeriver = (scoreData, _chart) => ({ +export const SDVXLIKE_SCORE_DERIVER: GPTScoreDeriver = (scoreData, _chart) => ({ grade: GetGrade(SDVXLIKE_GBOUNDARIES, scoreData.score), }); diff --git a/typescript/server/src/game-implementations/games/arcaea.oldtest.ts b/typescript/server/src/game-implementations/games/arcaea.oldtest.ts index 5ddb824c1..614b121ce 100644 --- a/typescript/server/src/game-implementations/games/arcaea.oldtest.ts +++ b/typescript/server/src/game-implementations/games/arcaea.oldtest.ts @@ -48,7 +48,8 @@ t.test("Arcaea Implementation", (t) => { t.test("Grade Deriver", (t) => { const f = (score: number, expected: string) => t.equal( - ARCAEA_IMPL.derivers.grade(dmf(baseMetrics, { score }), TestingArcaeaSheriruthFTR), + ARCAEA_IMPL.scoreDeriver(dmf(baseMetrics, { score }) as any, TestingArcaeaSheriruthFTR) + .grade, expected, `A score of ${score.toLocaleString()} should result in grade=${expected}.`, ); diff --git a/typescript/server/src/game-implementations/games/arcaea.ts b/typescript/server/src/game-implementations/games/arcaea.ts index ad5d5aee8..9e7931267 100644 --- a/typescript/server/src/game-implementations/games/arcaea.ts +++ b/typescript/server/src/game-implementations/games/arcaea.ts @@ -23,10 +23,7 @@ export const ARCAEA_IMPL: GPTServerImplementation = { return true; }, }, - derivers: { - grade: ({ score }) => GetGrade(ARCAEA_GBOUNDARIES, score), - }, - newDeriver: (scoreData, _chart) => ({ + scoreDeriver: (scoreData, _chart) => ({ grade: GetGrade(ARCAEA_GBOUNDARIES, scoreData.score), }), newCalcs: (scoreData, _derivedData, chart) => ({ diff --git a/typescript/server/src/game-implementations/games/bms-pms.oldtest.ts b/typescript/server/src/game-implementations/games/bms-pms.oldtest.ts index 17d05517f..f9621ed3a 100644 --- a/typescript/server/src/game-implementations/games/bms-pms.oldtest.ts +++ b/typescript/server/src/game-implementations/games/bms-pms.oldtest.ts @@ -84,7 +84,7 @@ for (const [game, playtype, impl] of [ t.test("Percent", (t) => { const f = (modifant: Partial, expected: any, msg: string) => t.equal( - impl.derivers.percent(dmf(baseMetrics, modifant), chart as any), + impl.scoreDeriver(dmf(baseMetrics, modifant) as any, chart as any).percent, expected, msg, ); @@ -105,10 +105,10 @@ for (const [game, playtype, impl] of [ t.test("Grade", (t) => { const f = (percent: number, expected: any) => t.equal( - impl.derivers.grade( - dmf(baseMetrics, { score: percentToScore(percent) }), + impl.scoreDeriver( + dmf(baseMetrics, { score: percentToScore(percent) }) as any, chart as any, - ), + ).grade, expected, `A percent of ${percent}% should result in grade=${expected}.`, ); diff --git a/typescript/server/src/game-implementations/games/bms-pms.ts b/typescript/server/src/game-implementations/games/bms-pms.ts index d7cce6496..437f3fb8b 100644 --- a/typescript/server/src/game-implementations/games/bms-pms.ts +++ b/typescript/server/src/game-implementations/games/bms-pms.ts @@ -9,8 +9,7 @@ import { GoalFmtPercent, GoalOutOfFmtPercent, GradeGoalFormatter, - IIDXLIKE_DERIVERS, - IIDXLIKE_NEW_DERIVER, + IIDXLIKE_SCORE_DERIVER, IIDXLIKE_PB_RANKING_VALUES, IIDXLIKE_SCORE_VALIDATORS, IIDXLIKE_VALIDATORS, @@ -41,8 +40,7 @@ const BMS_PMS_MERGERS: Array> = [ // implementations. Nice. const BMS_IMPL: GPTServerImplementation = { - derivers: IIDXLIKE_DERIVERS, - newDeriver: IIDXLIKE_NEW_DERIVER, + scoreDeriver: IIDXLIKE_SCORE_DERIVER, newCalcs: SGL_NEW_CALCS, newSessionCalcs: SGL_NEW_SESSION_CALCS, newProfileCalcs: SGL_NEW_PROFILE_CALCS, diff --git a/typescript/server/src/game-implementations/games/chunithm.oldtest.ts b/typescript/server/src/game-implementations/games/chunithm.oldtest.ts index 8f2c481a6..7d1705142 100644 --- a/typescript/server/src/game-implementations/games/chunithm.oldtest.ts +++ b/typescript/server/src/game-implementations/games/chunithm.oldtest.ts @@ -42,7 +42,7 @@ t.test("CHUNITHM Implementation", (t) => { t.test("Grade Deriver", (t) => { const f = (score: number, expected: any) => t.equal( - CHUNITHM_IMPL.derivers.grade(dmf(baseMetrics, { score }), CHUNITHMBBKKChart), + CHUNITHM_IMPL.scoreDeriver(dmf(baseMetrics, { score }) as any, CHUNITHMBBKKChart).grade, expected, `A score of ${score.toLocaleString()} should result in grade=${expected}.`, ); diff --git a/typescript/server/src/game-implementations/games/chunithm.ts b/typescript/server/src/game-implementations/games/chunithm.ts index 33fbb0c15..29af0fb2c 100644 --- a/typescript/server/src/game-implementations/games/chunithm.ts +++ b/typescript/server/src/game-implementations/games/chunithm.ts @@ -11,10 +11,7 @@ import { GoalFmtScore, GoalOutOfFmtScore, GradeGoalFormatter } from "./_common"; export const CHUNITHM_IMPL: GPTServerImplementation<"chunithm:Single"> = { chartSpecificValidators: {}, - derivers: { - grade: ({ score }) => GetGrade(CHUNITHM_GBOUNDARIES, score), - }, - newDeriver: (scoreData, _chart) => ({ + scoreDeriver: (scoreData, _chart) => ({ grade: GetGrade(CHUNITHM_GBOUNDARIES, scoreData.score), }), newCalcs: (scoreData, _derivedData, chart) => ({ diff --git a/typescript/server/src/game-implementations/games/ddr.oldtest.ts b/typescript/server/src/game-implementations/games/ddr.oldtest.ts index c66e87f3c..d9d9105d2 100644 --- a/typescript/server/src/game-implementations/games/ddr.oldtest.ts +++ b/typescript/server/src/game-implementations/games/ddr.oldtest.ts @@ -25,7 +25,7 @@ t.test("DDR Implementation", (t) => { t.test("Grade", (t) => { const f = (score: number, expected: any) => t.equal( - impl.derivers.grade(dmf(baseMetrics, { score }), TestingDDRSP as any), + impl.scoreDeriver(dmf(baseMetrics, { score }) as any, TestingDDRSP as any).grade, expected, `A score of ${score} should result in grade=${expected}.`, ); diff --git a/typescript/server/src/game-implementations/games/ddr.ts b/typescript/server/src/game-implementations/games/ddr.ts index 60cb3799b..07554234a 100644 --- a/typescript/server/src/game-implementations/games/ddr.ts +++ b/typescript/server/src/game-implementations/games/ddr.ts @@ -312,16 +312,7 @@ export const DDR_IMPL: GPTServerImplementation<"ddr:DP" | "ddr:SP"> = { return { flare: IsNullish(flarePoints) ? null : DeriveFlareClass(flarePoints) }; }, defaultMergeRefName: "Best Score", - derivers: { - grade: ({ score, lamp }) => { - if (lamp === "FAILED") { - return "E"; - } - - return GetGrade(DDR_GBOUNDARIES, score); - }, - }, - newDeriver: (scoreData, _chart) => ({ + scoreDeriver: (scoreData, _chart) => ({ grade: scoreData.lamp === "FAILED" ? "E" : GetGrade(DDR_GBOUNDARIES, scoreData.score), }), newCalcs: (scoreData, _derivedData, chart) => { diff --git a/typescript/server/src/game-implementations/games/gitadora.oldtest.ts b/typescript/server/src/game-implementations/games/gitadora.oldtest.ts index 6f83bb013..60f1b7caa 100644 --- a/typescript/server/src/game-implementations/games/gitadora.oldtest.ts +++ b/typescript/server/src/game-implementations/games/gitadora.oldtest.ts @@ -46,7 +46,8 @@ for (const [playtype, impl] of [ t.test("Grade Deriver", (t) => { const f = (percent: number, expected: any) => t.equal( - impl.derivers.grade(dmf(baseMetrics, { percent }), TestingGitadoraChart as any), + impl.scoreDeriver(dmf(baseMetrics, { percent }) as any, TestingGitadoraChart as any) + .grade, expected, `A percent of ${percent}% should result in grade=${expected}.`, ); diff --git a/typescript/server/src/game-implementations/games/gitadora.ts b/typescript/server/src/game-implementations/games/gitadora.ts index 3e866f6ad..977f3197e 100644 --- a/typescript/server/src/game-implementations/games/gitadora.ts +++ b/typescript/server/src/game-implementations/games/gitadora.ts @@ -11,10 +11,7 @@ import { GoalFmtPercent, GoalOutOfFmtPercent, GradeGoalFormatter } from "./_comm const GITADORA_IMPL: GPTServerImplementation<"gitadora:Dora" | "gitadora:Gita"> = { chartSpecificValidators: {}, - derivers: { - grade: ({ percent }) => GetGrade(GITADORA_GBOUNDARIES, percent), - }, - newDeriver: (scoreData, _chart) => ({ + scoreDeriver: (scoreData, _chart) => ({ grade: GetGrade(GITADORA_GBOUNDARIES, scoreData.percent), }), newCalcs: (scoreData, _derivedData, chart) => ({ diff --git a/typescript/server/src/game-implementations/games/iidx.oldtest.ts b/typescript/server/src/game-implementations/games/iidx.oldtest.ts index e5df78085..ded287750 100644 --- a/typescript/server/src/game-implementations/games/iidx.oldtest.ts +++ b/typescript/server/src/game-implementations/games/iidx.oldtest.ts @@ -39,7 +39,7 @@ t.test("IIDX Implementation", (t) => { t.test("Percent", (t) => { const f = (modifant: Partial, expected: any, msg: string) => t.equal( - impl.derivers.percent(dmf(baseMetrics, modifant), Testing511SPA as any), + impl.scoreDeriver(dmf(baseMetrics, modifant) as any, Testing511SPA as any).percent, expected, msg, ); @@ -64,10 +64,10 @@ t.test("IIDX Implementation", (t) => { t.test("Grade", (t) => { const f = (percent: number, expected: any) => t.equal( - impl.derivers.grade( - dmf(baseMetrics, { score: percentToScore(percent) }), + impl.scoreDeriver( + dmf(baseMetrics, { score: percentToScore(percent) }) as any, Testing511SPA as any, - ), + ).grade, expected, `A percent of ${percent}% should result in grade=${expected}.`, ); diff --git a/typescript/server/src/game-implementations/games/iidx.ts b/typescript/server/src/game-implementations/games/iidx.ts index 9fa6b69e7..be1c8d9ec 100644 --- a/typescript/server/src/game-implementations/games/iidx.ts +++ b/typescript/server/src/game-implementations/games/iidx.ts @@ -20,8 +20,7 @@ import { GoalFmtPercent, GoalOutOfFmtPercent, GradeGoalFormatter, - IIDXLIKE_DERIVERS, - IIDXLIKE_NEW_DERIVER, + IIDXLIKE_SCORE_DERIVER, IIDXLIKE_PB_RANKING_VALUES, IIDXLIKE_SCORE_VALIDATORS, IIDXLIKE_VALIDATORS, @@ -135,8 +134,7 @@ const IIDX_GOAL_PG_FMT: GPTGoalProgressFormatters<"iidx:DP" | "iidx:SP"> = { }; export const IIDX_SP_IMPL: GPTServerImplementation<"iidx:SP"> = { - derivers: IIDXLIKE_DERIVERS, - newDeriver: IIDXLIKE_NEW_DERIVER, + scoreDeriver: IIDXLIKE_SCORE_DERIVER, chartSpecificValidators: IIDXLIKE_VALIDATORS, pbRankingValues: IIDXLIKE_PB_RANKING_VALUES, newCalcs: (scoreData, _derivedData, chart) => { @@ -219,8 +217,7 @@ export const IIDX_SP_IMPL: GPTServerImplementation<"iidx:SP"> = { }; export const IIDX_DP_IMPL: GPTServerImplementation<"iidx:DP"> = { - derivers: IIDXLIKE_DERIVERS, - newDeriver: IIDXLIKE_NEW_DERIVER, + scoreDeriver: IIDXLIKE_SCORE_DERIVER, chartSpecificValidators: IIDXLIKE_VALIDATORS, pbRankingValues: IIDXLIKE_PB_RANKING_VALUES, newCalcs: (scoreData, _derivedData, chart) => { diff --git a/typescript/server/src/game-implementations/games/itg.ts b/typescript/server/src/game-implementations/games/itg.ts index 860c30e2e..a8b1a59a8 100644 --- a/typescript/server/src/game-implementations/games/itg.ts +++ b/typescript/server/src/game-implementations/games/itg.ts @@ -11,27 +11,7 @@ import { GoalFmtPercent, GradeGoalFormatter } from "./_common"; export const ITG_STAMINA_IMPL: GPTServerImplementation<"itg:Stamina"> = { chartSpecificValidators: {}, - derivers: { - finalPercent: (metrics) => { - // *important* - // don't check if metrics.survivedPercent === 100, as due to floating - // point inaccuracies, it's possible to have a 100% fail - // (on extremely long charts, for example) - if (metrics.lamp === "FAILED") { - return metrics.survivedPercent; - } - - return 100 + metrics.scorePercent; - }, - grade: ({ scorePercent, lamp }) => { - if (lamp === "FAILED") { - return "F"; - } - - return GetGrade(ITG_GBOUNDARIES, scorePercent); - }, - }, - newDeriver: (scoreData, _chart) => ({ + scoreDeriver: (scoreData, _chart) => ({ // *important*: don't check survivedPercent === 100 — floating point can // produce a 100% survived-percent on a fail for very long charts. finalPercent: diff --git a/typescript/server/src/game-implementations/games/jubeat.oldtest.ts b/typescript/server/src/game-implementations/games/jubeat.oldtest.ts index 8f99928f7..69a8fc727 100644 --- a/typescript/server/src/game-implementations/games/jubeat.oldtest.ts +++ b/typescript/server/src/game-implementations/games/jubeat.oldtest.ts @@ -41,7 +41,7 @@ t.test("Jubeat Implementation", (t) => { t.test("Grade Deriver", (t) => { const f = (score: number, expected: any) => t.equal( - JUBEAT_IMPL.derivers.grade(dmf(baseMetrics, { score }), TestingJubeatChart), + JUBEAT_IMPL.scoreDeriver(dmf(baseMetrics, { score }) as any, TestingJubeatChart).grade, expected, `A score of ${score.toLocaleString()} should result in grade=${expected}.`, ); diff --git a/typescript/server/src/game-implementations/games/jubeat.ts b/typescript/server/src/game-implementations/games/jubeat.ts index 09ad1e50f..5ed8eafee 100644 --- a/typescript/server/src/game-implementations/games/jubeat.ts +++ b/typescript/server/src/game-implementations/games/jubeat.ts @@ -162,10 +162,7 @@ export const JUBEAT_IMPL: GPTServerImplementation<"jubeat:Single"> = { } }, }, - derivers: { - grade: ({ score }) => GetGrade(JUBEAT_GBOUNDARIES, score), - }, - newDeriver: (scoreData, _chart) => ({ + scoreDeriver: (scoreData, _chart) => ({ grade: GetGrade(JUBEAT_GBOUNDARIES, scoreData.score), }), newCalcs: (scoreData, _derivedData, chart) => ({ diff --git a/typescript/server/src/game-implementations/games/maimai.oldtest.ts b/typescript/server/src/game-implementations/games/maimai.oldtest.ts index 8e3d995ce..802642e6a 100644 --- a/typescript/server/src/game-implementations/games/maimai.oldtest.ts +++ b/typescript/server/src/game-implementations/games/maimai.oldtest.ts @@ -58,7 +58,7 @@ t.test("maimai Implementation", (t) => { t.test("Grade Deriver", (t) => { const f = (percent: number, expected: string) => t.equal( - MAIMAI_IMPL.derivers.grade(dmf(baseMetrics, { percent }), TestingMaimaiChart), + MAIMAI_IMPL.scoreDeriver(dmf(baseMetrics, { percent }) as any, TestingMaimaiChart).grade, expected, `A percent of ${percent} should result in grade=${expected}.`, ); diff --git a/typescript/server/src/game-implementations/games/maimai.ts b/typescript/server/src/game-implementations/games/maimai.ts index df99274e5..ae9dfbfbe 100644 --- a/typescript/server/src/game-implementations/games/maimai.ts +++ b/typescript/server/src/game-implementations/games/maimai.ts @@ -23,16 +23,7 @@ export const MAIMAI_IMPL: GPTServerImplementation<"maimai:Single"> = { return true; }, }, - derivers: { - grade: ({ percent }, chart) => { - if (percent === chart.data.maxPercent) { - return "SSS+"; - } - - return GetGrade(MAIMAI_GBOUNDARIES, percent); - }, - }, - newDeriver: (scoreData, chart) => ({ + scoreDeriver: (scoreData, chart) => ({ grade: scoreData.percent === chart.data.maxPercent ? "SSS+" diff --git a/typescript/server/src/game-implementations/games/maimaidx.oldtest.ts b/typescript/server/src/game-implementations/games/maimaidx.oldtest.ts index 088380e8f..686ef8c0d 100644 --- a/typescript/server/src/game-implementations/games/maimaidx.oldtest.ts +++ b/typescript/server/src/game-implementations/games/maimaidx.oldtest.ts @@ -38,7 +38,8 @@ t.test("Maimai DX Implementation", (t) => { t.test("Grade Deriver", (t) => { const f = (percent: number, expected: any) => t.equal( - MAIMAIDX_IMPL.derivers.grade(dmf(baseMetrics, { percent }), TestingMaimaiDXChart), + MAIMAIDX_IMPL.scoreDeriver(dmf(baseMetrics, { percent }) as any, TestingMaimaiDXChart) + .grade, expected, `A percent of ${percent} should result in grade=${expected}.`, ); diff --git a/typescript/server/src/game-implementations/games/maimaidx.ts b/typescript/server/src/game-implementations/games/maimaidx.ts index bf05f7152..09ceb2bc5 100644 --- a/typescript/server/src/game-implementations/games/maimaidx.ts +++ b/typescript/server/src/game-implementations/games/maimaidx.ts @@ -11,10 +11,7 @@ import { GoalFmtPercent, GoalOutOfFmtPercent, GradeGoalFormatter } from "./_comm export const MAIMAIDX_IMPL: GPTServerImplementation<"maimaidx:Single"> = { chartSpecificValidators: {}, - derivers: { - grade: ({ percent }) => GetGrade(MAIMAIDX_GBOUNDARIES, percent), - }, - newDeriver: (scoreData, _chart) => ({ + scoreDeriver: (scoreData, _chart) => ({ grade: GetGrade(MAIMAIDX_GBOUNDARIES, scoreData.percent), }), newCalcs: (scoreData, _derivedData, chart) => ({ diff --git a/typescript/server/src/game-implementations/games/museca.oldtest.ts b/typescript/server/src/game-implementations/games/museca.oldtest.ts index d09d17800..b9de78584 100644 --- a/typescript/server/src/game-implementations/games/museca.oldtest.ts +++ b/typescript/server/src/game-implementations/games/museca.oldtest.ts @@ -33,7 +33,7 @@ t.test("MUSECA Implementation", (t) => { t.test("Grade Deriver", (t) => { const f = (score: number, expected: any) => t.equal( - MUSECA_IMPL.derivers.grade(dmf(baseMetrics, { score }), TestingMusecaChart), + MUSECA_IMPL.scoreDeriver(dmf(baseMetrics, { score }) as any, TestingMusecaChart).grade, expected, `A score of ${score.toLocaleString()} should result in grade=${expected}.`, ); diff --git a/typescript/server/src/game-implementations/games/museca.ts b/typescript/server/src/game-implementations/games/museca.ts index 60c2e3958..f21e71619 100644 --- a/typescript/server/src/game-implementations/games/museca.ts +++ b/typescript/server/src/game-implementations/games/museca.ts @@ -10,10 +10,7 @@ import { GoalFmtScore, GoalOutOfFmtScore, GradeGoalFormatter } from "./_common"; export const MUSECA_IMPL: GPTServerImplementation<"museca:Single"> = { chartSpecificValidators: {}, - derivers: { - grade: ({ score }) => GetGrade(MUSECA_GBOUNDARIES, score), - }, - newDeriver: (scoreData, _chart) => ({ + scoreDeriver: (scoreData, _chart) => ({ grade: GetGrade(MUSECA_GBOUNDARIES, scoreData.score), }), newCalcs: (scoreData, _derivedData, chart) => ({ diff --git a/typescript/server/src/game-implementations/games/ongeki.oldtest.ts b/typescript/server/src/game-implementations/games/ongeki.oldtest.ts index 83c194eb4..f5e79f4e8 100644 --- a/typescript/server/src/game-implementations/games/ongeki.oldtest.ts +++ b/typescript/server/src/game-implementations/games/ongeki.oldtest.ts @@ -48,7 +48,7 @@ t.test("ONGEKI Implementation", (t: any) => { t.test("Grade Deriver", (t: any) => { const f = (score: number, expected: string) => t.equal( - ONGEKI_IMPL.derivers.grade(dmf(baseMetrics, { score }), TestingOngekiChart), + ONGEKI_IMPL.scoreDeriver(dmf(baseMetrics, { score }) as any, TestingOngekiChart).grade, expected, `A score of ${score.toLocaleString()} should result in grade=${expected}.`, ); @@ -73,10 +73,10 @@ t.test("ONGEKI Implementation", (t: any) => { t.test("Star Deriver", (t: any) => { const f = (platinumScore: number, expected: number) => t.equal( - ONGEKI_IMPL.derivers.platinumStars( - dmf(baseMetrics, { platinumScore }), + ONGEKI_IMPL.scoreDeriver( + dmf(baseMetrics, { platinumScore }) as any, TestingOngekiChart, - ), + ).platinumStars, expected, `A score of ${platinumScore.toLocaleString()} should result in stars=${expected}.`, ); diff --git a/typescript/server/src/game-implementations/games/ongeki.ts b/typescript/server/src/game-implementations/games/ongeki.ts index b04b64850..ba38788d5 100644 --- a/typescript/server/src/game-implementations/games/ongeki.ts +++ b/typescript/server/src/game-implementations/games/ongeki.ts @@ -63,12 +63,7 @@ export const ONGEKI_IMPL: GPTServerImplementation<"ongeki:Single"> = { return true; }, }, - derivers: { - grade: ({ score }) => GetGrade(ONGEKI_GBOUNDARIES, score), - platinumStars: ({ platinumScore }, chart) => - starCount(platinumScore, chart.data.maxPlatScore), - }, - newDeriver: (scoreData, chart) => ({ + scoreDeriver: (scoreData, chart) => ({ grade: GetGrade(ONGEKI_GBOUNDARIES, scoreData.score), platinumStars: starCount(scoreData.platinumScore, chart.data.maxPlatScore), }), diff --git a/typescript/server/src/game-implementations/games/popn.oldtest.ts b/typescript/server/src/game-implementations/games/popn.oldtest.ts index 0e9c7bec1..773629c98 100644 --- a/typescript/server/src/game-implementations/games/popn.oldtest.ts +++ b/typescript/server/src/game-implementations/games/popn.oldtest.ts @@ -41,7 +41,7 @@ t.test("Pop'n Implementation", (t) => { t.test("Grade Deriver", (t) => { const f = (score: number, expected: any) => t.equal( - POPN_9B_IMPL.derivers.grade(dmf(baseMetrics, { score }), TestingPopnChart), + POPN_9B_IMPL.scoreDeriver(dmf(baseMetrics, { score }) as any, TestingPopnChart).grade, expected, `A score of ${score.toLocaleString()} should result in grade=${expected}.`, ); @@ -61,7 +61,8 @@ t.test("Pop'n Implementation", (t) => { t.test("Lamp Deriver", (t) => { const f = (clearMedal: ProvidedMetrics["popn:9B"]["clearMedal"], expected: any) => t.equal( - POPN_9B_IMPL.derivers.lamp(dmf(baseMetrics, { clearMedal }), TestingPopnChart), + POPN_9B_IMPL.scoreDeriver(dmf(baseMetrics, { clearMedal }) as any, TestingPopnChart) + .lamp, expected, `A clear medal of ${clearMedal} should result in lamp=${expected}.`, ); diff --git a/typescript/server/src/game-implementations/games/popn.ts b/typescript/server/src/game-implementations/games/popn.ts index 8ba36b108..f76cf3f9e 100644 --- a/typescript/server/src/game-implementations/games/popn.ts +++ b/typescript/server/src/game-implementations/games/popn.ts @@ -35,23 +35,7 @@ export function PopnClearMedalToLamp( export const POPN_9B_IMPL: GPTServerImplementation<"popn:9B"> = { chartSpecificValidators: {}, - derivers: { - lamp: ({ clearMedal }) => PopnClearMedalToLamp(clearMedal), - grade: ({ score, clearMedal }) => { - const gradeString = GetGrade(POPN_GBOUNDARIES, score); - - // lol double-calc - const lamp = PopnClearMedalToLamp(clearMedal); - - // grades are kneecapped at "A" if you failed. - if (score >= 90_000 && lamp === "FAILED") { - return "A"; - } - - return gradeString; - }, - }, - newDeriver: (scoreData, _chart) => { + scoreDeriver: (scoreData, _chart) => { const lamp = PopnClearMedalToLamp(scoreData.clearMedal); return { diff --git a/typescript/server/src/game-implementations/games/sdvx.oldtest.ts b/typescript/server/src/game-implementations/games/sdvx.oldtest.ts index 5bf0428a0..ccd3bffc8 100644 --- a/typescript/server/src/game-implementations/games/sdvx.oldtest.ts +++ b/typescript/server/src/game-implementations/games/sdvx.oldtest.ts @@ -49,7 +49,7 @@ t.test("SDVX Implementation", (t) => { t.test("Grade Deriver", (t) => { const f = (score: number, expected: any) => t.equal( - SDVX_IMPL.derivers.grade(dmf(baseMetrics, { score }), TestingSDVXAlbidaChart), + SDVX_IMPL.scoreDeriver(dmf(baseMetrics, { score }) as any, TestingSDVXAlbidaChart).grade, expected, `A score of ${score.toLocaleString()} should result in grade=${expected}.`, ); diff --git a/typescript/server/src/game-implementations/games/sdvx.ts b/typescript/server/src/game-implementations/games/sdvx.ts index c4646ac12..bdd1b7343 100644 --- a/typescript/server/src/game-implementations/games/sdvx.ts +++ b/typescript/server/src/game-implementations/games/sdvx.ts @@ -5,12 +5,11 @@ import { CreatePBMergeFor } from "#game-implementations/utils/pb-merge"; import { SDVXLIKE_CLASS_DERIVERS, SDVXLIKE_DEFAULT_MERGE_NAME, - SDVXLIKE_DERIVERS, SDVXLIKE_GOAL_FMT, SDVXLIKE_GOAL_OO_FMT, SDVXLIKE_GOAL_PG_FMT, SDVXLIKE_NEW_CALCS, - SDVXLIKE_NEW_DERIVER, + SDVXLIKE_SCORE_DERIVER, SDVXLIKE_NEW_PROFILE_CALCS, SDVXLIKE_NEW_SESSION_CALCS, SDVXLIKE_PROFILE_CALCS, @@ -20,8 +19,7 @@ import { } from "./_common"; export const SDVX_IMPL: GPTServerImplementation<"sdvx:Single"> = { - derivers: SDVXLIKE_DERIVERS, - newDeriver: SDVXLIKE_NEW_DERIVER, + scoreDeriver: SDVXLIKE_SCORE_DERIVER, newCalcs: SDVXLIKE_NEW_CALCS, newSessionCalcs: SDVXLIKE_NEW_SESSION_CALCS, newProfileCalcs: SDVXLIKE_NEW_PROFILE_CALCS, diff --git a/typescript/server/src/game-implementations/games/usc.oldtest.ts b/typescript/server/src/game-implementations/games/usc.oldtest.ts index 4287225af..b04f32156 100644 --- a/typescript/server/src/game-implementations/games/usc.oldtest.ts +++ b/typescript/server/src/game-implementations/games/usc.oldtest.ts @@ -44,7 +44,7 @@ for (const [playtype, impl] of [ t.test("Grade Deriver", (t) => { const f = (score: number, expected: any) => t.equal( - impl.derivers.grade(dmf(baseMetrics, { score }), TestingUSCChart as any), + impl.scoreDeriver(dmf(baseMetrics, { score }) as any, TestingUSCChart as any).grade, expected, `A score of ${score.toLocaleString()} should result in grade=${expected}.`, ); diff --git a/typescript/server/src/game-implementations/games/usc.ts b/typescript/server/src/game-implementations/games/usc.ts index f4b2fd914..a71b6b21f 100644 --- a/typescript/server/src/game-implementations/games/usc.ts +++ b/typescript/server/src/game-implementations/games/usc.ts @@ -4,12 +4,11 @@ import type { GPTStrings } from "tachi-common"; import { SDVXLIKE_CLASS_DERIVERS, SDVXLIKE_DEFAULT_MERGE_NAME, - SDVXLIKE_DERIVERS, SDVXLIKE_GOAL_FMT, SDVXLIKE_GOAL_OO_FMT, SDVXLIKE_GOAL_PG_FMT, SDVXLIKE_NEW_CALCS, - SDVXLIKE_NEW_DERIVER, + SDVXLIKE_SCORE_DERIVER, SDVXLIKE_NEW_PROFILE_CALCS, SDVXLIKE_NEW_SESSION_CALCS, SDVXLIKE_PB_MERGERS, @@ -20,8 +19,7 @@ import { } from "./_common"; const USC_IMPL: GPTServerImplementation = { - derivers: SDVXLIKE_DERIVERS, - newDeriver: SDVXLIKE_NEW_DERIVER, + scoreDeriver: SDVXLIKE_SCORE_DERIVER, newCalcs: SDVXLIKE_NEW_CALCS, newSessionCalcs: SDVXLIKE_NEW_SESSION_CALCS, newProfileCalcs: SDVXLIKE_NEW_PROFILE_CALCS, diff --git a/typescript/server/src/game-implementations/games/wacca.oldtest.ts b/typescript/server/src/game-implementations/games/wacca.oldtest.ts index 20beab92c..6b20c5c66 100644 --- a/typescript/server/src/game-implementations/games/wacca.oldtest.ts +++ b/typescript/server/src/game-implementations/games/wacca.oldtest.ts @@ -41,7 +41,7 @@ t.test("WACCA Implementation", (t) => { t.test("Grade Deriver", (t) => { const f = (score: number, expected: any) => t.equal( - WACCA_IMPL.derivers.grade(dmf(baseMetrics, { score }), TestingWaccaPupaExp), + WACCA_IMPL.scoreDeriver(dmf(baseMetrics, { score }) as any, TestingWaccaPupaExp).grade, expected, `A score of ${score.toLocaleString()} should result in grade=${expected}.`, ); diff --git a/typescript/server/src/game-implementations/games/wacca.ts b/typescript/server/src/game-implementations/games/wacca.ts index ed9af0832..c317453b7 100644 --- a/typescript/server/src/game-implementations/games/wacca.ts +++ b/typescript/server/src/game-implementations/games/wacca.ts @@ -11,10 +11,7 @@ import { GoalFmtScore, GoalOutOfFmtScore, GradeGoalFormatter } from "./_common"; export const WACCA_IMPL: GPTServerImplementation<"wacca:Single"> = { chartSpecificValidators: {}, - derivers: { - grade: ({ score }) => GetGrade(WACCA_GBOUNDARIES, score), - }, - newDeriver: (scoreData, _chart) => ({ + scoreDeriver: (scoreData, _chart) => ({ grade: GetGrade(WACCA_GBOUNDARIES, scoreData.score), }), newCalcs: (scoreData, _derivedData, chart) => ({ diff --git a/typescript/server/src/game-implementations/types.ts b/typescript/server/src/game-implementations/types.ts index 3caba2b7d..3215218ac 100644 --- a/typescript/server/src/game-implementations/types.ts +++ b/typescript/server/src/game-implementations/types.ts @@ -2,7 +2,6 @@ import type { DryScoreData } from "#lib/score-import/framework/common/types"; import type { MONGO_PBScoreDocumentNoRank } from "#lib/score-import/framework/pb/create-pb-doc"; import type { ClassConfigs, - ConfDerivedMetrics, ConfScoreMetrics, GPTString, GPTStringToGame, @@ -20,11 +19,7 @@ import type { SessionRatingAlgorithms, } from "tachi-common"; import type { DerivedClassConfig } from "tachi-common/types/game-config-utils"; -import type { - __OLD_KILL_ScoreMetricDeriver, - AllConfMetrics, - ConfEnumScoreMetric, -} from "tachi-common/types/metrics"; +import type { AllConfMetrics, ConfEnumScoreMetric } from "tachi-common/types/metrics"; /** * Validate this chart-specific metric. This should return a string representing an @@ -117,22 +112,8 @@ export type GPTChartSpecificMetricValidators = { : never]: ChartSpecificMetricValidator; }; -export type __OLD_KILL_GPTDerivers = { - [K in keyof ConfDerivedMetrics[GPT]]: __OLD_KILL_ScoreMetricDeriver< - // @ts-expect-error This *might* be a bug in the typescript compiler - // as this works for all GPT inputs normally. - // Possibly some generic nonsense but like... - - // can you really blame them for this not working? - // can you? LOOK at what we're doing. - ConfDerivedMetrics[GPT][K], - GPT - >; -}; - -// New-style deriver; just f(scoreData, chart) -> derivedMetrics -// instead of the overly complex shit above. -export type GPTNewDeriver = ( +/** Derives chart-dependent score metrics (grade, percent, …) from provided score data. */ +export type GPTScoreDeriver = ( scoreData: MONGO_ScoreData, chart: MONGO_ChartDocument, ) => MongoDerivedMetrics[GPT]; @@ -241,14 +222,7 @@ export interface GPTServerImplementation { /** * How should we derive the derived metrics for this game? */ - derivers: __OLD_KILL_GPTDerivers; - - /** - * How should we derive the derived metrics for this game? - * - * New style, simpler function. - */ - newDeriver: GPTNewDeriver; + scoreDeriver: GPTScoreDeriver; /** * How should we compute the score rating algorithms for this game? diff --git a/typescript/server/src/lib/score-import/framework/score-importing/derivers.ts b/typescript/server/src/lib/score-import/framework/score-importing/derivers.ts index 4b641841f..ba8e300f3 100644 --- a/typescript/server/src/lib/score-import/framework/score-importing/derivers.ts +++ b/typescript/server/src/lib/score-import/framework/score-importing/derivers.ts @@ -1,7 +1,4 @@ -import type { __OLD_KILL_GPTDerivers } from "#game-implementations/types"; import type { KtLogger } from "#lib/log/log"; -import type { MetricValue } from "tachi-common/types/metrics"; - import { GPT_SERVER_IMPLEMENTATIONS } from "#game-implementations/game-implementations"; import { GetGPTConfig, @@ -27,28 +24,10 @@ function DeriveMetrics( metrics: DryScoreData, chart: MONGO_ChartDocument, ) { - const deriverImplementation: __OLD_KILL_GPTDerivers = - GPT_SERVER_IMPLEMENTATIONS[gpt].derivers; - - const derivedMetrics: Record = {}; - - const gptConfig = GetGPTConfig(gpt); - - for (const [key, fn] of Object.entries(deriverImplementation)) { - const metricConfig = gptConfig.derivedMetrics[key]; - - if (!metricConfig) { - throw new InternalFailure( - `${gpt} has a deriver defined for '${key}', but no such field exists in the config?`, - ); - } - - const value = fn(metrics, chart); - - derivedMetrics[key] = value; - } - - return derivedMetrics as MongoDerivedMetrics[GPT]; + return GPT_SERVER_IMPLEMENTATIONS[gpt].scoreDeriver( + metrics as MONGO_ScoreData, + chart, + ) as MongoDerivedMetrics[GPT]; } export function CreateEnumIndexes(gpt: GPT, metrics: any, log: KtLogger) {