From 7be66e9cb371bb5c656b20d08acd05e4b0e738df Mon Sep 17 00:00:00 2001 From: Christian Fehmer Date: Mon, 24 Feb 2025 12:04:33 +0100 Subject: [PATCH] fix: rounding issues causing daily leaderboard to be out of order sometimes (@fehmer) (#6303) --- backend/__tests__/utils/misc.spec.ts | 14 ++++++++++++++ backend/src/utils/misc.ts | 6 ++++-- 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/backend/__tests__/utils/misc.spec.ts b/backend/__tests__/utils/misc.spec.ts index c4fb2c6ff..419a0876a 100644 --- a/backend/__tests__/utils/misc.spec.ts +++ b/backend/__tests__/utils/misc.spec.ts @@ -62,6 +62,20 @@ describe("Misc Utils", () => { timestamp: 1653591901000, expectedScore: 1196200960717699, }, + { + wpm: 196.205, + acc: 96.075, + timestamp: 1653591901000, + expectedScore: 1196210960817699, + }, + { + // this one is particularly important - in JS 154.39 * 100 is equal to 15438.999999999998 + // thanks floating point errors! + wpm: 154.39, + acc: 96.14, + timestamp: 1740333827000, + expectedScore: 1154390961421373, + }, ]; _.each(testCases, ({ wpm, acc, timestamp, expectedScore }) => { diff --git a/backend/src/utils/misc.ts b/backend/src/utils/misc.ts index d035c9cc6..9a66b4ef6 100644 --- a/backend/src/utils/misc.ts +++ b/backend/src/utils/misc.ts @@ -67,8 +67,10 @@ export function matchesAPattern(text: string, pattern: string): boolean { } export function kogascore(wpm: number, acc: number, timestamp: number): number { - const normalizedWpm = Math.floor(wpm * 100); - const normalizedAcc = Math.floor(acc * 100); + // its safe to round after multiplying by 100 (99.99 * 100 rounded will be 9999 not 100) + // rounding is necessary to protect against floating point errors + const normalizedWpm = Math.round(wpm * 100); + const normalizedAcc = Math.round(acc * 100); const padAmount = 100000; const firstPart = (padAmount + normalizedWpm) * padAmount;