mirror of
https://github.com/monkeytypegame/monkeytype.git
synced 2025-11-18 14:55:34 +08:00
Use better score metric (#3030)
This commit is contained in:
parent
5d45898893
commit
cd767bff1c
3 changed files with 100 additions and 24 deletions
|
|
@ -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);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
})
|
||||
);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue