mirror of
https://github.com/monkeytypegame/monkeytype.git
synced 2025-03-12 15:08:45 +08:00
Migrate utils pb to ts (#2631)
* Migrate utils pb to ts * Fix * Move to separate function
This commit is contained in:
parent
41b8148c4a
commit
1df8388e2d
3 changed files with 150 additions and 203 deletions
|
@ -167,19 +167,7 @@ class UsersDAO {
|
|||
}
|
||||
|
||||
static async checkIfPb(uid, user, result) {
|
||||
const {
|
||||
mode,
|
||||
mode2,
|
||||
acc,
|
||||
consistency,
|
||||
difficulty,
|
||||
lazyMode,
|
||||
language,
|
||||
punctuation,
|
||||
rawWpm,
|
||||
wpm,
|
||||
funbox,
|
||||
} = result;
|
||||
const { mode, funbox } = result;
|
||||
|
||||
if (funbox !== "none" && funbox !== "plus_one" && funbox !== "plus_two") {
|
||||
return false;
|
||||
|
@ -192,20 +180,7 @@ class UsersDAO {
|
|||
let lbpb = user.lbPersonalBests;
|
||||
if (!lbpb) lbpb = {};
|
||||
|
||||
let pb = checkAndUpdatePb(
|
||||
user.personalBests,
|
||||
lbpb,
|
||||
mode,
|
||||
mode2,
|
||||
acc,
|
||||
consistency,
|
||||
difficulty,
|
||||
lazyMode,
|
||||
language,
|
||||
punctuation,
|
||||
rawWpm,
|
||||
wpm
|
||||
);
|
||||
let pb = checkAndUpdatePb(user.personalBests, lbpb, result);
|
||||
|
||||
if (pb.isPb) {
|
||||
await db
|
||||
|
@ -227,20 +202,7 @@ class UsersDAO {
|
|||
return [];
|
||||
}
|
||||
|
||||
const {
|
||||
mode,
|
||||
mode2,
|
||||
acc,
|
||||
consistency,
|
||||
difficulty,
|
||||
lazyMode,
|
||||
language,
|
||||
punctuation,
|
||||
rawWpm,
|
||||
wpm,
|
||||
tags,
|
||||
funbox,
|
||||
} = result;
|
||||
const { mode, tags, funbox } = result;
|
||||
|
||||
if (funbox !== "none" && funbox !== "plus_one" && funbox !== "plus_two") {
|
||||
return [];
|
||||
|
@ -262,20 +224,7 @@ class UsersDAO {
|
|||
let ret = [];
|
||||
|
||||
tagsToCheck.forEach(async (tag) => {
|
||||
let tagpb = checkAndUpdatePb(
|
||||
tag.personalBests,
|
||||
undefined,
|
||||
mode,
|
||||
mode2,
|
||||
acc,
|
||||
consistency,
|
||||
difficulty,
|
||||
lazyMode,
|
||||
language,
|
||||
punctuation,
|
||||
rawWpm,
|
||||
wpm
|
||||
);
|
||||
let tagpb = checkAndUpdatePb(tag.personalBests, undefined, result);
|
||||
if (tagpb.isPb) {
|
||||
ret.push(tag._id);
|
||||
await db
|
||||
|
|
|
@ -1,148 +0,0 @@
|
|||
/*
|
||||
|
||||
|
||||
obj structure
|
||||
|
||||
time: {
|
||||
10: [ - this is a list because there can be
|
||||
different personal bests for different difficulties, languages and punctuation
|
||||
{
|
||||
acc,
|
||||
consistency,
|
||||
difficulty,
|
||||
language,
|
||||
punctuation,
|
||||
raw,
|
||||
timestamp,
|
||||
wpm
|
||||
}
|
||||
]
|
||||
},
|
||||
words: {
|
||||
10: [
|
||||
{}
|
||||
]
|
||||
},
|
||||
zen: {
|
||||
zen: [
|
||||
{}
|
||||
]
|
||||
},
|
||||
custom: {
|
||||
custom: {
|
||||
[]
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
*/
|
||||
|
||||
export function checkAndUpdatePb(
|
||||
obj,
|
||||
lbObj,
|
||||
mode,
|
||||
mode2,
|
||||
acc,
|
||||
consistency,
|
||||
difficulty,
|
||||
lazyMode = false,
|
||||
language,
|
||||
punctuation,
|
||||
raw,
|
||||
wpm
|
||||
) {
|
||||
//verify structure first
|
||||
if (obj === undefined) obj = {};
|
||||
if (obj[mode] === undefined) obj[mode] = {};
|
||||
if (obj[mode][mode2] === undefined) obj[mode][mode2] = [];
|
||||
|
||||
let isPb = false;
|
||||
let found = false;
|
||||
//find a pb
|
||||
obj[mode][mode2].forEach((pb) => {
|
||||
//check if we should compare first
|
||||
if (
|
||||
(pb.lazyMode === lazyMode ||
|
||||
(pb.lazyMode === undefined && lazyMode === false)) &&
|
||||
pb.difficulty === difficulty &&
|
||||
pb.language === language &&
|
||||
pb.punctuation === punctuation
|
||||
) {
|
||||
found = true;
|
||||
//compare
|
||||
if (pb.wpm < wpm) {
|
||||
//update
|
||||
isPb = true;
|
||||
pb.acc = acc;
|
||||
pb.consistency = consistency;
|
||||
pb.difficulty = difficulty;
|
||||
pb.language = language;
|
||||
pb.punctuation = punctuation;
|
||||
pb.lazyMode = lazyMode;
|
||||
pb.raw = raw;
|
||||
pb.wpm = wpm;
|
||||
pb.timestamp = Date.now();
|
||||
}
|
||||
}
|
||||
});
|
||||
//if not found push a new one
|
||||
if (!found) {
|
||||
isPb = true;
|
||||
obj[mode][mode2].push({
|
||||
acc,
|
||||
consistency,
|
||||
difficulty,
|
||||
lazyMode,
|
||||
language,
|
||||
punctuation,
|
||||
raw,
|
||||
wpm,
|
||||
timestamp: Date.now(),
|
||||
});
|
||||
}
|
||||
|
||||
if (
|
||||
lbObj &&
|
||||
mode === "time" &&
|
||||
(mode2 == "15" || mode2 == "60") &&
|
||||
!lazyMode
|
||||
) {
|
||||
//updating lbpersonalbests object
|
||||
//verify structure first
|
||||
if (lbObj[mode] === undefined) lbObj[mode] = {};
|
||||
if (lbObj[mode][mode2] === undefined || Array.isArray(lbObj[mode][mode2]))
|
||||
lbObj[mode][mode2] = {};
|
||||
|
||||
let bestForEveryLanguage = {};
|
||||
if (obj?.[mode]?.[mode2]) {
|
||||
obj[mode][mode2].forEach((pb) => {
|
||||
if (!bestForEveryLanguage[pb.language]) {
|
||||
bestForEveryLanguage[pb.language] = pb;
|
||||
} else {
|
||||
if (bestForEveryLanguage[pb.language].wpm < pb.wpm) {
|
||||
bestForEveryLanguage[pb.language] = pb;
|
||||
}
|
||||
}
|
||||
});
|
||||
Object.keys(bestForEveryLanguage).forEach((key) => {
|
||||
if (lbObj[mode][mode2][key] === undefined) {
|
||||
lbObj[mode][mode2][key] = bestForEveryLanguage[key];
|
||||
} else {
|
||||
if (lbObj[mode][mode2][key].wpm < bestForEveryLanguage[key].wpm) {
|
||||
lbObj[mode][mode2][key] = bestForEveryLanguage[key];
|
||||
}
|
||||
}
|
||||
});
|
||||
bestForEveryLanguage = {};
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
isPb,
|
||||
obj,
|
||||
lbObj,
|
||||
};
|
||||
}
|
146
backend/utils/pb.ts
Normal file
146
backend/utils/pb.ts
Normal file
|
@ -0,0 +1,146 @@
|
|||
import _ from "lodash";
|
||||
|
||||
interface CheckAndUpdatePbResult {
|
||||
isPb: boolean;
|
||||
obj: object;
|
||||
lbObj: object;
|
||||
}
|
||||
|
||||
type Result = MonkeyTypes.Result<MonkeyTypes.Mode>;
|
||||
|
||||
export function checkAndUpdatePb(
|
||||
userPersonalBests: MonkeyTypes.User["personalBests"],
|
||||
lbPersonalBests: MonkeyTypes.User["lbPersonalBests"],
|
||||
result: Result
|
||||
): CheckAndUpdatePbResult {
|
||||
const { mode, mode2 } = result;
|
||||
|
||||
const userPb = userPersonalBests ?? {};
|
||||
userPb[mode] = userPb[mode] ?? {};
|
||||
userPb[mode][mode2] = userPb[mode][mode2] ?? [];
|
||||
|
||||
const personalBestMatch: MonkeyTypes.PersonalBest = userPb[mode][mode2].find(
|
||||
(pb: MonkeyTypes.PersonalBest) => {
|
||||
return matchesPersonalBest(result, pb);
|
||||
}
|
||||
);
|
||||
|
||||
let isPb = true;
|
||||
|
||||
if (personalBestMatch) {
|
||||
const didUpdate = updatePersonalBest(personalBestMatch, result);
|
||||
isPb = didUpdate;
|
||||
} else {
|
||||
userPb[mode][mode2].push(buildPersonalBest(result));
|
||||
}
|
||||
|
||||
updateLeaderboardPersonalBests(userPb, lbPersonalBests, result);
|
||||
|
||||
return {
|
||||
isPb,
|
||||
obj: userPb,
|
||||
lbObj: lbPersonalBests,
|
||||
};
|
||||
}
|
||||
|
||||
function matchesPersonalBest(
|
||||
result: Result,
|
||||
personalBest: MonkeyTypes.PersonalBest
|
||||
): boolean {
|
||||
const sameLazyMode =
|
||||
result.lazyMode === personalBest.lazyMode ||
|
||||
(!result.lazyMode && !personalBest.lazyMode);
|
||||
const samePunctuation = result.punctuation === personalBest.punctuation;
|
||||
const sameDifficulty = result.difficulty === personalBest.difficulty;
|
||||
const sameLanguage = result.language === personalBest.language;
|
||||
|
||||
return sameLazyMode && samePunctuation && sameDifficulty && sameLanguage;
|
||||
}
|
||||
|
||||
function updatePersonalBest(
|
||||
personalBest: MonkeyTypes.PersonalBest,
|
||||
result: Result
|
||||
): boolean {
|
||||
if (personalBest.wpm > result.wpm) {
|
||||
return false;
|
||||
}
|
||||
|
||||
personalBest.acc = result.acc;
|
||||
personalBest.consistency = result.consistency;
|
||||
personalBest.difficulty = result.difficulty;
|
||||
personalBest.language = result.language;
|
||||
personalBest.punctuation = result.punctuation;
|
||||
personalBest.lazyMode = result.lazyMode;
|
||||
personalBest.raw = result.rawWpm;
|
||||
personalBest.wpm = result.wpm;
|
||||
personalBest.timestamp = Date.now();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
function buildPersonalBest(result: Result): MonkeyTypes.PersonalBest {
|
||||
return {
|
||||
acc: result.acc,
|
||||
consistency: result.consistency,
|
||||
difficulty: result.difficulty,
|
||||
lazyMode: result.lazyMode,
|
||||
language: result.language,
|
||||
punctuation: result.punctuation,
|
||||
raw: result.rawWpm,
|
||||
wpm: result.wpm,
|
||||
timestamp: Date.now(),
|
||||
};
|
||||
}
|
||||
|
||||
function updateLeaderboardPersonalBests(
|
||||
userPersonalBests: MonkeyTypes.User["personalBests"],
|
||||
lbPersonalBests: MonkeyTypes.User["lbPersonalBests"],
|
||||
result: Result
|
||||
): void {
|
||||
if (!shouldUpdateLeaderboardPersonalBests(lbPersonalBests, result)) {
|
||||
return;
|
||||
}
|
||||
|
||||
const { mode, mode2 } = result;
|
||||
|
||||
lbPersonalBests[mode] = lbPersonalBests[mode] ?? {};
|
||||
const lbMode2 = lbPersonalBests[mode][mode2];
|
||||
if (!lbMode2 || Array.isArray(lbMode2)) {
|
||||
lbPersonalBests[mode][mode2] = {};
|
||||
}
|
||||
|
||||
const bestForEveryLanguage = {};
|
||||
|
||||
userPersonalBests[mode][mode2].forEach((pb: MonkeyTypes.PersonalBest) => {
|
||||
const language = pb.language;
|
||||
if (
|
||||
!bestForEveryLanguage[language] ||
|
||||
bestForEveryLanguage[language].wpm < pb.wpm
|
||||
) {
|
||||
bestForEveryLanguage[language] = pb;
|
||||
}
|
||||
});
|
||||
|
||||
_.each(
|
||||
bestForEveryLanguage,
|
||||
(pb: MonkeyTypes.PersonalBest, language: string) => {
|
||||
const languageDoesNotExist = !lbPersonalBests[mode][mode2][language];
|
||||
|
||||
if (
|
||||
languageDoesNotExist ||
|
||||
lbPersonalBests[mode][mode2][language].wpm < pb.wpm
|
||||
) {
|
||||
lbPersonalBests[mode][mode2][language] = pb;
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
function shouldUpdateLeaderboardPersonalBests(
|
||||
lbPersonalBests: MonkeyTypes.User["lbPersonalBests"],
|
||||
result: Result
|
||||
): boolean {
|
||||
const isValidTimeMode =
|
||||
result.mode === "time" && (result.mode2 === "15" || result.mode2 === "60");
|
||||
return lbPersonalBests && isValidTimeMode && !result.lazyMode;
|
||||
}
|
Loading…
Reference in a new issue