Migrate utils pb to ts ()

* Migrate utils pb to ts

* Fix

* Move to separate function
This commit is contained in:
Bruce Berrios 2022-03-04 17:24:10 -05:00 committed by GitHub
parent 41b8148c4a
commit 1df8388e2d
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 150 additions and 203 deletions
backend

View file

@ -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

View file

@ -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
View 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;
}