monkeytype/src/js/db.js

503 lines
11 KiB
JavaScript

import { loadTags } from "./result-filters";
import * as AccountButton from "./account-button";
import * as CloudFunctions from "./cloud-functions";
import * as Notifications from "./notifications";
const db = firebase.firestore();
db.settings({ experimentalForceLongPolling: true });
let dbSnapshot = null;
export function updateName(uid, name) {
db.collection(`users`).doc(uid).set({ name: name }, { merge: true });
}
export function getSnapshot() {
return dbSnapshot;
}
export function setSnapshot(newSnapshot) {
delete newSnapshot.banned;
delete newSnapshot.verified;
dbSnapshot = newSnapshot;
}
export async function initSnapshot() {
let user = firebase.auth().currentUser;
if (user == null) return false;
let snap = {
results: undefined,
personalBests: {},
name: undefined,
tags: [],
favouriteThemes: [],
refactored: false,
banned: undefined,
verified: undefined,
emailVerified: undefined,
lbMemory: {
time15: {
global: null,
daily: null,
},
time60: {
global: null,
daily: null,
},
},
globalStats: {
time: 0,
started: 0,
completed: 0,
},
};
try {
await db
.collection(`users/${user.uid}/tags/`)
.get()
.then((data) => {
data.docs.forEach((doc) => {
let tag = doc.data();
tag.id = doc.id;
if (tag.personalBests === undefined) {
tag.personalBests = {};
}
snap.tags.push(tag);
});
snap.tags = snap.tags.sort((a, b) => {
if (a.name > b.name) {
return 1;
} else if (a.name < b.name) {
return -1;
} else {
return 0;
}
});
})
.catch((e) => {
throw e;
});
await db
.collection("users")
.doc(user.uid)
.get()
.then((res) => {
let data = res.data();
if (data === undefined) return;
if (data.personalBests !== undefined) {
snap.personalBests = data.personalBests;
}
snap.name = data.name;
snap.discordId = data.discordId;
snap.pairingCode =
data.discordPairingCode == null ? undefined : data.discordPairingCode;
snap.config = data.config;
snap.favouriteThemes =
data.favouriteThemes === undefined ? [] : data.favouriteThemes;
snap.refactored = data.refactored === true ? true : false;
snap.globalStats = {
time: data.timeTyping,
started: data.startedTests,
completed: data.completedTests,
};
snap.banned = data.banned;
snap.verified = data.verified;
snap.emailVerified = user.emailVerified;
try {
if (data.lbMemory.time15 !== undefined) {
snap.lbMemory.time15 = data.lbMemory.time15;
}
if (data.lbMemory.time60 !== undefined) {
snap.lbMemory.time60 = data.lbMemory.time60;
}
} catch {}
})
.catch((e) => {
throw e;
});
dbSnapshot = snap;
} catch (e) {
console.error(e);
}
loadTags(dbSnapshot.tags);
return dbSnapshot;
}
export async function getUserResults() {
let user = firebase.auth().currentUser;
if (user == null) return false;
if (dbSnapshot === null) return false;
if (dbSnapshot.results !== undefined) {
return true;
} else {
try {
return await db
.collection(`users/${user.uid}/results/`)
.orderBy("timestamp", "desc")
.limit(1000)
.get()
.then((data) => {
dbSnapshot.results = [];
data.docs.forEach((doc) => {
let result = doc.data();
result.id = doc.id;
if (result.bailedOut === undefined) result.bailedOut = false;
if (result.blindMode === undefined) result.blindMode = false;
if (result.difficulty === undefined) result.difficulty = "normal";
if (result.funbox === undefined) result.funbox = "none";
if (result.language === undefined) result.language = "english";
if (result.numbers === undefined) result.numbers = false;
if (result.punctuation === undefined) result.punctuation = false;
dbSnapshot.results.push(result);
});
return true;
})
.catch((e) => {
throw e;
});
} catch (e) {
console.error(e);
return false;
}
}
}
export async function getUserHighestWpm(
mode,
mode2,
punctuation,
language,
difficulty
) {
function cont() {
let topWpm = 0;
dbSnapshot.results.forEach((result) => {
if (
result.mode == mode &&
result.mode2 == mode2 &&
result.punctuation == punctuation &&
result.language == language &&
result.difficulty == difficulty
) {
if (result.wpm > topWpm) {
topWpm = result.wpm;
}
}
});
return topWpm;
}
let retval;
if (dbSnapshot == null || dbSnapshot.results === undefined) {
retval = 0;
} else {
retval = cont();
}
return retval;
}
export async function getUserAverageWpm10(
mode,
mode2,
punctuation,
language,
difficulty
) {
function cont() {
let wpmSum = 0;
let count = 0;
// You have to use every so you can break out of the loop
dbSnapshot.results.every((result) => {
if (
result.mode == mode &&
result.mode2 == mode2 &&
result.punctuation == punctuation &&
result.language == language &&
result.difficulty == difficulty
) {
wpmSum += result.wpm;
count++;
if (count >= 10) {
return false;
}
}
return true;
});
return Math.round(wpmSum / count);
}
let retval = 0;
if (dbSnapshot == null) return retval;
var dbSnapshotValid = await getUserResults();
if (dbSnapshotValid === false) {
return retval;
}
retval = cont();
return retval;
}
export async function getLocalPB(
mode,
mode2,
punctuation,
language,
difficulty
) {
function cont() {
let ret = 0;
try {
dbSnapshot.personalBests[mode][mode2].forEach((pb) => {
if (
pb.punctuation == punctuation &&
pb.difficulty == difficulty &&
pb.language == language
) {
ret = pb.wpm;
}
});
return ret;
} catch (e) {
return ret;
}
}
let retval;
if (dbSnapshot == null) {
retval = 0;
} else {
retval = cont();
}
return retval;
}
export async function saveLocalPB(
mode,
mode2,
punctuation,
language,
difficulty,
wpm,
acc,
raw,
consistency
) {
if (mode == "quote") return;
function cont() {
try {
let found = false;
if (dbSnapshot.personalBests[mode][mode2] === undefined) {
dbSnapshot.personalBests[mode][mode2] = [];
}
dbSnapshot.personalBests[mode][mode2].forEach((pb) => {
if (
pb.punctuation == punctuation &&
pb.difficulty == difficulty &&
pb.language == language
) {
found = true;
pb.wpm = wpm;
pb.acc = acc;
pb.raw = raw;
pb.timestamp = Date.now();
pb.consistency = consistency;
}
});
if (!found) {
//nothing found
dbSnapshot.personalBests[mode][mode2].push({
language: language,
difficulty: difficulty,
punctuation: punctuation,
wpm: wpm,
acc: acc,
raw: raw,
timestamp: Date.now(),
consistency: consistency,
});
}
} catch (e) {
//that mode or mode2 is not found
dbSnapshot.personalBests[mode] = {};
dbSnapshot.personalBests[mode][mode2] = [
{
language: language,
difficulty: difficulty,
punctuation: punctuation,
wpm: wpm,
acc: acc,
raw: raw,
timestamp: Date.now(),
consistency: consistency,
},
];
}
}
if (dbSnapshot != null) {
cont();
}
}
export async function getLocalTagPB(
tagId,
mode,
mode2,
punctuation,
language,
difficulty
) {
function cont() {
let ret = 0;
let filteredtag = dbSnapshot.tags.filter((t) => t.id === tagId)[0];
try {
filteredtag.personalBests[mode][mode2].forEach((pb) => {
if (
pb.punctuation == punctuation &&
pb.difficulty == difficulty &&
pb.language == language
) {
ret = pb.wpm;
}
});
return ret;
} catch (e) {
return ret;
}
}
let retval;
if (dbSnapshot == null) {
retval = 0;
} else {
retval = cont();
}
return retval;
}
export async function saveLocalTagPB(
tagId,
mode,
mode2,
punctuation,
language,
difficulty,
wpm,
acc,
raw,
consistency
) {
if (mode == "quote") return;
function cont() {
let filteredtag = dbSnapshot.tags.filter((t) => t.id === tagId)[0];
try {
let found = false;
if (filteredtag.personalBests[mode][mode2] === undefined) {
filteredtag.personalBests[mode][mode2] = [];
}
filteredtag.personalBests[mode][mode2].forEach((pb) => {
if (
pb.punctuation == punctuation &&
pb.difficulty == difficulty &&
pb.language == language
) {
found = true;
pb.wpm = wpm;
pb.acc = acc;
pb.raw = raw;
pb.timestamp = Date.now();
pb.consistency = consistency;
}
});
if (!found) {
//nothing found
filteredtag.personalBests[mode][mode2].push({
language: language,
difficulty: difficulty,
punctuation: punctuation,
wpm: wpm,
acc: acc,
raw: raw,
timestamp: Date.now(),
consistency: consistency,
});
}
} catch (e) {
//that mode or mode2 is not found
filteredtag.personalBests[mode] = {};
filteredtag.personalBests[mode][mode2] = [
{
language: language,
difficulty: difficulty,
punctuation: punctuation,
wpm: wpm,
acc: acc,
raw: raw,
timestamp: Date.now(),
consistency: consistency,
},
];
}
}
if (dbSnapshot != null) {
cont();
}
}
export function updateLbMemory(mode, mode2, type, value) {
getSnapshot().lbMemory[mode + mode2][type] = value;
}
export async function saveConfig(config) {
if (firebase.auth().currentUser !== null) {
AccountButton.loading(true);
CloudFunctions.saveConfig({
uid: firebase.auth().currentUser.uid,
obj: config,
}).then((d) => {
AccountButton.loading(false);
if (d.data.returnCode !== 1) {
Notifications.add(`Error saving config to DB! ${d.data.message}`, 4000);
}
return;
});
}
}
// export async function DB.getLocalTagPB(tagId) {
// function cont() {
// let ret = 0;
// try {
// ret = dbSnapshot.tags.filter((t) => t.id === tagId)[0].pb;
// if (ret == undefined) {
// ret = 0;
// }
// return ret;
// } catch (e) {
// return ret;
// }
// }
// let retval;
// if (dbSnapshot != null) {
// retval = cont();
// }
// return retval;
// }
// export async functio(tagId, wpm) {
// function cont() {
// dbSnapshot.tags.forEach((tag) => {
// if (tag.id === tagId) {
// tag.pb = wpm;
// }
// });
// }
// if (dbSnapshot != null) {
// cont();
// }
// }