From 5d458988932443400b5bcbfb6a5dea04ace18a28 Mon Sep 17 00:00:00 2001 From: Bruce Berrios <58147810+Bruception@users.noreply.github.com> Date: Thu, 26 May 2022 16:13:42 -0400 Subject: [PATCH 1/2] check if user is banned (#3029) --- backend/src/api/controllers/result.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/backend/src/api/controllers/result.ts b/backend/src/api/controllers/result.ts index 480b1b8f7..24b71c4de 100644 --- a/backend/src/api/controllers/result.ts +++ b/backend/src/api/controllers/result.ts @@ -321,6 +321,7 @@ export async function addResult( const validResultCriteria = (funbox === "none" || funbox === "plus_one" || funbox === "plus_two") && !bailedOut && + !user.banned && (user.timeTyping ?? 0) > 7200; if (dailyLeaderboard && validResultCriteria) { From cd767bff1cd88dce40667a82bda9afbc6a2dcb5b Mon Sep 17 00:00:00 2001 From: Bruce Berrios <58147810+Bruception@users.noreply.github.com> Date: Thu, 26 May 2022 20:21:23 -0400 Subject: [PATCH 2/2] Use better score metric (#3030) --- backend/__tests__/utils/misc.spec.ts | 62 +++++++++++++++++++++++++ backend/src/utils/daily-leaderboards.ts | 31 +++---------- backend/src/utils/misc.ts | 31 +++++++++++++ 3 files changed, 100 insertions(+), 24 deletions(-) diff --git a/backend/__tests__/utils/misc.spec.ts b/backend/__tests__/utils/misc.spec.ts index 299398d4b..d43988d10 100644 --- a/backend/__tests__/utils/misc.spec.ts +++ b/backend/__tests__/utils/misc.spec.ts @@ -37,4 +37,66 @@ describe("Misc Utils", () => { }); }); }); + + it("tensComplement", () => { + const testCases = [ + { + input: 123, + expected: 877, + }, + { + input: 877, + expected: 123, + }, + { + input: 0, + expected: 0, + }, + { + input: 86423, + expected: 13577, + }, + { + input: 10998739999, + expected: 89001260001, + }, + ]; + + _.each(testCases, ({ input, expected }) => { + expect(misc.tensComplement(input)).toBe(expected); + }); + }); + + it("kogascore", () => { + const testCases = [ + { + wpm: 214.8, + acc: 93.04, + timestamp: 1653586489000, + expectedScore: 1214800930436711, + }, + { + wpm: 214.8, + acc: 93.04, + timestamp: 1653601763000, + expectedScore: 1214800930421437, + }, + { + wpm: 199.37, + acc: 97.69, + timestamp: 1653588809000, + expectedScore: 1199370976934391, + }, + { + wpm: 196.2, + acc: 96.07, + timestamp: 1653591901000, + expectedScore: 1196200960731299, + }, + ]; + + _.each(testCases, ({ wpm, acc, timestamp, expectedScore }) => { + expect(misc.kogascore(wpm, acc, timestamp)).toBe(expectedScore); + }); + }); }); diff --git a/backend/src/utils/daily-leaderboards.ts b/backend/src/utils/daily-leaderboards.ts index 0cacd6466..1e16dc23c 100644 --- a/backend/src/utils/daily-leaderboards.ts +++ b/backend/src/utils/daily-leaderboards.ts @@ -1,7 +1,7 @@ import _ from "lodash"; import LRUCache from "lru-cache"; import * as RedisClient from "../init/redis"; -import { getCurrentDayTimestamp, matchesAPattern } from "./misc"; +import { getCurrentDayTimestamp, matchesAPattern, kogascore } from "./misc"; interface DailyLeaderboardEntry { uid: string; @@ -19,21 +19,6 @@ const dailyLeaderboardNamespace = "monkeytypes:dailyleaderboard"; const scoresNamespace = `${dailyLeaderboardNamespace}:scores`; const resultsNamespace = `${dailyLeaderboardNamespace}:results`; -function compareDailyLeaderboardEntries( - a: DailyLeaderboardEntry, - b: DailyLeaderboardEntry -): number { - if (a.wpm !== b.wpm) { - return b.wpm - a.wpm; - } - - if (a.acc !== b.acc) { - return b.acc - a.acc; - } - - return a.timestamp - b.timestamp; -} - export class DailyLeaderboard { private leaderboardResultsKeyName: string; private leaderboardScoresKeyName: string; @@ -85,6 +70,8 @@ export class DailyLeaderboard { (currentDayTimestamp + leaderboardExpirationDurationInMilliseconds) / 1000 ); + const resultScore = kogascore(entry.wpm, entry.acc, entry.timestamp); + // @ts-ignore const rank = await connection.addResult( 2, @@ -93,7 +80,7 @@ export class DailyLeaderboard { maxResults, leaderboardExpirationTimeInSeconds, entry.uid, - entry.wpm, + resultScore, JSON.stringify(entry) ); @@ -126,13 +113,9 @@ export class DailyLeaderboard { maxRank ); - const normalizedResults: DailyLeaderboardEntry[] = results - .map((result) => JSON.parse(result)) - .sort(compareDailyLeaderboardEntries); - - const resultsWithRanks: DailyLeaderboardEntry[] = normalizedResults.map( - (result, index) => ({ - ...result, + const resultsWithRanks: DailyLeaderboardEntry[] = results.map( + (resultJSON, index) => ({ + ...JSON.parse(resultJSON), rank: minRank + index + 1, }) ); diff --git a/backend/src/utils/misc.ts b/backend/src/utils/misc.ts index 4c9c2583f..a0ee2604f 100644 --- a/backend/src/utils/misc.ts +++ b/backend/src/utils/misc.ts @@ -90,3 +90,34 @@ export function matchesAPattern(text: string, pattern: string): boolean { const regex = new RegExp(`^${pattern}$`); return regex.test(text); } + +export function tensComplement(num: number): number { + if (num === 0) { + return 0; + } + + let i = 0; + let temp = num; + + while (temp !== 0) { + ++i; + temp = Math.floor(temp / 10); + } + + return Math.pow(10, i) - num; +} + +export function kogascore(wpm: number, acc: number, timestamp: number): number { + const normalizedWpm = Math.floor(wpm * 100); + const normalizedAcc = Math.floor(acc * 100); + + const firstPart = (100000 + normalizedWpm) * 100000; + const secondPart = (firstPart + normalizedAcc) * 100000; + + const currentDayTimeMilliseconds = timestamp - (timestamp % 86400000); + const todaySeconds = Math.floor( + (timestamp - currentDayTimeMilliseconds) / 1000 + ); + + return secondPart + tensComplement(todaySeconds); +}