diff --git a/.github/ISSUE_TEMPLATE/bug_report.yaml b/.github/ISSUE_TEMPLATE/bug_report.yaml
index 7c82d19d5..044d0eeba 100644
--- a/.github/ISSUE_TEMPLATE/bug_report.yaml
+++ b/.github/ISSUE_TEMPLATE/bug_report.yaml
@@ -2,7 +2,6 @@ name: Bug report
description: Create a report to help us improve
labels: [bug]
body:
-
- type: markdown
attributes:
value: |
@@ -10,8 +9,7 @@ body:
```
Thanks for taking the time to fill out this bug! If you need real-time help, join us on Discord: discord.gg/monkeytype
```
-
-
+
- type: checkboxes
attributes:
label: Did you clear cache before opening an issue?
@@ -19,7 +17,7 @@ body:
options:
- label: I have cleared my cache
required: true
-
+
- type: checkboxes
attributes:
label: Is there an existing issue for this?
@@ -27,7 +25,7 @@ body:
options:
- label: I have searched the existing issues
required: true
-
+
- type: markdown
attributes:
value: |
@@ -35,35 +33,35 @@ body:
```
Below fields are very important to quickly track down the issue, so please take the time to carefully check when the issue happens and when it does not.
```
-
+
- type: dropdown
attributes:
label: Does the issue happen when logged in?
options: ["Yes", "No", "N/A"]
validations:
required: true
-
+
- type: dropdown
attributes:
label: Does the issue happen when logged out?
options: ["Yes", "No"]
validations:
required: true
-
+
- type: dropdown
attributes:
label: Does the issue happen in incognito mode when logged in?
options: ["Yes", "No", "N/A"]
validations:
required: true
-
+
- type: dropdown
attributes:
label: Does the issue happen in incognito mode when logged out?
options: ["Yes", "No"]
validations:
required: true
-
+
- type: textarea
attributes:
label: Account information
@@ -128,4 +126,3 @@ body:
Tip: You can attach images or log files by clicking this area to highlight it and then dragging files in.
validations:
required: false
-
diff --git a/.prettierrc b/.prettierrc
index 9ecd5a034..61dfe5298 100644
--- a/.prettierrc
+++ b/.prettierrc
@@ -1,5 +1,14 @@
{
"tabWidth": 2,
"useTabs": false,
- "htmlWhitespaceSensitivity": "ignore"
+ "htmlWhitespaceSensitivity": "ignore",
+ "endOfLine": "lf",
+ "overrides": [
+ {
+ "files": ["*.ts"],
+ "options": {
+ "parser": "typescript"
+ }
+ }
+ ]
}
diff --git a/frontend/src/scripts/account/all-time-stats.js b/frontend/src/scripts/account/all-time-stats.ts
similarity index 64%
rename from frontend/src/scripts/account/all-time-stats.js
rename to frontend/src/scripts/account/all-time-stats.ts
index 9d222795f..cce9700c1 100644
--- a/frontend/src/scripts/account/all-time-stats.js
+++ b/frontend/src/scripts/account/all-time-stats.ts
@@ -1,33 +1,37 @@
import * as DB from "../db";
import * as Misc from "../misc";
-export function clear() {
+export function clear(): void {
$(".pageAccount .globalTimeTyping .val").text(`-`);
$(".pageAccount .globalTestsStarted .val").text(`-`);
$(".pageAccount .globalTestsCompleted .val").text(`-`);
}
-export function update() {
- if (DB.getSnapshot().globalStats.time != undefined) {
+export function update(): void {
+ const snapshot = DB.getSnapshot();
+
+ if (snapshot.globalStats !== undefined) {
// let th = Math.floor(DB.getSnapshot().globalStats.time / 3600);
// let tm = Math.floor((DB.getSnapshot().globalStats.time % 3600) / 60);
// let ts = Math.floor((DB.getSnapshot().globalStats.time % 3600) % 60);
$(".pageAccount .globalTimeTyping .val").text(
Misc.secondsToString(
- Math.round(DB.getSnapshot().globalStats.time),
+ Math.round(snapshot.globalStats.time as number),
true,
true
)
);
}
- if (DB.getSnapshot().globalStats.started != undefined) {
+
+ if (snapshot.globalStats !== undefined) {
$(".pageAccount .globalTestsStarted .val").text(
- DB.getSnapshot().globalStats.started
+ snapshot.globalStats.started as number
);
}
- if (DB.getSnapshot().globalStats.completed != undefined) {
+
+ if (snapshot.globalStats !== undefined) {
$(".pageAccount .globalTestsCompleted .val").text(
- DB.getSnapshot().globalStats.completed
+ snapshot.globalStats.completed as number
);
}
}
diff --git a/frontend/src/scripts/account/mini-result-chart.js b/frontend/src/scripts/account/mini-result-chart.ts
similarity index 71%
rename from frontend/src/scripts/account/mini-result-chart.js
rename to frontend/src/scripts/account/mini-result-chart.ts
index 4168eccf6..8f33dfb5c 100644
--- a/frontend/src/scripts/account/mini-result-chart.js
+++ b/frontend/src/scripts/account/mini-result-chart.ts
@@ -1,23 +1,23 @@
import * as ChartController from "../controllers/chart-controller";
import Config from "../config";
-export function updatePosition(x, y) {
+export function updatePosition(x: number, y: number): void {
$(".pageAccount .miniResultChartWrapper").css({ top: y, left: x });
}
-export function show() {
+export function show(): void {
$(".pageAccount .miniResultChartWrapper").stop(true, true).fadeIn(125);
$(".pageAccount .miniResultChartBg").stop(true, true).fadeIn(125);
}
-function hide() {
+function hide(): void {
$(".pageAccount .miniResultChartWrapper").stop(true, true).fadeOut(125);
$(".pageAccount .miniResultChartBg").stop(true, true).fadeOut(125);
}
-export function updateData(data) {
+export function updateData(data: MonkeyTypes.ChartData): void {
// let data = filteredResults[filteredId].chartData;
- let labels = [];
+ const labels = [];
for (let i = 1; i <= data.wpm.length; i++) {
labels.push(i.toString());
}
@@ -28,22 +28,22 @@ export function updateData(data) {
ChartController.miniResult.updateColors();
- let maxChartVal = Math.max(...[Math.max(...data.wpm), Math.max(...data.raw)]);
- let minChartVal = Math.min(...[Math.min(...data.wpm), Math.min(...data.raw)]);
- ChartController.miniResult.options.scales.yAxes[0].ticks.max = Math.round(
- maxChartVal
+ const maxChartVal = Math.max(
+ ...[Math.max(...data.wpm), Math.max(...data.raw)]
);
- ChartController.miniResult.options.scales.yAxes[1].ticks.max = Math.round(
- maxChartVal
+ const minChartVal = Math.min(
+ ...[Math.min(...data.wpm), Math.min(...data.raw)]
);
+ ChartController.miniResult.options.scales.yAxes[0].ticks.max =
+ Math.round(maxChartVal);
+ ChartController.miniResult.options.scales.yAxes[1].ticks.max =
+ Math.round(maxChartVal);
if (!Config.startGraphsAtZero) {
- ChartController.miniResult.options.scales.yAxes[0].ticks.min = Math.round(
- minChartVal
- );
- ChartController.miniResult.options.scales.yAxes[1].ticks.min = Math.round(
- minChartVal
- );
+ ChartController.miniResult.options.scales.yAxes[0].ticks.min =
+ Math.round(minChartVal);
+ ChartController.miniResult.options.scales.yAxes[1].ticks.min =
+ Math.round(minChartVal);
} else {
ChartController.miniResult.options.scales.yAxes[0].ticks.min = 0;
ChartController.miniResult.options.scales.yAxes[1].ticks.min = 0;
@@ -52,6 +52,6 @@ export function updateData(data) {
ChartController.miniResult.update({ duration: 0 });
}
-$(document).on("click", ".pageAccount .miniResultChartBg", (event) => {
+$(document).on("click", ".pageAccount .miniResultChartBg", () => {
hide();
});
diff --git a/frontend/src/scripts/account/pb-tables.js b/frontend/src/scripts/account/pb-tables.ts
similarity index 98%
rename from frontend/src/scripts/account/pb-tables.js
rename to frontend/src/scripts/account/pb-tables.ts
index 031f45877..3669c7c81 100644
--- a/frontend/src/scripts/account/pb-tables.js
+++ b/frontend/src/scripts/account/pb-tables.ts
@@ -2,7 +2,7 @@ import * as DB from "../db";
import Config from "../config";
import * as Misc from "../misc";
-export function update() {
+export function update(): void {
$(".pageAccount .timePbTable tbody").html(`
15 |
@@ -75,10 +75,11 @@ export function update() {
}
const pb = DB.getSnapshot().personalBests;
+ if (pb === undefined) return;
let pbData;
let text;
let dateText = `-
-`;
- let multiplier = Config.alwaysShowCPM ? 5 : 1;
+ const multiplier = Config.alwaysShowCPM ? 5 : 1;
text = "";
try {
diff --git a/frontend/src/scripts/account/result-filters.js b/frontend/src/scripts/account/result-filters.ts
similarity index 67%
rename from frontend/src/scripts/account/result-filters.js
rename to frontend/src/scripts/account/result-filters.ts
index 5f4129841..8f125c7b9 100644
--- a/frontend/src/scripts/account/result-filters.js
+++ b/frontend/src/scripts/account/result-filters.ts
@@ -3,7 +3,7 @@ import * as DB from "../db";
import Config from "../config";
import * as Notifications from "../elements/notifications";
-export let defaultResultFilters = {
+export const defaultResultFilters: MonkeyTypes.ResultFilters = {
difficulty: {
normal: true,
expert: true,
@@ -62,15 +62,15 @@ export let defaultResultFilters = {
export let filters = defaultResultFilters;
-function save() {
+function save(): void {
window.localStorage.setItem("resultFilters", JSON.stringify(filters));
}
-export function load() {
+export function load(): void {
// let newTags = $.cookie("activeTags");
console.log("loading filters");
try {
- let newResultFilters = window.localStorage.getItem("resultFilters");
+ const newResultFilters = window.localStorage.getItem("resultFilters");
if (
newResultFilters != undefined &&
newResultFilters !== "" &&
@@ -84,7 +84,9 @@ export function load() {
// save();
}
- let newTags = {};
+ const newTags: {
+ [tag: string]: boolean;
+ } = { none: false };
Object.keys(defaultResultFilters.tags).forEach((tag) => {
if (filters.tags[tag] !== undefined) {
@@ -104,11 +106,13 @@ export function load() {
}
}
-export function getFilters() {
+export function getFilters(): MonkeyTypes.ResultFilters {
return filters;
}
-export function getGroup(group) {
+export function getGroup(
+ group: G
+): MonkeyTypes.ResultFilters[G] {
return filters[group];
}
@@ -116,7 +120,10 @@ export function getGroup(group) {
// filters[group][filter] = value;
// }
-export function getFilter(group, filter) {
+export function getFilter(
+ group: G,
+ filter: MonkeyTypes.Filter
+): MonkeyTypes.ResultFilters[G][MonkeyTypes.Filter] {
return filters[group][filter];
}
@@ -124,30 +131,42 @@ export function getFilter(group, filter) {
// filters[group][filter] = !filters[group][filter];
// }
-export function loadTags(tags) {
+export function loadTags(tags: MonkeyTypes.Tag[]): void {
console.log("loading tags");
tags.forEach((tag) => {
defaultResultFilters.tags[tag._id] = true;
});
}
-export function reset() {
+export function reset(): void {
filters = defaultResultFilters;
save();
}
-export function updateActive() {
- let aboveChartDisplay = {};
- Object.keys(getFilters()).forEach((group) => {
+type AboveChartDisplay = MonkeyTypes.PartialRecord<
+ MonkeyTypes.Group,
+ { all: boolean; array?: string[] }
+>;
+
+export function updateActive(): void {
+ const aboveChartDisplay: AboveChartDisplay = {};
+ (Object.keys(getFilters()) as MonkeyTypes.Group[]).forEach((group) => {
aboveChartDisplay[group] = {
all: true,
array: [],
};
- Object.keys(getGroup(group)).forEach((filter) => {
+ (
+ Object.keys(getGroup(group)) as MonkeyTypes.Filter[]
+ ).forEach((filter) => {
+ const groupAboveChartDisplay = aboveChartDisplay[group];
+
+ if (groupAboveChartDisplay === undefined) return;
+
if (getFilter(group, filter)) {
- aboveChartDisplay[group].array.push(filter);
+ groupAboveChartDisplay["array"]?.push(filter);
} else {
- aboveChartDisplay[group].all = false;
+ if (groupAboveChartDisplay["all"] !== undefined)
+ groupAboveChartDisplay["all"] = false;
}
let buttonEl;
if (group === "date") {
@@ -167,7 +186,7 @@ export function updateActive() {
});
});
- function addText(group) {
+ function addText(group: MonkeyTypes.Group): string {
let ret = "";
ret += "";
if (group == "difficulty") {
@@ -200,21 +219,23 @@ export function updateActive() {
} else if (group == "funbox") {
ret += ``;
}
- if (aboveChartDisplay[group].all) {
+ if (aboveChartDisplay[group]?.all) {
ret += "all";
} else {
if (group === "tags") {
- ret += aboveChartDisplay.tags.array
- .map((id) => {
+ ret += aboveChartDisplay.tags?.array
+ ?.map((id) => {
if (id == "none") return id;
- let name = DB.getSnapshot().tags.filter((t) => t._id == id)[0];
+ const snapshot = DB.getSnapshot();
+ const name = snapshot.tags?.filter((t) => t._id == id)[0];
if (name !== undefined) {
- return DB.getSnapshot().tags.filter((t) => t._id == id)[0].name;
+ return snapshot.tags?.filter((t) => t._id == id)[0].name;
}
+ return name;
})
.join(", ");
} else {
- ret += aboveChartDisplay[group].array.join(", ").replace(/_/g, " ");
+ ret += aboveChartDisplay[group]?.array?.join(", ").replace(/_/g, " ");
}
}
ret += "
";
@@ -232,13 +253,13 @@ export function updateActive() {
chartString += ``;
//time
- if (aboveChartDisplay.mode.array.includes("time")) {
+ if (aboveChartDisplay.mode?.array?.includes("time")) {
chartString += addText("time");
chartString += ``;
}
//words
- if (aboveChartDisplay.mode.array.includes("words")) {
+ if (aboveChartDisplay.mode?.array?.includes("words")) {
chartString += addText("words");
chartString += ``;
}
@@ -271,14 +292,21 @@ export function updateActive() {
}, 0);
}
-export function toggle(group, filter) {
+export function toggle(
+ group: G,
+ filter: MonkeyTypes.Filter
+): void {
try {
if (group === "date") {
- Object.keys(getGroup("date")).forEach((date) => {
- filters["date"][date] = false;
- });
+ (Object.keys(getGroup("date")) as MonkeyTypes.Filter<"date">[]).forEach(
+ (date) => {
+ filters["date"][date] = false;
+ }
+ );
}
- filters[group][filter] = !filters[group][filter];
+ filters[group][filter] = !filters[group][
+ filter
+ ] as unknown as MonkeyTypes.ResultFilters[G][keyof MonkeyTypes.ResultFilters[G]];
save();
} catch (e) {
Notifications.add(
@@ -292,18 +320,21 @@ export function toggle(group, filter) {
}
}
-export function updateTags() {
+export function updateTags(): void {
$(
".pageAccount .content .filterButtons .buttonsAndTitle.tags .buttons"
).empty();
- if (DB.getSnapshot().tags.length > 0) {
+
+ const snapshot = DB.getSnapshot();
+
+ if (snapshot.tags?.length || 0 > 0) {
$(".pageAccount .content .filterButtons .buttonsAndTitle.tags").removeClass(
"hidden"
);
$(
".pageAccount .content .filterButtons .buttonsAndTitle.tags .buttons"
).append(`no tag
`);
- DB.getSnapshot().tags.forEach((tag) => {
+ snapshot.tags?.forEach((tag) => {
$(
".pageAccount .content .filterButtons .buttonsAndTitle.tags .buttons"
).append(`${tag.name}
`);
@@ -318,32 +349,49 @@ export function updateTags() {
$(
".pageAccount .filterButtons .buttonsAndTitle .buttons, .pageAccount .group.topFilters .buttonsAndTitle.testDate .buttons"
).click(".button", (e) => {
- const filter = $(e.target).attr("filter");
- const group = $(e.target).parents(".buttons").attr("group");
+ const group = $(e.target)
+ .parents(".buttons")
+ .attr("group") as MonkeyTypes.Group;
+ const filter = $(e.target).attr("filter") as MonkeyTypes.Filter;
if ($(e.target).hasClass("allFilters")) {
- Object.keys(getFilters()).forEach((group) => {
- Object.keys(getGroup(group)).forEach((filter) => {
+ (Object.keys(getFilters()) as MonkeyTypes.Group[]).forEach((group) => {
+ (
+ Object.keys(getGroup(group)) as MonkeyTypes.Filter[]
+ ).forEach((filter) => {
if (group === "date") {
+ // TODO figure out why "filter" is never
+ // @ts-ignore
filters[group][filter] = false;
- } else {
+ } else if (filters[group] !== undefined) {
+ // @ts-ignore
filters[group][filter] = true;
}
});
});
filters["date"]["all"] = true;
} else if ($(e.target).hasClass("noFilters")) {
- Object.keys(getFilters()).forEach((group) => {
+ (Object.keys(getFilters()) as MonkeyTypes.Group[]).forEach((group) => {
if (group !== "date") {
- Object.keys(getGroup(group)).forEach((filter) => {
+ (
+ Object.keys(getGroup(group)) as MonkeyTypes.Filter[]
+ ).forEach((filter) => {
+ // TODO figure out why "filter" is never
+ // @ts-ignore
filters[group][filter] = false;
});
}
});
} else if ($(e.target).hasClass("button")) {
if (e.shiftKey) {
- Object.keys(getGroup(group)).forEach((filter) => {
+ (
+ Object.keys(getGroup(group)) as MonkeyTypes.Filter[]
+ ).forEach((filter) => {
+ // TODO figure out why "filter" is never
+ // @ts-ignore
filters[group][filter] = false;
});
+ // TODO figure out why "filter" is never
+ // @ts-ignore
filters[group][filter] = true;
} else {
toggle(group, filter);
@@ -354,12 +402,18 @@ $(
save();
});
-$(".pageAccount .topFilters .button.allFilters").click((e) => {
- Object.keys(getFilters()).forEach((group) => {
- Object.keys(getGroup(group)).forEach((filter) => {
+$(".pageAccount .topFilters .button.allFilters").click(() => {
+ (Object.keys(getFilters()) as MonkeyTypes.Group[]).forEach((group) => {
+ (
+ Object.keys(getGroup(group)) as MonkeyTypes.Filter[]
+ ).forEach((filter) => {
if (group === "date") {
+ // TODO figure out why "filter" is never
+ // @ts-ignore
filters[group][filter] = false;
} else {
+ // TODO figure out why "filter" is never
+ // @ts-ignore
filters[group][filter] = true;
}
});
@@ -369,9 +423,13 @@ $(".pageAccount .topFilters .button.allFilters").click((e) => {
save();
});
-$(".pageAccount .topFilters .button.currentConfigFilter").click((e) => {
- Object.keys(getFilters()).forEach((group) => {
- Object.keys(getGroup(group)).forEach((filter) => {
+$(".pageAccount .topFilters .button.currentConfigFilter").click(() => {
+ (Object.keys(getFilters()) as MonkeyTypes.Group[]).forEach((group) => {
+ (
+ Object.keys(getGroup(group)) as MonkeyTypes.Filter[]
+ ).forEach((filter) => {
+ // TODO figure out why "filter" is never
+ // @ts-ignore
filters[group][filter] = false;
});
});
@@ -379,11 +437,22 @@ $(".pageAccount .topFilters .button.currentConfigFilter").click((e) => {
filters["difficulty"][Config.difficulty] = true;
filters["mode"][Config.mode] = true;
if (Config.mode === "time") {
- filters["time"][Config.time] = true;
+ if ([15, 30, 60, 120].includes(Config.time)) {
+ const configTime = Config.time as MonkeyTypes.DefaultTimeModes;
+ filters["time"][configTime] = true;
+ }
} else if (Config.mode === "words") {
- filters["words"][Config.words] = true;
+ if ([10, 25, 50, 100, 200].includes(Config.words)) {
+ const configWords = Config.words as MonkeyTypes.DefaultWordsModes;
+ filters["words"][configWords] = true;
+ }
} else if (Config.mode === "quote") {
- Object.keys(getGroup("quoteLength")).forEach((ql) => {
+ (
+ Object.keys(
+ getGroup("quoteLength")
+ ) as MonkeyTypes.Filter<"quoteLength">[]
+ ).forEach((ql) => {
+ // TODO figure out how to fix this
filters["quoteLength"][ql] = true;
});
}
@@ -410,7 +479,8 @@ $(".pageAccount .topFilters .button.currentConfigFilter").click((e) => {
}
filters["tags"]["none"] = true;
- DB.getSnapshot().tags.forEach((tag) => {
+
+ DB.getSnapshot().tags?.forEach((tag) => {
if (tag.active === true) {
filters["tags"]["none"] = false;
filters["tags"][tag._id] = true;
@@ -422,7 +492,7 @@ $(".pageAccount .topFilters .button.currentConfigFilter").click((e) => {
save();
});
-$(".pageAccount .topFilters .button.toggleAdvancedFilters").click((e) => {
+$(".pageAccount .topFilters .button.toggleAdvancedFilters").click(() => {
$(".pageAccount .filterButtons").slideToggle(250);
$(".pageAccount .topFilters .button.toggleAdvancedFilters").toggleClass(
"active"
diff --git a/frontend/src/scripts/account/sign-out-button.js b/frontend/src/scripts/account/sign-out-button.ts
similarity index 92%
rename from frontend/src/scripts/account/sign-out-button.js
rename to frontend/src/scripts/account/sign-out-button.ts
index 0fe149942..4c85d266e 100644
--- a/frontend/src/scripts/account/sign-out-button.js
+++ b/frontend/src/scripts/account/sign-out-button.ts
@@ -1,4 +1,4 @@
-export function show() {
+export function show(): void {
// $(".signOut").removeClass("hidden").css("opacity", 1);
$(".signOut")
.stop(true, true)
@@ -18,7 +18,7 @@ export function show() {
);
}
-export function hide() {
+export function hide(): void {
$(".signOut")
.stop(true, true)
.css({
diff --git a/frontend/src/scripts/config.js b/frontend/src/scripts/config.ts
similarity index 78%
rename from frontend/src/scripts/config.js
rename to frontend/src/scripts/config.ts
index 830784006..9ed4a1290 100644
--- a/frontend/src/scripts/config.js
+++ b/frontend/src/scripts/config.ts
@@ -4,25 +4,25 @@ import * as Notifications from "./elements/notifications";
import * as Misc from "./misc";
import * as ConfigEvent from "./observables/config-event";
-export let localStorageConfig = null;
+export let localStorageConfig: MonkeyTypes.Config;
export let dbConfigLoaded = false;
export let changedBeforeDb = false;
-export function setLocalStorageConfig(val) {
+export function setLocalStorageConfig(val: MonkeyTypes.Config): void {
localStorageConfig = val;
}
-export function setDbConfigLoaded(val) {
+export function setDbConfigLoaded(val: boolean): void {
dbConfigLoaded = val;
}
-export function setChangedBeforeDb(val) {
+export function setChangedBeforeDb(val: boolean): void {
changedBeforeDb = val;
}
-let loadDone;
+let loadDone: (...stuff: any[]) => any;
-let defaultConfig = {
+const defaultConfig: MonkeyTypes.Config = {
theme: "serika_dark",
customTheme: false,
customThemeColors: [
@@ -73,7 +73,7 @@ let defaultConfig = {
keymapStyle: "staggered",
keymapLegendStyle: "lowercase",
keymapLayout: "overrideSync",
- fontFamily: "Roboto_Mono",
+ fontFamily: "roboto_mono",
smoothLineScroll: false,
alwaysShowDecimalPlaces: false,
alwaysShowWordsHistory: false,
@@ -117,7 +117,7 @@ let defaultConfig = {
lazyMode: false,
};
-function isConfigKeyValid(name) {
+function isConfigKeyValid(name: string): boolean {
if (name === null || name === undefined || name === "") return false;
if (name.length > 30) return false;
return /^[0-9a-zA-Z_.\-#+]+$/.test(name);
@@ -127,7 +127,7 @@ let config = {
...defaultConfig,
};
-export async function saveToLocalStorage(noDbCheck = false) {
+export async function saveToLocalStorage(noDbCheck = false): Promise {
if (!dbConfigLoaded && !noDbCheck) {
setChangedBeforeDb(true);
}
@@ -137,9 +137,9 @@ export async function saveToLocalStorage(noDbCheck = false) {
// expires: d,
// path: "/",
// });
- let save = config;
+ const save = config;
delete save.resultFilters;
- let stringified = JSON.stringify(save);
+ const stringified = JSON.stringify(save);
window.localStorage.setItem("config", stringified);
// restartCount = 0;
if (!noDbCheck) await DB.saveConfig(save);
@@ -147,7 +147,7 @@ export async function saveToLocalStorage(noDbCheck = false) {
}
//numbers
-export function setNumbers(numb, nosave) {
+export function setNumbers(numb: boolean, nosave?: boolean): void {
if (config.mode === "quote") {
numb = false;
}
@@ -162,7 +162,7 @@ export function setNumbers(numb, nosave) {
}
//punctuation
-export function setPunctuation(punc, nosave) {
+export function setPunctuation(punc: boolean, nosave?: boolean): void {
if (config.mode === "quote") {
punc = false;
}
@@ -176,12 +176,12 @@ export function setPunctuation(punc, nosave) {
ConfigEvent.dispatch("punctuation", config.punctuation);
}
-export function setMode(mode, nosave) {
+export function setMode(mode: MonkeyTypes.Mode, nosave?: boolean): void {
if (mode !== "words" && config.funbox === "memory") {
Notifications.add("Memory funbox can only be used with words mode.", 0);
return;
}
- let previous = config.mode;
+ const previous = config.mode;
config.mode = mode;
if (config.mode == "custom") {
setPunctuation(false, true);
@@ -198,7 +198,7 @@ export function setMode(mode, nosave) {
ConfigEvent.dispatch("mode", previous, config.mode);
}
-export function setPlaySoundOnError(val, nosave) {
+export function setPlaySoundOnError(val: boolean, nosave?: boolean): void {
if (val == undefined) {
val = false;
}
@@ -207,7 +207,10 @@ export function setPlaySoundOnError(val, nosave) {
ConfigEvent.dispatch("playSoundOnError", config.playSoundOnError);
}
-export function setPlaySoundOnClick(val, nosave) {
+export function setPlaySoundOnClick(
+ val: MonkeyTypes.PlaySoundOnClick,
+ nosave?: boolean
+): void {
if (val == undefined) {
val = "off";
}
@@ -216,7 +219,10 @@ export function setPlaySoundOnClick(val, nosave) {
ConfigEvent.dispatch("playSoundOnClick", config.playSoundOnClick);
}
-export function setSoundVolume(val, nosave) {
+export function setSoundVolume(
+ val: MonkeyTypes.SoundVolume,
+ nosave?: boolean
+): void {
if (val == undefined) {
val = "1.0";
}
@@ -226,7 +232,10 @@ export function setSoundVolume(val, nosave) {
}
//difficulty
-export function setDifficulty(diff, nosave) {
+export function setDifficulty(
+ diff: MonkeyTypes.Difficulty,
+ nosave?: boolean
+): void {
if (
(diff !== "normal" && diff !== "expert" && diff !== "master") ||
diff == undefined
@@ -239,20 +248,20 @@ export function setDifficulty(diff, nosave) {
}
//set fav themes
-export function setFavThemes(themes, nosave) {
+export function setFavThemes(themes: string[], nosave?: boolean): void {
config.favThemes = themes;
if (!nosave) saveToLocalStorage();
ConfigEvent.dispatch("favThemes", config.favThemes);
}
-export function setFunbox(funbox, nosave) {
- let val = funbox ? funbox : "none";
+export function setFunbox(funbox: string, nosave?: boolean): void {
+ const val = funbox ? funbox : "none";
config.funbox = val;
if (!nosave) saveToLocalStorage();
ConfigEvent.dispatch("funbox", config.funbox);
}
-export function setBlindMode(blind, nosave) {
+export function setBlindMode(blind: boolean, nosave?: boolean): void {
if (blind == undefined) {
blind = false;
}
@@ -261,7 +270,10 @@ export function setBlindMode(blind, nosave) {
ConfigEvent.dispatch("blindMode", config.blindMode);
}
-export function setChartAccuracy(chartAccuracy, nosave) {
+export function setChartAccuracy(
+ chartAccuracy: boolean,
+ nosave?: boolean
+): void {
if (chartAccuracy == undefined) {
chartAccuracy = true;
}
@@ -270,7 +282,10 @@ export function setChartAccuracy(chartAccuracy, nosave) {
ConfigEvent.dispatch("chartAccuracy", config.chartAccuracy);
}
-export function setChartStyle(chartStyle, nosave) {
+export function setChartStyle(
+ chartStyle: MonkeyTypes.ChartStyle,
+ nosave?: boolean
+): void {
if (chartStyle == undefined) {
chartStyle = "line";
}
@@ -279,7 +294,10 @@ export function setChartStyle(chartStyle, nosave) {
ConfigEvent.dispatch("chartStyle", config.chartStyle);
}
-export function setStopOnError(soe, nosave) {
+export function setStopOnError(
+ soe: MonkeyTypes.StopOnError | boolean,
+ nosave?: boolean
+): void {
if (soe == undefined || soe === true || soe === false) {
soe = "off";
}
@@ -291,7 +309,10 @@ export function setStopOnError(soe, nosave) {
ConfigEvent.dispatch("stopOnError", config.stopOnError);
}
-export function setAlwaysShowDecimalPlaces(val, nosave) {
+export function setAlwaysShowDecimalPlaces(
+ val: boolean,
+ nosave?: boolean
+): void {
if (val == undefined) {
val = false;
}
@@ -303,7 +324,7 @@ export function setAlwaysShowDecimalPlaces(val, nosave) {
);
}
-export function setAlwaysShowCPM(val, nosave) {
+export function setAlwaysShowCPM(val: boolean, nosave?: boolean): void {
if (val == undefined) {
val = false;
}
@@ -312,7 +333,7 @@ export function setAlwaysShowCPM(val, nosave) {
ConfigEvent.dispatch("alwaysShowCPM", config.alwaysShowCPM);
}
-export function setShowOutOfFocusWarning(val, nosave) {
+export function setShowOutOfFocusWarning(val: boolean, nosave?: boolean): void {
if (val == undefined) {
val = true;
}
@@ -324,7 +345,7 @@ export function setShowOutOfFocusWarning(val, nosave) {
ConfigEvent.dispatch("showOutOfFocusWarning", config.showOutOfFocusWarning);
}
-export function setSwapEscAndTab(val, nosave) {
+export function setSwapEscAndTab(val: boolean, nosave?: boolean): void {
if (val == undefined) {
val = false;
}
@@ -334,7 +355,10 @@ export function setSwapEscAndTab(val, nosave) {
}
//pace caret
-export function setPaceCaret(val, nosave) {
+export function setPaceCaret(
+ val: MonkeyTypes.PaceCaret,
+ nosave?: boolean
+): void {
if (val == undefined) {
val = "off";
}
@@ -353,9 +377,8 @@ export function setPaceCaret(val, nosave) {
ConfigEvent.dispatch("paceCaret", config.paceCaret);
}
-export function setPaceCaretCustomSpeed(val, nosave) {
- val = parseInt(val);
- if (val == undefined || Number.isNaN(val)) {
+export function setPaceCaretCustomSpeed(val: number, nosave?: boolean): void {
+ if (val == undefined) {
val = 100;
}
config.paceCaretCustomSpeed = val;
@@ -363,7 +386,7 @@ export function setPaceCaretCustomSpeed(val, nosave) {
ConfigEvent.dispatch("paceCaretCustomSpeed", config.paceCaretCustomSpeed);
}
-export function setRepeatedPace(pace, nosave) {
+export function setRepeatedPace(pace: boolean, nosave?: boolean): void {
if (pace == undefined) {
pace = true;
}
@@ -373,7 +396,10 @@ export function setRepeatedPace(pace, nosave) {
}
//min wpm
-export function setMinWpm(minwpm, nosave) {
+export function setMinWpm(
+ minwpm: MonkeyTypes.MinimumWordsPerMinute,
+ nosave?: boolean
+): void {
if (minwpm == undefined) {
minwpm = "off";
}
@@ -382,9 +408,8 @@ export function setMinWpm(minwpm, nosave) {
ConfigEvent.dispatch("minWpm", config.minWpm);
}
-export function setMinWpmCustomSpeed(val, nosave) {
- val = parseInt(val);
- if (val == undefined || Number.isNaN(val)) {
+export function setMinWpmCustomSpeed(val: number, nosave?: boolean): void {
+ if (val == undefined) {
val = 100;
}
config.minWpmCustomSpeed = val;
@@ -393,7 +418,10 @@ export function setMinWpmCustomSpeed(val, nosave) {
}
//min acc
-export function setMinAcc(min, nosave) {
+export function setMinAcc(
+ min: MonkeyTypes.MinimumAccuracy,
+ nosave?: boolean
+): void {
if (min == undefined) {
min = "off";
}
@@ -402,8 +430,8 @@ export function setMinAcc(min, nosave) {
ConfigEvent.dispatch("minAcc", config.minAcc);
}
-export function setMinAccCustom(val, nosave) {
- if (val == undefined || Number.isNaN(parseInt(val))) {
+export function setMinAccCustom(val: number, nosave?: boolean): void {
+ if (val === undefined) {
val = 90;
}
config.minAccCustom = val;
@@ -412,7 +440,10 @@ export function setMinAccCustom(val, nosave) {
}
//min burst
-export function setMinBurst(min, nosave) {
+export function setMinBurst(
+ min: MonkeyTypes.MinimumBurst,
+ nosave?: boolean
+): void {
if (min == undefined) {
min = "off";
}
@@ -421,9 +452,8 @@ export function setMinBurst(min, nosave) {
ConfigEvent.dispatch("minBurst", config.minBurst);
}
-export function setMinBurstCustomSpeed(val, nosave) {
- val = parseInt(val);
- if (val == undefined || Number.isNaN(val)) {
+export function setMinBurstCustomSpeed(val: number, nosave?: boolean): void {
+ if (val == undefined) {
val = 100;
}
config.minBurstCustomSpeed = val;
@@ -432,7 +462,10 @@ export function setMinBurstCustomSpeed(val, nosave) {
}
//always show words history
-export function setAlwaysShowWordsHistory(val, nosave) {
+export function setAlwaysShowWordsHistory(
+ val: boolean,
+ nosave?: boolean
+): void {
if (val == undefined) {
val = false;
}
@@ -442,7 +475,10 @@ export function setAlwaysShowWordsHistory(val, nosave) {
}
//single list command line
-export function setSingleListCommandLine(option, nosave) {
+export function setSingleListCommandLine(
+ option: MonkeyTypes.SingleListCommandLine,
+ nosave?: boolean
+): void {
if (!option) option = "manual";
config.singleListCommandLine = option;
if (!nosave) saveToLocalStorage();
@@ -450,7 +486,7 @@ export function setSingleListCommandLine(option, nosave) {
}
//caps lock warning
-export function setCapsLockWarning(val, nosave) {
+export function setCapsLockWarning(val: boolean, nosave?: boolean): void {
if (val == undefined) {
val = false;
}
@@ -459,7 +495,7 @@ export function setCapsLockWarning(val, nosave) {
ConfigEvent.dispatch("capsLockWarning", config.capsLockWarning);
}
-export function setShowAllLines(sal, nosave) {
+export function setShowAllLines(sal: boolean, nosave?: boolean): void {
if (sal == undefined) {
sal = false;
}
@@ -470,7 +506,7 @@ export function setShowAllLines(sal, nosave) {
ConfigEvent.dispatch("showAllLines", config.showAllLines);
}
-export function setQuickEnd(qe, nosave) {
+export function setQuickEnd(qe: boolean, nosave?: boolean): void {
if (qe == undefined) {
qe = false;
}
@@ -479,7 +515,10 @@ export function setQuickEnd(qe, nosave) {
ConfigEvent.dispatch("quickEnd", config.quickEnd);
}
-export function setEnableAds(val, nosave) {
+export function setEnableAds(
+ val: MonkeyTypes.EnableAds | boolean,
+ nosave?: boolean
+): void {
if (val == undefined || val === true || val === false) {
val = "off";
}
@@ -493,7 +532,10 @@ export function setEnableAds(val, nosave) {
}
}
-export function setRepeatQuotes(val, nosave) {
+export function setRepeatQuotes(
+ val: MonkeyTypes.RepeatQuotes | boolean,
+ nosave?: boolean
+): void {
if (val == undefined || val === true || val === false) {
val = "off";
}
@@ -503,7 +545,7 @@ export function setRepeatQuotes(val, nosave) {
}
//flip colors
-export function setFlipTestColors(flip, nosave) {
+export function setFlipTestColors(flip: boolean, nosave?: boolean): void {
if (flip == undefined) {
flip = false;
}
@@ -513,7 +555,7 @@ export function setFlipTestColors(flip, nosave) {
}
//extra color
-export function setColorfulMode(extra, nosave) {
+export function setColorfulMode(extra: boolean, nosave?: boolean): void {
if (extra == undefined) {
extra = false;
}
@@ -523,7 +565,7 @@ export function setColorfulMode(extra, nosave) {
}
//strict space
-export function setStrictSpace(val, nosave) {
+export function setStrictSpace(val: boolean, nosave?: boolean): void {
if (val == undefined) {
val = false;
}
@@ -533,7 +575,10 @@ export function setStrictSpace(val, nosave) {
}
//opposite shift space
-export function setOppositeShiftMode(val, nosave) {
+export function setOppositeShiftMode(
+ val: MonkeyTypes.OppositeShiftMode,
+ nosave?: boolean
+): void {
if (val == undefined) {
val = "off";
}
@@ -542,7 +587,10 @@ export function setOppositeShiftMode(val, nosave) {
ConfigEvent.dispatch("oppositeShiftMode", config.oppositeShiftMode);
}
-export function setPageWidth(val, nosave) {
+export function setPageWidth(
+ val: MonkeyTypes.PageWidth,
+ nosave?: boolean
+): void {
if (val == null || val == undefined) {
val = "100";
}
@@ -559,7 +607,10 @@ export function setPageWidth(val, nosave) {
ConfigEvent.dispatch("pageWidth", config.pageWidth);
}
-export function setCaretStyle(caretStyle, nosave) {
+export function setCaretStyle(
+ caretStyle: MonkeyTypes.CaretStyle,
+ nosave?: boolean
+): void {
if (caretStyle == null || caretStyle == undefined) {
caretStyle = "default";
}
@@ -591,7 +642,10 @@ export function setCaretStyle(caretStyle, nosave) {
ConfigEvent.dispatch("caretStyle", config.caretStyle);
}
-export function setPaceCaretStyle(caretStyle, nosave) {
+export function setPaceCaretStyle(
+ caretStyle: MonkeyTypes.CaretStyle,
+ nosave?: boolean
+): void {
if (caretStyle == null || caretStyle == undefined) {
caretStyle = "default";
}
@@ -621,7 +675,7 @@ export function setPaceCaretStyle(caretStyle, nosave) {
ConfigEvent.dispatch("paceCaretStyle", config.paceCaretStyle);
}
-export function setShowTimerProgress(timer, nosave) {
+export function setShowTimerProgress(timer: boolean, nosave?: boolean): void {
if (timer == null || timer == undefined) {
timer = false;
}
@@ -630,7 +684,7 @@ export function setShowTimerProgress(timer, nosave) {
ConfigEvent.dispatch("showTimerProgress", config.showTimerProgress);
}
-export function setShowLiveWpm(live, nosave) {
+export function setShowLiveWpm(live: boolean, nosave?: boolean): void {
if (live == null || live == undefined) {
live = false;
}
@@ -639,7 +693,7 @@ export function setShowLiveWpm(live, nosave) {
ConfigEvent.dispatch("showLiveWpm", config.showLiveWpm);
}
-export function setShowLiveAcc(live, nosave) {
+export function setShowLiveAcc(live: boolean, nosave?: boolean): void {
if (live == null || live == undefined) {
live = false;
}
@@ -648,7 +702,7 @@ export function setShowLiveAcc(live, nosave) {
ConfigEvent.dispatch("showLiveAcc", config.showLiveAcc);
}
-export function setShowLiveBurst(live, nosave) {
+export function setShowLiveBurst(live: boolean, nosave?: boolean): void {
if (live == null || live == undefined) {
live = false;
}
@@ -657,7 +711,10 @@ export function setShowLiveBurst(live, nosave) {
ConfigEvent.dispatch("showLiveBurst", config.showLiveBurst);
}
-export function setHighlightMode(mode, nosave) {
+export function setHighlightMode(
+ mode: MonkeyTypes.HighlightMode,
+ nosave?: boolean
+): void {
if (
mode === "word" &&
(config.funbox === "nospace" ||
@@ -678,7 +735,7 @@ export function setHighlightMode(mode, nosave) {
ConfigEvent.dispatch("highlightMode", config.highlightMode);
}
-export function setHideExtraLetters(val, nosave) {
+export function setHideExtraLetters(val: boolean, nosave?: boolean): void {
if (val == null || val == undefined) {
val = false;
}
@@ -687,7 +744,10 @@ export function setHideExtraLetters(val, nosave) {
ConfigEvent.dispatch("hideExtraLetters", config.hideExtraLetters);
}
-export function setTimerStyle(style, nosave) {
+export function setTimerStyle(
+ style: MonkeyTypes.TimerStyle,
+ nosave?: boolean
+): void {
if (style == null || style == undefined) {
style = "mini";
}
@@ -696,7 +756,10 @@ export function setTimerStyle(style, nosave) {
ConfigEvent.dispatch("timerStyle", config.timerStyle);
}
-export function setTimerColor(color, nosave) {
+export function setTimerColor(
+ color: MonkeyTypes.TimerColor,
+ nosave?: boolean
+): void {
if (!color || !["black", "sub", "text", "main"].includes(color)) {
color = "black";
}
@@ -738,9 +801,12 @@ export function setTimerColor(color, nosave) {
if (!nosave) saveToLocalStorage();
ConfigEvent.dispatch("timerColor", config.timerColor);
}
-export function setTimerOpacity(opacity, nosave) {
+export function setTimerOpacity(
+ opacity: MonkeyTypes.TimerOpacity,
+ nosave?: boolean
+): void {
if (opacity == null || opacity == undefined) {
- opacity = 0.25;
+ opacity = "0.25";
}
config.timerOpacity = opacity;
if (!nosave) saveToLocalStorage();
@@ -748,7 +814,7 @@ export function setTimerOpacity(opacity, nosave) {
}
//key tips
-export function setKeyTips(keyTips, nosave) {
+export function setKeyTips(keyTips: boolean, nosave?: boolean): void {
config.showKeyTips = keyTips;
if (config.showKeyTips) {
$("#bottom .keyTips").removeClass("hidden");
@@ -760,26 +826,34 @@ export function setKeyTips(keyTips, nosave) {
}
//mode
-export function setTimeConfig(time, nosave) {
- if (time === null || isNaN(time) || time < 0) {
- time = 15;
- }
- time = parseInt(time);
- // if (!nosave) setMode("time", nosave);
- config.time = time;
+export function setTimeConfig(
+ time: MonkeyTypes.TimeModes,
+ nosave?: boolean
+): void {
+ const newTime =
+ time === null || time === undefined || isNaN(time) || time < 0
+ ? defaultConfig.time
+ : time;
+
$("#top .config .time .text-button").removeClass("active");
- if (![15, 30, 60, 120].includes(time)) {
- time = "custom";
- }
- $("#top .config .time .text-button[timeConfig='" + time + "']").addClass(
- "active"
- );
+
+ const timeCustom = ![15, 30, 60, 120].includes(newTime) ? "custom" : newTime;
+
+ config.time = newTime;
+
+ $(
+ "#top .config .time .text-button[timeConfig='" + timeCustom + "']"
+ ).addClass("active");
if (!nosave) saveToLocalStorage();
ConfigEvent.dispatch("time", config.time);
}
//quote length
-export function setQuoteLength(len, nosave, multipleMode) {
+export function setQuoteLength(
+ len: MonkeyTypes.QuoteLengthArray | MonkeyTypes.QuoteLength,
+ nosave?: boolean,
+ multipleMode?: boolean
+): void {
if (Array.isArray(len)) {
//config load
if (len.length === 1 && len[0] === -1) len = [1];
@@ -789,7 +863,7 @@ export function setQuoteLength(len, nosave, multipleMode) {
if (len === null || isNaN(len) || len < -2 || len > 3) {
len = 1;
}
- len = parseInt(len);
+ len = parseInt(len.toString()) as MonkeyTypes.QuoteLength;
if (multipleMode) {
if (!config.quoteLength.includes(len)) {
config.quoteLength.push(len);
@@ -812,31 +886,35 @@ export function setQuoteLength(len, nosave, multipleMode) {
ConfigEvent.dispatch("quoteLength", config.quoteLength);
}
-export function setWordCount(wordCount, nosave) {
- wordCount = parseInt(wordCount);
- if (
+export function setWordCount(
+ wordCount: MonkeyTypes.WordsModes,
+ nosave?: boolean
+): void {
+ const newWordCount =
wordCount === null ||
- isNaN(wordCount) ||
+ wordCount === undefined ||
wordCount < 0 ||
wordCount > 100000
- ) {
- wordCount = defaultConfig.words;
- }
- // if (!nosave) setMode("words", nosave);
- config.words = wordCount;
+ ? defaultConfig.words
+ : wordCount;
+
$("#top .config .wordCount .text-button").removeClass("active");
- if (![10, 25, 50, 100, 200].includes(wordCount)) {
- wordCount = "custom";
- }
- $(`#top .config .wordCount .text-button[wordCount='${wordCount}']`).addClass(
- "active"
- );
+
+ const wordCustom = ![10, 25, 50, 100, 200].includes(newWordCount)
+ ? "custom"
+ : newWordCount;
+
+ config.words = newWordCount;
+
+ $(
+ "#top .config .wordCount .text-button[wordCount='" + wordCustom + "']"
+ ).addClass("active");
if (!nosave) saveToLocalStorage();
ConfigEvent.dispatch("words", config.words);
}
//caret
-export function setSmoothCaret(mode, nosave) {
+export function setSmoothCaret(mode: boolean, nosave?: boolean): void {
config.smoothCaret = mode;
if (mode) {
$("#caret").css("animation-name", "caretFlashSmooth");
@@ -847,21 +925,21 @@ export function setSmoothCaret(mode, nosave) {
ConfigEvent.dispatch("smoothCaret", config.smoothCaret);
}
-export function setStartGraphsAtZero(mode, nosave) {
+export function setStartGraphsAtZero(mode: boolean, nosave?: boolean): void {
config.startGraphsAtZero = mode;
if (!nosave) saveToLocalStorage();
ConfigEvent.dispatch("startGraphsAtZero", config.startGraphsAtZero);
}
//linescroll
-export function setSmoothLineScroll(mode, nosave) {
+export function setSmoothLineScroll(mode: boolean, nosave?: boolean): void {
config.smoothLineScroll = mode;
if (!nosave) saveToLocalStorage();
ConfigEvent.dispatch("smoothLineScroll", config.smoothLineScroll);
}
//quick tab
-export function setQuickTabMode(mode, nosave) {
+export function setQuickTabMode(mode: boolean, nosave?: boolean): void {
config.quickTab = mode;
if (!config.quickTab) {
$("#restartTestButton").removeClass("hidden");
@@ -878,9 +956,9 @@ export function setQuickTabMode(mode, nosave) {
ConfigEvent.dispatch("quickTab", config.quickTab);
}
-export function previewFontFamily(font) {
+export function previewFontFamily(font: string): void {
if (font == undefined) {
- font = "Roboto_Mono";
+ font = "roboto_mono";
}
document.documentElement.style.setProperty(
"--font",
@@ -889,9 +967,9 @@ export function previewFontFamily(font) {
}
//font family
-export function setFontFamily(font, nosave) {
+export function setFontFamily(font: string, nosave?: boolean): void {
if (font == undefined || font === "") {
- font = "Roboto_Mono";
+ font = "roboto_mono";
Notifications.add(
"Empty input received, reverted to the default font.",
0,
@@ -918,7 +996,7 @@ export function setFontFamily(font, nosave) {
}
//freedom
-export function setFreedomMode(freedom, nosave) {
+export function setFreedomMode(freedom: boolean, nosave?: boolean): void {
if (freedom == null) {
freedom = false;
}
@@ -930,7 +1008,10 @@ export function setFreedomMode(freedom, nosave) {
ConfigEvent.dispatch("freedomMode", config.freedomMode);
}
-export function setConfidenceMode(cm, nosave) {
+export function setConfidenceMode(
+ cm: MonkeyTypes.ConfidenceMode,
+ nosave?: boolean
+): void {
if (cm == undefined || !["off", "on", "max"].includes(cm)) {
cm = defaultConfig.confidenceMode;
}
@@ -943,7 +1024,10 @@ export function setConfidenceMode(cm, nosave) {
ConfigEvent.dispatch("confidenceMode", config.confidenceMode);
}
-export function setIndicateTypos(value, nosave) {
+export function setIndicateTypos(
+ value: MonkeyTypes.IndicateTypos,
+ nosave?: boolean
+): void {
if (!["off", "below", "replace"].includes(value)) {
value = defaultConfig.indicateTypos;
}
@@ -952,27 +1036,34 @@ export function setIndicateTypos(value, nosave) {
ConfigEvent.dispatch("indicateTypos", config.indicateTypos);
}
-export function setCustomTheme(boolean, nosave) {
+export function setCustomTheme(boolean: boolean, nosave?: boolean): void {
if (boolean !== undefined) config.customTheme = boolean;
if (!nosave) saveToLocalStorage();
ConfigEvent.dispatch("customTheme", config.customTheme);
}
-export function setTheme(name, nosave) {
+export function setTheme(name: string, nosave?: boolean): void {
config.theme = name;
- setCustomTheme(false, true, true);
+ setCustomTheme(false, true);
if (!nosave) saveToLocalStorage();
ConfigEvent.dispatch("theme", config.theme);
}
-function setThemes(theme, customState, nosave) {
+function setThemes(
+ theme: string,
+ customState: boolean,
+ nosave?: boolean
+): void {
config.theme = theme;
config.customTheme = customState;
if (!nosave) saveToLocalStorage();
ConfigEvent.dispatch("setThemes", customState);
}
-export function setRandomTheme(val, nosave) {
+export function setRandomTheme(
+ val: MonkeyTypes.RandomTheme | boolean,
+ nosave?: boolean
+): void {
if (val === undefined || val === true || val === false) {
val = "off";
}
@@ -981,7 +1072,7 @@ export function setRandomTheme(val, nosave) {
ConfigEvent.dispatch("randomTheme", config.randomTheme);
}
-export function setBritishEnglish(val, nosave) {
+export function setBritishEnglish(val: boolean, nosave?: boolean): void {
if (!val) {
val = false;
}
@@ -990,7 +1081,7 @@ export function setBritishEnglish(val, nosave) {
ConfigEvent.dispatch("britishEnglish", config.britishEnglish);
}
-export function setLazyMode(val, nosave) {
+export function setLazyMode(val: boolean, nosave?: boolean): void {
if (!val) {
val = false;
}
@@ -999,7 +1090,7 @@ export function setLazyMode(val, nosave) {
ConfigEvent.dispatch("lazyMode", config.lazyMode, nosave);
}
-export function setCustomThemeColors(colors, nosave) {
+export function setCustomThemeColors(colors: string[], nosave?: boolean): void {
if (colors !== undefined) {
config.customThemeColors = colors;
// ThemeController.set("custom");
@@ -1009,7 +1100,7 @@ export function setCustomThemeColors(colors, nosave) {
ConfigEvent.dispatch("customThemeColors", config.customThemeColors);
}
-export function setLanguage(language, nosave) {
+export function setLanguage(language: string, nosave?: boolean): void {
if (language == null || language == undefined) {
language = "english";
}
@@ -1025,7 +1116,7 @@ export function setLanguage(language, nosave) {
ConfigEvent.dispatch("language", config.language);
}
-export function setMonkey(monkey, nosave) {
+export function setMonkey(monkey: boolean, nosave?: boolean): void {
if (monkey === null || monkey === undefined) {
monkey = false;
}
@@ -1039,7 +1130,10 @@ export function setMonkey(monkey, nosave) {
ConfigEvent.dispatch("monkey", config.monkey);
}
-export function setKeymapMode(mode, nosave) {
+export function setKeymapMode(
+ mode: MonkeyTypes.KeymapMode,
+ nosave?: boolean
+): void {
if (mode == null || mode == undefined) {
mode = "off";
}
@@ -1050,7 +1144,10 @@ export function setKeymapMode(mode, nosave) {
ConfigEvent.dispatch("keymapMode", config.keymapMode);
}
-export function setKeymapLegendStyle(style, nosave) {
+export function setKeymapLegendStyle(
+ style: MonkeyTypes.KeymapLegendStyle,
+ nosave?: boolean
+): void {
// Remove existing styles
const keymapLegendStyles = ["lowercase", "uppercase", "blank"];
keymapLegendStyles.forEach((name) => {
@@ -1079,14 +1176,17 @@ export function setKeymapLegendStyle(style, nosave) {
ConfigEvent.dispatch("keymapLegendStyle", config.keymapLegendStyle);
}
-export function setKeymapStyle(style, nosave) {
+export function setKeymapStyle(
+ style: MonkeyTypes.KeymapStyle,
+ nosave?: boolean
+): void {
style = style || "staggered";
config.keymapStyle = style;
if (!nosave) saveToLocalStorage();
ConfigEvent.dispatch("keymapStyle", config.keymapStyle);
}
-export function setKeymapLayout(layout, nosave) {
+export function setKeymapLayout(layout: string, nosave?: boolean): void {
if (layout == null || layout == undefined) {
layout = "qwerty";
}
@@ -1095,7 +1195,7 @@ export function setKeymapLayout(layout, nosave) {
ConfigEvent.dispatch("keymapLayout", config.keymapLayout);
}
-export function setLayout(layout, nosave) {
+export function setLayout(layout: string, nosave?: boolean): void {
if (layout == null || layout == undefined) {
layout = "qwerty";
}
@@ -1104,7 +1204,7 @@ export function setLayout(layout, nosave) {
ConfigEvent.dispatch("layout", config.layout);
}
-// export function setSavedLayout(layout, nosave) {
+// export function setSavedLayout(layout, nosave?: boolean): void {
// if (layout == null || layout == undefined) {
// layout = "qwerty";
// }
@@ -1112,7 +1212,10 @@ export function setLayout(layout, nosave) {
// setLayout(layout, nosave);
// }
-export function setFontSize(fontSize, nosave) {
+export function setFontSize(
+ fontSize: MonkeyTypes.FontSize,
+ nosave?: boolean
+): void {
if (fontSize == null || fontSize == undefined) {
fontSize = 1;
}
@@ -1162,7 +1265,7 @@ export function setFontSize(fontSize, nosave) {
ConfigEvent.dispatch("fontSize", config.fontSize);
}
-export function setCustomBackground(value, nosave) {
+export function setCustomBackground(value: string, nosave?: boolean): void {
if (value == null || value == undefined) {
value = "";
}
@@ -1182,36 +1285,46 @@ export function setCustomBackground(value, nosave) {
}
}
-export async function setCustomLayoutfluid(value, nosave) {
+export async function setCustomLayoutfluid(
+ value: MonkeyTypes.CustomLayoutFluidSpaces,
+ nosave?: boolean
+): Promise {
if (value == null || value == undefined) {
value = "qwerty#dvorak#colemak";
}
- value = value.replace(/ /g, "#");
+ let customLayoutfluid = value.replace(
+ / /g,
+ "#"
+ ) as MonkeyTypes.CustomLayoutFluid;
//validate the layouts
- let allGood = true;
- await value.split("#").forEach(async (customLayout) => {
- const lay = await Misc.getLayout(customLayout);
- if (!lay) allGood = false;
- });
+ const allGood = (
+ await Promise.all(
+ value.split("#").map((customLayout) => Misc.getLayout(customLayout))
+ )
+ ).every((customLayout) => customLayout);
+
if (!allGood) {
Notifications.add(
"One of the layouts was not found. Make sure the name matches exactly. Reverting to default",
0,
4
);
- value = "qwerty#dvorak#colemak";
+ customLayoutfluid = "qwerty#dvorak#colemak";
nosave = false;
}
- config.customLayoutfluid = value;
+ config.customLayoutfluid = customLayoutfluid;
$(".pageSettings .section.customLayoutfluid input").val(
- value.replace(/#/g, " ")
+ customLayoutfluid.replace(/#/g, " ")
);
if (!nosave) saveToLocalStorage();
- ConfigEvent.dispatch("customLayoutFluid", config.customLayoutFluid);
+ ConfigEvent.dispatch("customLayoutFluid", config.customLayoutfluid);
}
-export function setCustomBackgroundSize(value, nosave) {
+export function setCustomBackgroundSize(
+ value: MonkeyTypes.CustomBackgroundSize,
+ nosave?: boolean
+): void {
if (value != "cover" && value != "contain" && value != "max") {
value = "cover";
}
@@ -1220,20 +1333,26 @@ export function setCustomBackgroundSize(value, nosave) {
ConfigEvent.dispatch("customBackgroundSize", config.customBackgroundSize);
}
-export function setCustomBackgroundFilter(array, nosave) {
+export function setCustomBackgroundFilter(
+ array: MonkeyTypes.CustomBackgroundFilter,
+ nosave?: boolean
+): void {
config.customBackgroundFilter = array;
if (!nosave) saveToLocalStorage();
ConfigEvent.dispatch("customBackgroundFilter", config.customBackgroundFilter);
}
-export function setMonkeyPowerLevel(level, nosave) {
+export function setMonkeyPowerLevel(
+ level: MonkeyTypes.MonkeyPowerLevel,
+ nosave?: boolean
+): void {
if (!["off", "1", "2", "3", "4"].includes(level)) level = "off";
config.monkeyPowerLevel = level;
if (!nosave) saveToLocalStorage();
ConfigEvent.dispatch("monkeyPowerLevel", config.monkeyPowerLevel);
}
-export function setBurstHeatmap(value, nosave) {
+export function setBurstHeatmap(value: boolean, nosave?: boolean): void {
if (!value) {
value = false;
}
@@ -1244,17 +1363,21 @@ export function setBurstHeatmap(value, nosave) {
ConfigEvent.dispatch("burstHeatmap", config.burstHeatmap);
}
-export function apply(configObj) {
- if (configObj == null || configObj == undefined) {
+export function apply(configObj: MonkeyTypes.Config | null | "null"): void {
+ if (configObj == null || configObj == undefined || configObj === "null") {
Notifications.add("Could not apply config", -1, 3);
return;
}
- Object.keys(defaultConfig).forEach((configKey) => {
- if (configObj[configKey] === undefined) {
- configObj[configKey] = defaultConfig[configKey];
+ (Object.keys(defaultConfig) as (keyof MonkeyTypes.Config)[]).forEach(
+ (configKey) => {
+ if (configObj[configKey] === undefined) {
+ const newValue = defaultConfig[configKey];
+
+ (configObj[configKey] as typeof newValue) = newValue;
+ }
}
- });
- if (configObj && configObj != null && configObj != "null") {
+ );
+ if (configObj && configObj !== null) {
setCustomThemeColors(configObj.customThemeColors, true);
setThemes(configObj.theme, configObj.customTheme, true);
// setTheme(configObj.theme, true);
@@ -1432,7 +1555,7 @@ export function apply(configObj) {
$("#ad_about1").remove();
$("#ad_about2").remove();
}
- } catch (e) {
+ } catch (e: any) {
Notifications.add("Error initialising ads: " + e.message);
console.log("error initialising ads " + e.message);
$(".footerads").remove();
@@ -1454,20 +1577,25 @@ export function apply(configObj) {
}
}
-export function reset() {
+export function reset(): void {
apply(defaultConfig);
saveToLocalStorage();
}
-export function loadFromLocalStorage() {
+export function loadFromLocalStorage(): void {
console.log("loading localStorage config");
// let newConfig = $.cookie("config");
- let newConfig = window.localStorage.getItem("config");
- if (newConfig !== undefined && newConfig !== null && newConfig !== "") {
+ const newConfigString = window.localStorage.getItem("config");
+ let newConfig: MonkeyTypes.Config;
+ if (
+ newConfigString !== undefined &&
+ newConfigString !== null &&
+ newConfigString !== ""
+ ) {
try {
- newConfig = JSON.parse(newConfig);
+ newConfig = JSON.parse(newConfigString);
} catch (e) {
- newConfig = {};
+ newConfig = {} as MonkeyTypes.Config;
}
apply(newConfig);
console.log("applying localStorage config");
@@ -1479,23 +1607,23 @@ export function loadFromLocalStorage() {
loadDone();
}
-export function getConfigChanges() {
- let configChanges = {};
- Object.keys(config)
+export function getConfigChanges(): MonkeyTypes.Config {
+ const configChanges = {} as MonkeyTypes.Config;
+ (Object.keys(config) as (keyof MonkeyTypes.Config)[])
.filter((key) => {
return config[key] != defaultConfig[key];
})
.forEach((key) => {
- configChanges[key] = config[key];
+ (configChanges[key] as typeof config[typeof key]) = config[key];
});
return configChanges;
}
-export function setConfig(newConfig) {
+export function setConfig(newConfig: MonkeyTypes.Config): void {
config = newConfig;
}
-export let loadPromise = new Promise((v) => {
+export const loadPromise = new Promise((v) => {
loadDone = v;
});
diff --git a/frontend/src/scripts/controllers/account-controller.js b/frontend/src/scripts/controllers/account-controller.js
index 490f111aa..c2c95f352 100644
--- a/frontend/src/scripts/controllers/account-controller.js
+++ b/frontend/src/scripts/controllers/account-controller.js
@@ -79,10 +79,10 @@ export async function getDataAndInit() {
LoadingPage.updateBar(45);
}
LoadingPage.updateText("Applying settings...");
- let snap = DB.getSnapshot();
- $("#menu .icon-button.account .text").text(snap.name);
+ const snapshot = DB.getSnapshot();
+ $("#menu .icon-button.account .text").text(snapshot.name);
- ResultFilters.loadTags(DB.getSnapshot().tags);
+ ResultFilters.loadTags(snapshot.tags);
Promise.all([Misc.getLanguageList(), Misc.getFunboxList()]).then((values) => {
let languages = values[0];
@@ -98,12 +98,12 @@ export async function getDataAndInit() {
});
let user = firebase.auth().currentUser;
- if (snap.name == undefined) {
+ if (snapshot.name == undefined) {
//verify username
if (Misc.isUsernameValid(user.name)) {
//valid, just update
- snap.name = user.name;
- DB.setSnapshot(snap);
+ snapshot.name = user.name;
+ DB.setSnapshot(snapshot);
DB.updateName(user.uid, user.name);
} else {
//invalid, get new
@@ -134,7 +134,8 @@ export async function getDataAndInit() {
if (response?.status == 200) {
nameGood = true;
Notifications.add("Name updated", 1);
- DB.getSnapshot().name = name;
+ snapshot.name = name;
+ DB.setSnapshot(snapshot);
$("#menu .icon-button.account .text").text(name);
}
}
@@ -145,11 +146,11 @@ export async function getDataAndInit() {
if (Config.localStorageConfig === null) {
console.log("no local config, applying db");
AccountButton.loading(false);
- UpdateConfig.apply(DB.getSnapshot().config);
+ UpdateConfig.apply(snapshot.config);
Settings.update();
UpdateConfig.saveToLocalStorage(true);
TestLogic.restart(false, true);
- } else if (DB.getSnapshot().config !== undefined) {
+ } else if (snapshot.config !== undefined) {
//loading db config, keep for now
let configsDifferent = false;
Object.keys(Config).forEach((key) => {
@@ -158,22 +159,18 @@ export async function getDataAndInit() {
if (key !== "resultFilters") {
if (Array.isArray(Config[key])) {
Config[key].forEach((arrval, index) => {
- if (arrval != DB.getSnapshot().config[key][index]) {
+ if (arrval != snapshot.config[key][index]) {
configsDifferent = true;
console.log(
- `.config is different: ${arrval} != ${
- DB.getSnapshot().config[key][index]
- }`
+ `.config is different: ${arrval} != ${snapshot.config[key][index]}`
);
}
});
} else {
- if (Config[key] != DB.getSnapshot().config[key]) {
+ if (Config[key] != snapshot.config[key]) {
configsDifferent = true;
console.log(
- `..config is different ${key}: ${Config[key]} != ${
- DB.getSnapshot().config[key]
- }`
+ `..config is different ${key}: ${Config[key]} != ${snapshot.config[key]}`
);
}
}
@@ -188,7 +185,7 @@ export async function getDataAndInit() {
if (configsDifferent) {
console.log("configs are different, applying config from db");
AccountButton.loading(false);
- UpdateConfig.apply(DB.getSnapshot().config);
+ UpdateConfig.apply(snapshot.config);
Settings.update();
UpdateConfig.saveToLocalStorage(true);
if (ActivePage.get() == "test") {
@@ -444,7 +441,11 @@ export async function signInWithGoogle() {
})
.then((result) => {
if (result.status === 200) {
- DB.getSnapshot().results.push(TestLogic.notSignedInLastResult);
+ const snapshot = DB.getSnapshot();
+
+ snapshot.results.push(TestLogic.notSignedInLastResult);
+
+ DB.setSnapshot(snapshot);
}
});
// PageController.change("account");
@@ -659,7 +660,11 @@ async function signUp() {
})
.then((result) => {
if (result.status === 200) {
- DB.getSnapshot().results.push(TestLogic.notSignedInLastResult);
+ const snapshot = DB.getSnapshot();
+
+ snapshot.results.push(TestLogic.notSignedInLastResult);
+
+ DB.setSnapshot(snapshot);
}
});
PageController.change("account");
diff --git a/frontend/src/scripts/controllers/input-controller.js b/frontend/src/scripts/controllers/input-controller.js
index 9d81e7bda..10418c5ab 100644
--- a/frontend/src/scripts/controllers/input-controller.js
+++ b/frontend/src/scripts/controllers/input-controller.js
@@ -523,8 +523,9 @@ function handleChar(char, charIndex) {
}
}
- let activeWordTopBeforeJump = document.querySelector("#words .word.active")
- .offsetTop;
+ let activeWordTopBeforeJump = document.querySelector(
+ "#words .word.active"
+ ).offsetTop;
TestUI.updateWordElement();
if (!Config.hideExtraLetters) {
diff --git a/frontend/src/scripts/controllers/tag-controller.js b/frontend/src/scripts/controllers/tag-controller.js
index 5fdf0b6a8..11de721e0 100644
--- a/frontend/src/scripts/controllers/tag-controller.js
+++ b/frontend/src/scripts/controllers/tag-controller.js
@@ -22,19 +22,31 @@ export function saveActiveToLocalStorage() {
}
export function clear(nosave = false) {
- DB.getSnapshot().tags.forEach((tag) => {
+ const snapshot = DB.getSnapshot();
+
+ snapshot.tags = snapshot.tags.map((tag) => {
tag.active = false;
+
+ return tag;
});
+
+ DB.setSnapshot(snapshot);
ModesNotice.update();
if (!nosave) saveActiveToLocalStorage();
}
export function set(tagid, state, nosave = false) {
- DB.getSnapshot().tags.forEach((tag) => {
+ const snapshot = DB.getSnapshot();
+
+ snapshot.tags = snapshot.tags.map((tag) => {
if (tag._id === tagid) {
tag.active = state;
}
+
+ return tag;
});
+
+ DB.setSnapshot(snapshot);
ModesNotice.update();
if (!nosave) saveActiveToLocalStorage();
}
diff --git a/frontend/src/scripts/controllers/verification-controller.js b/frontend/src/scripts/controllers/verification-controller.js
index 548b9df35..353b3589a 100644
--- a/frontend/src/scripts/controllers/verification-controller.js
+++ b/frontend/src/scripts/controllers/verification-controller.js
@@ -27,7 +27,11 @@ export async function verify(user) {
Notifications.add(response.data.message);
} else {
Notifications.add("Accounts linked", 1);
- DB.getSnapshot().discordId = response.data.did;
+ const snapshot = DB.getSnapshot();
+
+ snapshot.discordId = response.data.did;
+
+ DB.setSnapshot(snapshot);
Settings.updateDiscordSection();
}
}
diff --git a/frontend/src/scripts/db.js b/frontend/src/scripts/db.ts
similarity index 57%
rename from frontend/src/scripts/db.js
rename to frontend/src/scripts/db.ts
index 4f97987e0..07b89e041 100644
--- a/frontend/src/scripts/db.js
+++ b/frontend/src/scripts/db.ts
@@ -3,20 +3,22 @@ import * as Notifications from "./elements/notifications";
import axiosInstance from "./axios-instance";
import * as LoadingPage from "./pages/loading";
-let dbSnapshot = null;
+let dbSnapshot: MonkeyTypes.Snapshot;
-export function updateName(uid, name) {
+export function updateName(uid: string, name: string): void {
//TODO update
axiosInstance.patch("/user/name", {
name,
});
+
+ name = uid; // this is just so that typescript is happy; Remove once this function is updated.
}
-export function getSnapshot() {
+export function getSnapshot(): MonkeyTypes.Snapshot {
return dbSnapshot;
}
-export function setSnapshot(newSnapshot) {
+export function setSnapshot(newSnapshot: MonkeyTypes.Snapshot): void {
try {
delete newSnapshot.banned;
} catch {}
@@ -26,11 +28,19 @@ export function setSnapshot(newSnapshot) {
dbSnapshot = newSnapshot;
}
-export async function initSnapshot() {
+export async function initSnapshot(): Promise<
+ MonkeyTypes.Snapshot | number | boolean
+> {
//send api request with token that returns tags, presets, and data needed for snap
- let defaultSnap = {
+ const defaultSnap: MonkeyTypes.Snapshot = {
results: undefined,
- personalBests: {},
+ personalBests: {
+ time: {},
+ words: {},
+ zen: { zen: [] },
+ quote: { custom: [] },
+ custom: { custom: [] },
+ },
name: undefined,
presets: [],
tags: [],
@@ -38,7 +48,7 @@ export async function initSnapshot() {
banned: undefined,
verified: undefined,
emailVerified: undefined,
- lbMemory: {},
+ lbMemory: { time: { 15: { english: 0 }, 60: { english: 0 } } },
globalStats: {
time: 0,
started: 0,
@@ -47,7 +57,7 @@ export async function initSnapshot() {
quoteRatings: undefined,
quoteMod: false,
};
- let snap = defaultSnap;
+ const snap = defaultSnap;
try {
if (firebase.auth().currentUser == null) return false;
// if (ActivePage.get() == "loading") {
@@ -56,16 +66,16 @@ export async function initSnapshot() {
// LoadingPage.updateBar(16);
// }
// LoadingPage.updateText("Downloading user...");
- let promises = await Promise.all([
+ const promises = await Promise.all([
axiosInstance.get("/user"),
axiosInstance.get("/config"),
axiosInstance.get("/user/tags"),
axiosInstance.get("/presets"),
]);
- let userData = promises[0].data;
- let configData = promises[1].data;
- let tagsData = promises[2].data;
- let presetsData = promises[3].data;
+ const userData = promises[0].data;
+ const configData = promises[1].data;
+ const tagsData = promises[2].data;
+ const presetsData = promises[3].data;
snap.name = userData.name;
snap.personalBests = userData.personalBests;
@@ -84,7 +94,7 @@ export async function initSnapshot() {
if (userData.lbMemory?.time15 || userData.lbMemory?.time60) {
//old memory format
- snap.lbMemory = {};
+ snap.lbMemory = {} as MonkeyTypes.LeaderboardMemory;
} else if (userData.lbMemory) {
snap.lbMemory = userData.lbMemory;
}
@@ -104,7 +114,7 @@ export async function initSnapshot() {
// }
// LoadingPage.updateText("Downloading tags...");
snap.tags = tagsData;
- snap.tags = snap.tags.sort((a, b) => {
+ snap.tags = snap.tags?.sort((a, b) => {
if (a.name > b.name) {
return 1;
} else if (a.name < b.name) {
@@ -120,7 +130,7 @@ export async function initSnapshot() {
// }
// LoadingPage.updateText("Downloading presets...");
snap.presets = presetsData;
- snap.presets = snap.presets.sort((a, b) => {
+ snap.presets = snap.presets?.sort((a, b) => {
if (a.name > b.name) {
return 1;
} else if (a.name < b.name) {
@@ -138,8 +148,8 @@ export async function initSnapshot() {
}
}
-export async function getUserResults() {
- let user = firebase.auth().currentUser;
+export async function getUserResults(): Promise {
+ const user = firebase.auth().currentUser;
if (user == null) return false;
if (dbSnapshot === null) return false;
if (dbSnapshot.results !== undefined) {
@@ -148,8 +158,11 @@ export async function getUserResults() {
try {
LoadingPage.updateText("Downloading results...");
LoadingPage.updateBar(90);
- let results = await axiosInstance.get("/results");
- results.data.forEach((result) => {
+ const resultsData = await axiosInstance.get("/results");
+
+ let results = resultsData.data as MonkeyTypes.Result[];
+
+ results.forEach((result) => {
if (result.bailedOut === undefined) result.bailedOut = false;
if (result.blindMode === undefined) result.blindMode = false;
if (result.lazyMode === undefined) result.lazyMode = false;
@@ -160,12 +173,10 @@ export async function getUserResults() {
if (result.numbers === undefined) result.numbers = false;
if (result.punctuation === undefined) result.punctuation = false;
});
- results.data = results.data.sort((a, b) => {
- return a.timestamp < b.timestamp;
- });
- dbSnapshot.results = results.data;
+ results = results.sort((a, b) => b.timestamp - a.timestamp);
+ dbSnapshot.results = results;
return true;
- } catch (e) {
+ } catch (e: any) {
Notifications.add("Error getting results: " + e.message, -1);
return false;
}
@@ -208,17 +219,18 @@ export async function getUserResults() {
*/
}
-export async function getUserHighestWpm(
- mode,
- mode2,
- punctuation,
- language,
- difficulty,
- lazyMode
-) {
- function cont() {
+export async function getUserHighestWpm(
+ mode: M,
+ mode2: MonkeyTypes.Mode2,
+ punctuation: boolean,
+ language: string,
+ difficulty: MonkeyTypes.Difficulty,
+ lazyMode: boolean
+): Promise {
+ function cont(): number {
let topWpm = 0;
- dbSnapshot.results.forEach((result) => {
+
+ dbSnapshot.results?.forEach((result) => {
if (
result.mode == mode &&
result.mode2 == mode2 &&
@@ -236,25 +248,22 @@ export async function getUserHighestWpm(
return topWpm;
}
- let retval;
- if (dbSnapshot == null || dbSnapshot.results === undefined) {
- retval = 0;
- } else {
- retval = cont();
- }
+ const retval =
+ dbSnapshot === null || dbSnapshot.results === undefined ? 0 : cont();
+
return retval;
}
-export async function getUserAverageWpm10(
- mode,
- mode2,
- punctuation,
- language,
- difficulty,
- lazyMode
-) {
- function cont() {
- let activeTagIds = [];
+export async function getUserAverageWpm10(
+ mode: M,
+ mode2: MonkeyTypes.Mode2,
+ punctuation: boolean,
+ language: string,
+ difficulty: MonkeyTypes.Difficulty,
+ lazyMode: boolean
+): Promise {
+ function cont(): number {
+ const activeTagIds: string[] = [];
getSnapshot()?.tags?.forEach((tag) => {
if (tag.active === true) {
activeTagIds.push(tag._id);
@@ -266,7 +275,7 @@ export async function getUserAverageWpm10(
let last10Wpm = 0;
let last10Count = 0;
// You have to use every so you can break out of the loop
- dbSnapshot.results.every((result) => {
+ dbSnapshot.results?.every((result) => {
if (
result.mode == mode &&
result.punctuation == punctuation &&
@@ -311,34 +320,35 @@ export async function getUserAverageWpm10(
return Math.round(wpmSum / count);
}
- let retval = 0;
+ const retval =
+ dbSnapshot === null || (await getUserResults()) === false ? 0 : cont();
- if (dbSnapshot == null) return retval;
- let dbSnapshotValid = await getUserResults();
- if (dbSnapshotValid === false) {
- return retval;
- }
- retval = cont();
return retval;
}
-export async function getLocalPB(
- mode,
- mode2,
- punctuation,
- language,
- difficulty,
- lazyMode,
- funbox
-) {
+export async function getLocalPB(
+ mode: M,
+ mode2: MonkeyTypes.Mode2,
+ punctuation: boolean,
+ language: string,
+ difficulty: MonkeyTypes.Difficulty,
+ lazyMode: boolean,
+ funbox: string
+): Promise {
if (funbox !== "none" && funbox !== "plus_one" && funbox !== "plus_two") {
return 0;
}
- function cont() {
+ function cont(): number {
let ret = 0;
try {
- dbSnapshot.personalBests[mode][mode2].forEach((pb) => {
+ if (!dbSnapshot.personalBests) return ret;
+
+ (
+ dbSnapshot.personalBests[mode][
+ mode2
+ ] as unknown as MonkeyTypes.PersonalBest[]
+ ).forEach((pb) => {
if (
pb.punctuation == punctuation &&
pb.difficulty == difficulty &&
@@ -349,43 +359,61 @@ export async function getLocalPB(
ret = pb.wpm;
}
});
+
return ret;
} catch (e) {
return ret;
}
}
- let retval;
- if (dbSnapshot == null) {
- retval = 0;
- } else {
- retval = cont();
- }
+ const retval = dbSnapshot === null ? 0 : cont();
+
return retval;
}
-export async function saveLocalPB(
- mode,
- mode2,
- punctuation,
- language,
- difficulty,
- lazyMode,
- wpm,
- acc,
- raw,
- consistency
-) {
+export async function saveLocalPB(
+ mode: M,
+ mode2: MonkeyTypes.Mode2,
+ punctuation: boolean,
+ language: string,
+ difficulty: MonkeyTypes.Difficulty,
+ lazyMode: boolean,
+ wpm: number,
+ acc: number,
+ raw: number,
+ consistency: number
+): Promise {
if (mode == "quote") return;
- function cont() {
+ function cont(): void {
let found = false;
- if (dbSnapshot.personalBests === undefined) dbSnapshot.personalBests = {};
- if (dbSnapshot.personalBests[mode] === undefined)
- dbSnapshot.personalBests[mode] = {};
- if (dbSnapshot.personalBests[mode][mode2] === undefined)
- dbSnapshot.personalBests[mode][mode2] = [];
+ if (dbSnapshot.personalBests === undefined)
+ dbSnapshot.personalBests = {
+ time: {},
+ words: {},
+ zen: { zen: [] },
+ quote: { custom: [] },
+ custom: { custom: [] },
+ };
- dbSnapshot.personalBests[mode][mode2].forEach((pb) => {
+ if (dbSnapshot.personalBests[mode] === undefined) {
+ if (mode === "zen") {
+ dbSnapshot.personalBests["zen"] = { zen: [] };
+ } else {
+ dbSnapshot.personalBests[mode as Exclude] = {
+ custom: [],
+ };
+ }
+ }
+
+ if (dbSnapshot.personalBests[mode][mode2] === undefined)
+ dbSnapshot.personalBests[mode][mode2] =
+ [] as unknown as MonkeyTypes.PersonalBests[M][keyof MonkeyTypes.PersonalBests[M]];
+
+ (
+ dbSnapshot.personalBests[mode][
+ mode2
+ ] as unknown as MonkeyTypes.PersonalBest[]
+ ).forEach((pb) => {
if (
pb.punctuation == punctuation &&
pb.difficulty == difficulty &&
@@ -404,7 +432,11 @@ export async function saveLocalPB(
});
if (!found) {
//nothing found
- dbSnapshot.personalBests[mode][mode2].push({
+ (
+ dbSnapshot.personalBests[mode][
+ mode2
+ ] as unknown as MonkeyTypes.PersonalBest[]
+ ).push({
language: language,
difficulty: difficulty,
lazyMode: lazyMode,
@@ -423,20 +455,39 @@ export async function saveLocalPB(
}
}
-export async function getLocalTagPB(
- tagId,
- mode,
- mode2,
- punctuation,
- language,
- difficulty,
- lazyMode
-) {
- function cont() {
+export async function getLocalTagPB(
+ tagId: string,
+ mode: M,
+ mode2: MonkeyTypes.Mode2,
+ punctuation: boolean,
+ language: string,
+ difficulty: MonkeyTypes.Difficulty,
+ lazyMode: boolean
+): Promise {
+ function cont(): number {
let ret = 0;
- let filteredtag = dbSnapshot.tags.filter((t) => t._id === tagId)[0];
+
+ const filteredtag = (getSnapshot().tags ?? []).filter(
+ (t) => t._id === tagId
+ )[0];
+
+ if (filteredtag === undefined) return ret;
+
+ if (filteredtag.personalBests === undefined) {
+ filteredtag.personalBests = {
+ time: {},
+ words: {},
+ zen: { zen: [] },
+ quote: { custom: [] },
+ custom: { custom: [] },
+ };
+ }
+
try {
- filteredtag.personalBests[mode][mode2].forEach((pb) => {
+ const personalBests = (filteredtag.personalBests[mode][mode2] ??
+ []) as MonkeyTypes.PersonalBest[];
+
+ personalBests.forEach((pb) => {
if (
pb.punctuation == punctuation &&
pb.difficulty == difficulty &&
@@ -453,37 +504,51 @@ export async function getLocalTagPB(
return ret;
}
- let retval;
- if (dbSnapshot == null) {
- retval = 0;
- } else {
- retval = cont();
- }
+ const retval = dbSnapshot === null ? 0 : cont();
+
return retval;
}
-export async function saveLocalTagPB(
- tagId,
- mode,
- mode2,
- punctuation,
- language,
- difficulty,
- lazyMode,
- wpm,
- acc,
- raw,
- consistency
-) {
+export async function saveLocalTagPB(
+ tagId: string,
+ mode: M,
+ mode2: MonkeyTypes.Mode2,
+ punctuation: boolean,
+ language: string,
+ difficulty: MonkeyTypes.Difficulty,
+ lazyMode: boolean,
+ wpm: number,
+ acc: number,
+ raw: number,
+ consistency: number
+): Promise {
if (mode == "quote") return;
- function cont() {
- let filteredtag = dbSnapshot.tags.filter((t) => t._id === tagId)[0];
+ function cont(): void {
+ const filteredtag = dbSnapshot.tags?.filter(
+ (t) => t._id === tagId
+ )[0] as MonkeyTypes.Tag;
+
+ if (!filteredtag.personalBests) {
+ filteredtag.personalBests = {
+ time: {},
+ words: {},
+ zen: { zen: [] },
+ quote: { custom: [] },
+ custom: { custom: [] },
+ };
+ }
+
try {
let found = false;
if (filteredtag.personalBests[mode][mode2] === undefined) {
- filteredtag.personalBests[mode][mode2] = [];
+ filteredtag.personalBests[mode][mode2] =
+ [] as unknown as MonkeyTypes.PersonalBests[M][keyof MonkeyTypes.PersonalBests[M]];
}
- filteredtag.personalBests[mode][mode2].forEach((pb) => {
+ (
+ filteredtag.personalBests[mode][
+ mode2
+ ] as unknown as MonkeyTypes.PersonalBest[]
+ ).forEach((pb) => {
if (
pb.punctuation == punctuation &&
pb.difficulty == difficulty &&
@@ -502,7 +567,11 @@ export async function saveLocalTagPB(
});
if (!found) {
//nothing found
- filteredtag.personalBests[mode][mode2].push({
+ (
+ filteredtag.personalBests[mode][
+ mode2
+ ] as unknown as MonkeyTypes.PersonalBest[]
+ ).push({
language: language,
difficulty: difficulty,
lazyMode: lazyMode,
@@ -516,8 +585,20 @@ export async function saveLocalTagPB(
}
} catch (e) {
//that mode or mode2 is not found
- filteredtag.personalBests = {};
- filteredtag.personalBests[mode] = {};
+ filteredtag.personalBests = {
+ time: {},
+ words: {},
+ zen: { zen: [] },
+ quote: { custom: [] },
+ custom: { custom: [] },
+ };
+ if (mode === "zen") {
+ filteredtag.personalBests["zen"] = { zen: [] };
+ } else {
+ filteredtag.personalBests[mode as Exclude] = {
+ custom: [],
+ };
+ }
filteredtag.personalBests[mode][mode2] = [
{
language: language,
@@ -530,42 +611,63 @@ export async function saveLocalTagPB(
timestamp: Date.now(),
consistency: consistency,
},
- ];
+ ] as unknown as MonkeyTypes.PersonalBests[M][keyof MonkeyTypes.PersonalBests[M]];
}
}
if (dbSnapshot != null) {
cont();
}
+
+ return;
}
-export function updateLbMemory(mode, mode2, language, rank, api = false) {
+export function updateLbMemory(
+ mode: M,
+ mode2: MonkeyTypes.Mode2,
+ language: string,
+ rank: number,
+ api = false
+): void {
//could dbSnapshot just be used here instead of getSnapshot()
- if (dbSnapshot.lbMemory === undefined) dbSnapshot.lbMemory = {};
- if (dbSnapshot.lbMemory[mode] === undefined) dbSnapshot.lbMemory[mode] = {};
- if (dbSnapshot.lbMemory[mode][mode2] === undefined)
- dbSnapshot.lbMemory[mode][mode2] = {};
- let current = dbSnapshot.lbMemory[mode][mode2][language];
- dbSnapshot.lbMemory[mode][mode2][language] = rank;
- if (api && current != rank) {
- axiosInstance.patch("/user/leaderboardMemory", {
- mode,
- mode2,
- language,
- rank,
- });
+
+ if (mode === "time") {
+ const timeMode = mode as "time",
+ timeMode2 = mode2 as 15 | 60;
+
+ const snapshot = getSnapshot();
+ if (snapshot.lbMemory === undefined)
+ snapshot.lbMemory = { time: { 15: { english: 0 }, 60: { english: 0 } } };
+ if (snapshot.lbMemory[timeMode] === undefined)
+ snapshot.lbMemory[timeMode] = {
+ 15: { english: 0 },
+ 60: { english: 0 },
+ };
+ if (snapshot.lbMemory[timeMode][timeMode2] === undefined)
+ snapshot.lbMemory[timeMode][timeMode2] = {};
+ const current = snapshot.lbMemory[timeMode][timeMode2][language];
+ snapshot.lbMemory[timeMode][timeMode2][language] = rank;
+ if (api && current != rank) {
+ axiosInstance.patch("/user/leaderboardMemory", {
+ mode,
+ mode2,
+ language,
+ rank,
+ });
+ }
+ setSnapshot(snapshot);
}
}
-export async function saveConfig(config) {
+export async function saveConfig(config: MonkeyTypes.Config): Promise {
if (firebase.auth().currentUser !== null) {
AccountButton.loading(true);
try {
await axiosInstance.post("/config/save", { config });
- } catch (e) {
+ } catch (e: any) {
AccountButton.loading(false);
- let msg = e?.response?.data?.message ?? e.message;
+ const msg = e?.response?.data?.message ?? e.message;
Notifications.add("Failed to save config: " + msg, -1);
return;
}
@@ -573,30 +675,41 @@ export async function saveConfig(config) {
}
}
-export function saveLocalResult(result) {
- if (getSnapshot() !== null && getSnapshot().results !== undefined) {
- getSnapshot().results.unshift(result);
+export function saveLocalResult(
+ result: MonkeyTypes.Result
+): void {
+ const snapshot = getSnapshot();
+
+ if (snapshot !== null && snapshot.results !== undefined) {
+ snapshot.results.unshift(result);
+
+ setSnapshot(snapshot);
}
}
-export function updateLocalStats(stats) {
- if (getSnapshot() !== null) {
- if (getSnapshot().globalStats.time == undefined) {
- getSnapshot().globalStats.time = stats.time;
+export function updateLocalStats(stats: MonkeyTypes.Stats): void {
+ const snapshot = getSnapshot();
+ if (snapshot.globalStats === undefined)
+ snapshot.globalStats = {} as MonkeyTypes.Stats;
+ if (snapshot !== null && snapshot.globalStats !== undefined) {
+ if (snapshot.globalStats.time == undefined) {
+ snapshot.globalStats.time = stats.time;
} else {
- getSnapshot().globalStats.time += stats.time;
+ snapshot.globalStats.time += stats.time;
}
- if (getSnapshot().globalStats.started == undefined) {
- getSnapshot().globalStats.started = stats.started;
+ if (snapshot.globalStats.started == undefined) {
+ snapshot.globalStats.started = stats.started;
} else {
- getSnapshot().globalStats.started += stats.started;
+ snapshot.globalStats.started += stats.started;
}
- if (getSnapshot().globalStats.completed == undefined) {
- getSnapshot().globalStats.completed = 1;
+ if (snapshot.globalStats.completed == undefined) {
+ snapshot.globalStats.completed = 1;
} else {
- getSnapshot().globalStats.completed += 1;
+ snapshot.globalStats.completed += 1;
}
}
+
+ setSnapshot(snapshot);
}
// export async function DB.getLocalTagPB(tagId) {
@@ -613,10 +726,8 @@ export function updateLocalStats(stats) {
// }
// }
-// let retval;
-// if (dbSnapshot != null) {
-// retval = cont();
-// }
+// const retval = dbSnapshot !== null ? cont() : undefined;
+
// return retval;
// }
diff --git a/frontend/src/scripts/elements/commandline-lists.ts b/frontend/src/scripts/elements/commandline-lists.ts
index 90b937a7b..691a4e2f1 100644
--- a/frontend/src/scripts/elements/commandline-lists.ts
+++ b/frontend/src/scripts/elements/commandline-lists.ts
@@ -212,7 +212,7 @@ const commandsTags: MonkeyTypes.CommandsGroup = {
};
export function updateTagCommands(): void {
- if (DB.getSnapshot()?.tags?.length > 0) {
+ if (DB.getSnapshot()?.tags?.length ?? 0 > 0) {
commandsTags.list = [];
commandsTags.list.push({
@@ -220,15 +220,21 @@ export function updateTagCommands(): void {
display: `Clear tags`,
icon: "fa-times",
exec: (): void => {
- DB.getSnapshot().tags.forEach((tag: MonkeyTypes.Tag) => {
+ const snapshot = DB.getSnapshot();
+
+ snapshot.tags = snapshot.tags?.map((tag) => {
tag.active = false;
+
+ return tag;
});
+
+ DB.setSnapshot(snapshot);
ModesNotice.update();
TagController.saveActiveToLocalStorage();
},
});
- DB.getSnapshot().tags.forEach((tag: MonkeyTypes.Tag) => {
+ DB.getSnapshot().tags?.forEach((tag) => {
let dis = tag.name;
if (tag.active === true) {
@@ -283,10 +289,12 @@ const commandsPresets: MonkeyTypes.CommandsGroup = {
};
export function updatePresetCommands(): void {
- if (DB.getSnapshot()?.presets?.length > 0) {
+ const snapshot = DB.getSnapshot();
+
+ if (snapshot.presets !== undefined && snapshot.presets.length > 0) {
commandsPresets.list = [];
- DB.getSnapshot().presets.forEach((preset: MonkeyTypes.Preset) => {
+ snapshot.presets.forEach((preset: MonkeyTypes.Preset) => {
const dis = preset.name;
commandsPresets.list.push({
@@ -1655,7 +1663,7 @@ const commandsTimerColor: MonkeyTypes.CommandsGroup = {
display: "black",
configValue: "black",
exec: (): void => {
- UpdateConfig.setTimerColor("bar");
+ UpdateConfig.setTimerColor("black");
},
},
{
@@ -1740,7 +1748,7 @@ const commandsTimerOpacity: MonkeyTypes.CommandsGroup = {
display: ".25",
configValue: 0.25,
exec: (): void => {
- UpdateConfig.setTimerOpacity(0.25);
+ UpdateConfig.setTimerOpacity("0.25");
},
},
{
@@ -1748,7 +1756,7 @@ const commandsTimerOpacity: MonkeyTypes.CommandsGroup = {
display: ".5",
configValue: 0.5,
exec: (): void => {
- UpdateConfig.setTimerOpacity(0.5);
+ UpdateConfig.setTimerOpacity("0.5");
},
},
{
@@ -1756,7 +1764,7 @@ const commandsTimerOpacity: MonkeyTypes.CommandsGroup = {
display: ".75",
configValue: 0.75,
exec: (): void => {
- UpdateConfig.setTimerOpacity(0.75);
+ UpdateConfig.setTimerOpacity("0.75");
},
},
{
@@ -1764,7 +1772,7 @@ const commandsTimerOpacity: MonkeyTypes.CommandsGroup = {
display: "1",
configValue: 1,
exec: (): void => {
- UpdateConfig.setTimerOpacity(1);
+ UpdateConfig.setTimerOpacity("1");
},
},
],
@@ -1780,7 +1788,7 @@ const commandsWordCount: MonkeyTypes.CommandsGroup = {
configValue: 10,
exec: (): void => {
UpdateConfig.setMode("words");
- UpdateConfig.setWordCount("10");
+ UpdateConfig.setWordCount(10);
TestLogic.restart();
},
},
@@ -1790,7 +1798,7 @@ const commandsWordCount: MonkeyTypes.CommandsGroup = {
configValue: 25,
exec: (): void => {
UpdateConfig.setMode("words");
- UpdateConfig.setWordCount("25");
+ UpdateConfig.setWordCount(25);
TestLogic.restart();
},
},
@@ -1800,7 +1808,7 @@ const commandsWordCount: MonkeyTypes.CommandsGroup = {
configValue: 50,
exec: (): void => {
UpdateConfig.setMode("words");
- UpdateConfig.setWordCount("50");
+ UpdateConfig.setWordCount(50);
TestLogic.restart();
},
},
@@ -1810,7 +1818,7 @@ const commandsWordCount: MonkeyTypes.CommandsGroup = {
configValue: 100,
exec: (): void => {
UpdateConfig.setMode("words");
- UpdateConfig.setWordCount("100");
+ UpdateConfig.setWordCount(100);
TestLogic.restart();
},
},
@@ -1820,7 +1828,7 @@ const commandsWordCount: MonkeyTypes.CommandsGroup = {
configValue: 200,
exec: (): void => {
UpdateConfig.setMode("words");
- UpdateConfig.setWordCount("200");
+ UpdateConfig.setWordCount(200);
TestLogic.restart();
},
},
@@ -2057,7 +2065,7 @@ const commandsTimeConfig: MonkeyTypes.CommandsGroup = {
configValue: 15,
exec: (): void => {
UpdateConfig.setMode("time");
- UpdateConfig.setTimeConfig("15");
+ UpdateConfig.setTimeConfig(15);
TestLogic.restart();
},
},
@@ -2067,7 +2075,7 @@ const commandsTimeConfig: MonkeyTypes.CommandsGroup = {
configValue: 30,
exec: (): void => {
UpdateConfig.setMode("time");
- UpdateConfig.setTimeConfig("30");
+ UpdateConfig.setTimeConfig(30);
TestLogic.restart();
},
},
@@ -2077,7 +2085,7 @@ const commandsTimeConfig: MonkeyTypes.CommandsGroup = {
configValue: 60,
exec: (): void => {
UpdateConfig.setMode("time");
- UpdateConfig.setTimeConfig("60");
+ UpdateConfig.setTimeConfig(60);
TestLogic.restart();
},
},
@@ -2087,7 +2095,7 @@ const commandsTimeConfig: MonkeyTypes.CommandsGroup = {
configValue: 120,
exec: (): void => {
UpdateConfig.setMode("time");
- UpdateConfig.setTimeConfig("120");
+ UpdateConfig.setTimeConfig(120);
TestLogic.restart();
},
},
diff --git a/frontend/src/scripts/elements/commandline.ts b/frontend/src/scripts/elements/commandline.ts
index 5c97f8ce6..dcca80fd5 100644
--- a/frontend/src/scripts/elements/commandline.ts
+++ b/frontend/src/scripts/elements/commandline.ts
@@ -320,7 +320,7 @@ function useSingleListCommandLine(sshow = true): void {
// } else if (Config.singleListCommandLine == "on") {
CommandlineLists.setCurrent([allCommands]);
// }
- if (Config.singleListCommandLine != "off")
+ if (Config.singleListCommandLine != "manual")
$("#commandLine").addClass("allCommands");
if (sshow) show();
}
diff --git a/frontend/src/scripts/elements/custom-background-filter.ts b/frontend/src/scripts/elements/custom-background-filter.ts
index 5bebb1791..b396a9089 100644
--- a/frontend/src/scripts/elements/custom-background-filter.ts
+++ b/frontend/src/scripts/elements/custom-background-filter.ts
@@ -117,17 +117,16 @@ $(".section.customBackgroundFilter .opacity input").on("input", () => {
});
$(".section.customBackgroundFilter .save.button").click(() => {
- const arr: number[] = [];
- Object.keys(filters).forEach((filterKey) => {
- arr.push(filters[filterKey as keyof typeof filters].value);
- });
+ const arr = Object.keys(filters).map(
+ (filterKey) => filters[filterKey as keyof typeof filters].value
+ ) as MonkeyTypes.CustomBackgroundFilter;
UpdateConfig.setCustomBackgroundFilter(arr, false);
Notifications.add("Custom background filters saved", 1);
});
ConfigEvent.subscribe((eventKey, eventValue) => {
if (eventKey === "customBackgroundFilter") {
- loadConfig(((eventValue as unknown) as any[]).map((ev) => parseFloat(ev)));
+ loadConfig((eventValue as unknown as any[]).map((ev) => parseFloat(ev)));
apply();
}
});
diff --git a/frontend/src/scripts/elements/leaderboards.ts b/frontend/src/scripts/elements/leaderboards.ts
index c7a9d9633..01131ccea 100644
--- a/frontend/src/scripts/elements/leaderboards.ts
+++ b/frontend/src/scripts/elements/leaderboards.ts
@@ -70,9 +70,9 @@ function updateTimerElement(): void {
function startTimer(): void {
updateTimerElement();
- updateTimer = (setInterval(() => {
+ updateTimer = setInterval(() => {
updateTimerElement();
- }, 1000) as unknown) as number;
+ }, 1000) as unknown as number;
}
function showLoader(lb: number): void {
@@ -152,7 +152,7 @@ function checkLbMemory(lb: LbKey): void {
side = "right";
}
- const memory = DB.getSnapshot()?.lbMemory?.time?.[lb]?.english;
+ const memory = DB.getSnapshot()?.lbMemory?.time?.[lb]?.["english"];
if (memory && currentRank[lb]) {
const difference = memory - currentRank[lb].rank;
diff --git a/frontend/src/scripts/elements/modes-notice.ts b/frontend/src/scripts/elements/modes-notice.ts
index 385e30a6b..cc8b48117 100644
--- a/frontend/src/scripts/elements/modes-notice.ts
+++ b/frontend/src/scripts/elements/modes-notice.ts
@@ -169,7 +169,7 @@ export function update(): void {
let tagsString = "";
try {
- DB.getSnapshot().tags.forEach((tag: MonkeyTypes.Tag) => {
+ DB.getSnapshot().tags?.forEach((tag) => {
if (tag.active === true) {
tagsString += tag.name + ", ";
}
diff --git a/frontend/src/scripts/elements/monkey-power.ts b/frontend/src/scripts/elements/monkey-power.ts
index 58f9f0830..0efabaa80 100644
--- a/frontend/src/scripts/elements/monkey-power.ts
+++ b/frontend/src/scripts/elements/monkey-power.ts
@@ -212,7 +212,7 @@ export async function addPower(good = true, extra = false): Promise {
`translate(${shake[0]}px, ${shake[1]}px)`
);
if (ctx.resetTimeOut) clearTimeout(ctx.resetTimeOut);
- ctx.resetTimeOut = (setTimeout(reset, 2000) as unknown) as number;
+ ctx.resetTimeOut = setTimeout(reset, 2000) as unknown as number;
}
// Sparks
diff --git a/frontend/src/scripts/misc.ts b/frontend/src/scripts/misc.ts
index c1d43edda..600bd7a39 100644
--- a/frontend/src/scripts/misc.ts
+++ b/frontend/src/scripts/misc.ts
@@ -6,21 +6,24 @@ export function getuid(): void {
console.error("Only share this uid with Miodec and nobody else!");
}
-function hexToHSL(
- hex: string
-): { hue: number; sat: number; lgt: number; string: string } {
+function hexToHSL(hex: string): {
+ hue: number;
+ sat: number;
+ lgt: number;
+ string: string;
+} {
// Convert hex to RGB first
let r: number;
let g: number;
let b: number;
if (hex.length == 4) {
- r = (("0x" + hex[1] + hex[1]) as unknown) as number;
- g = (("0x" + hex[2] + hex[2]) as unknown) as number;
- b = (("0x" + hex[3] + hex[3]) as unknown) as number;
+ r = ("0x" + hex[1] + hex[1]) as unknown as number;
+ g = ("0x" + hex[2] + hex[2]) as unknown as number;
+ b = ("0x" + hex[3] + hex[3]) as unknown as number;
} else if (hex.length == 7) {
- r = (("0x" + hex[1] + hex[2]) as unknown) as number;
- g = (("0x" + hex[3] + hex[4]) as unknown) as number;
- b = (("0x" + hex[5] + hex[6]) as unknown) as number;
+ r = ("0x" + hex[1] + hex[2]) as unknown as number;
+ g = ("0x" + hex[3] + hex[4]) as unknown as number;
+ b = ("0x" + hex[5] + hex[6]) as unknown as number;
} else {
r = 0x00;
g = 0x00;
diff --git a/frontend/src/scripts/observables/config-event.ts b/frontend/src/scripts/observables/config-event.ts
index c3a86c3a5..424e8d9a8 100644
--- a/frontend/src/scripts/observables/config-event.ts
+++ b/frontend/src/scripts/observables/config-event.ts
@@ -1,12 +1,12 @@
-type SubscribeFunction = (key: string, value?: string, value2?: string) => void;
+type SubscribeFunction = (key: string, value?: V, value2?: V2) => void;
-const subscribers: SubscribeFunction[] = [];
+const subscribers: SubscribeFunction[] = [];
-export function subscribe(fn: SubscribeFunction): void {
+export function subscribe(fn: SubscribeFunction): void {
subscribers.push(fn);
}
-export function dispatch(key: string, value: string, value2: string): void {
+export function dispatch(key: string, value?: V, value2?: V2): void {
subscribers.forEach((fn) => {
try {
fn(key, value, value2);
diff --git a/frontend/src/scripts/pages/account.ts b/frontend/src/scripts/pages/account.ts
index 983f1ab53..1f13014ee 100644
--- a/frontend/src/scripts/pages/account.ts
+++ b/frontend/src/scripts/pages/account.ts
@@ -23,7 +23,7 @@ export function toggleFilterDebug(): void {
}
}
-let filteredResults: MonkeyTypes.Result[] = [];
+let filteredResults: MonkeyTypes.Result[] = [];
let visibleTableLines = 0;
function loadMoreLines(lineIndex?: number): void {
@@ -102,7 +102,7 @@ function loadMoreLines(lineIndex?: number): void {
if (result.tags !== undefined && result.tags.length > 0) {
result.tags.forEach((tag) => {
- DB.getSnapshot().tags.forEach((snaptag: MonkeyTypes.Tag) => {
+ DB.getSnapshot().tags?.forEach((snaptag) => {
if (tag === snaptag._id) {
tagNames += snaptag.name + ", ";
}
@@ -258,323 +258,332 @@ export function update(): void {
filteredResults = [];
$(".pageAccount .history table tbody").empty();
- DB.getSnapshot().results.forEach((result: MonkeyTypes.Result) => {
- // totalSeconds += tt;
+ DB.getSnapshot().results?.forEach(
+ (result: MonkeyTypes.Result) => {
+ // totalSeconds += tt;
- //apply filters
- try {
- let resdiff = result.difficulty;
- if (resdiff == undefined) {
- resdiff = "normal";
- }
- if (!ResultFilters.getFilter("difficulty", resdiff)) {
- if (filterDebug)
- console.log(`skipping result due to difficulty filter`, result);
- return;
- }
- if (!ResultFilters.getFilter("mode", result.mode)) {
- if (filterDebug)
- console.log(`skipping result due to mode filter`, result);
- return;
- }
-
- if (result.mode == "time") {
- let timefilter = "custom";
- if ([15, 30, 60, 120].includes(parseInt(result.mode2 as string))) {
- timefilter = result.mode2.toString();
+ //apply filters
+ try {
+ let resdiff = result.difficulty;
+ if (resdiff == undefined) {
+ resdiff = "normal";
}
- if (!ResultFilters.getFilter("time", timefilter)) {
+ if (!ResultFilters.getFilter("difficulty", resdiff)) {
if (filterDebug)
- console.log(`skipping result due to time filter`, result);
+ console.log(`skipping result due to difficulty filter`, result);
return;
}
- } else if (result.mode == "words") {
- let wordfilter = "custom";
- if (
- [10, 25, 50, 100, 200].includes(parseInt(result.mode2 as string))
- ) {
- wordfilter = result.mode2.toString();
- }
- if (!ResultFilters.getFilter("words", wordfilter)) {
+ if (!ResultFilters.getFilter("mode", result.mode)) {
if (filterDebug)
- console.log(`skipping result due to word filter`, result);
+ console.log(`skipping result due to mode filter`, result);
return;
}
- }
- if (result.quoteLength != null) {
- let filter = null;
- if (result.quoteLength === 0) {
- filter = "short";
- } else if (result.quoteLength === 1) {
- filter = "medium";
- } else if (result.quoteLength === 2) {
- filter = "long";
- } else if (result.quoteLength === 3) {
- filter = "thicc";
- }
- if (
- filter !== null &&
- !ResultFilters.getFilter("quoteLength", filter)
- ) {
- if (filterDebug)
- console.log(`skipping result due to quoteLength filter`, result);
- return;
- }
- }
-
- let langFilter = ResultFilters.getFilter(
- "language",
- result.language ?? "english"
- );
-
- if (
- result.language === "english_expanded" &&
- ResultFilters.getFilter("language", "english_1k")
- ) {
- langFilter = true;
- }
- if (!langFilter) {
- if (filterDebug)
- console.log(`skipping result due to language filter`, result);
- return;
- }
-
- let puncfilter = "off";
- if (result.punctuation) {
- puncfilter = "on";
- }
- if (!ResultFilters.getFilter("punctuation", puncfilter)) {
- if (filterDebug)
- console.log(`skipping result due to punctuation filter`, result);
- return;
- }
-
- let numfilter = "off";
- if (result.numbers) {
- numfilter = "on";
- }
- if (!ResultFilters.getFilter("numbers", numfilter)) {
- if (filterDebug)
- console.log(`skipping result due to numbers filter`, result);
- return;
- }
-
- if (result.funbox === "none" || result.funbox === undefined) {
- if (!ResultFilters.getFilter("funbox", "none")) {
- if (filterDebug)
- console.log(`skipping result due to funbox filter`, result);
- return;
- }
- } else {
- if (!ResultFilters.getFilter("funbox", result.funbox)) {
- if (filterDebug)
- console.log(`skipping result due to funbox filter`, result);
- return;
- }
- }
-
- let tagHide = true;
- if (result.tags === undefined || result.tags.length === 0) {
- //no tags, show when no tag is enabled
- if (DB.getSnapshot().tags.length > 0) {
- if (ResultFilters.getFilter("tags", "none")) tagHide = false;
- } else {
- tagHide = false;
- }
- } else {
- //tags exist
- const validTags: string[] = DB.getSnapshot().tags.map(
- (t: MonkeyTypes.Tag) => t._id
- );
- result.tags.forEach((tag) => {
- //check if i even need to check tags anymore
- if (!tagHide) return;
- //check if tag is valid
- if (validTags.includes(tag)) {
- //tag valid, check if filter is on
- if (ResultFilters.getFilter("tags", tag)) tagHide = false;
- } else {
- //tag not found in valid tags, meaning probably deleted
- if (ResultFilters.getFilter("tags", "none")) tagHide = false;
+ if (result.mode == "time") {
+ let timefilter: MonkeyTypes.Mode2Custom<"time"> = "custom";
+ if ([15, 30, 60, 120].includes(parseInt(result.mode2 as string))) {
+ timefilter = result.mode2;
}
- });
+ if (!ResultFilters.getFilter("time", timefilter)) {
+ if (filterDebug)
+ console.log(`skipping result due to time filter`, result);
+ return;
+ }
+ } else if (result.mode == "words") {
+ let wordfilter: MonkeyTypes.Mode2Custom<"words"> = "custom";
+ if (
+ [10, 25, 50, 100, 200].includes(parseInt(result.mode2 as string))
+ ) {
+ wordfilter = result.mode2;
+ }
+ if (!ResultFilters.getFilter("words", wordfilter)) {
+ if (filterDebug)
+ console.log(`skipping result due to word filter`, result);
+ return;
+ }
+ }
+
+ if (result.quoteLength != null) {
+ let filter: MonkeyTypes.QuoteModes | undefined = undefined;
+ if (result.quoteLength === 0) {
+ filter = "short";
+ } else if (result.quoteLength === 1) {
+ filter = "medium";
+ } else if (result.quoteLength === 2) {
+ filter = "long";
+ } else if (result.quoteLength === 3) {
+ filter = "thicc";
+ }
+ if (
+ filter !== undefined &&
+ !ResultFilters.getFilter("quoteLength", filter)
+ ) {
+ if (filterDebug)
+ console.log(
+ `skipping result due to quoteLength filter`,
+ result
+ );
+ return;
+ }
+ }
+
+ let langFilter = ResultFilters.getFilter(
+ "language",
+ result.language ?? "english"
+ );
+
+ if (
+ result.language === "english_expanded" &&
+ ResultFilters.getFilter("language", "english_1k")
+ ) {
+ langFilter = true;
+ }
+ if (!langFilter) {
+ if (filterDebug)
+ console.log(`skipping result due to language filter`, result);
+ return;
+ }
+
+ let puncfilter: MonkeyTypes.Filter<"punctuation"> = "off";
+ if (result.punctuation) {
+ puncfilter = "on";
+ }
+ if (!ResultFilters.getFilter("punctuation", puncfilter)) {
+ if (filterDebug)
+ console.log(`skipping result due to punctuation filter`, result);
+ return;
+ }
+
+ let numfilter: MonkeyTypes.Filter<"numbers"> = "off";
+ if (result.numbers) {
+ numfilter = "on";
+ }
+ if (!ResultFilters.getFilter("numbers", numfilter)) {
+ if (filterDebug)
+ console.log(`skipping result due to numbers filter`, result);
+ return;
+ }
+
+ if (result.funbox === "none" || result.funbox === undefined) {
+ if (!ResultFilters.getFilter("funbox", "none")) {
+ if (filterDebug)
+ console.log(`skipping result due to funbox filter`, result);
+ return;
+ }
+ } else {
+ if (!ResultFilters.getFilter("funbox", result.funbox)) {
+ if (filterDebug)
+ console.log(`skipping result due to funbox filter`, result);
+ return;
+ }
+ }
+
+ let tagHide = true;
+ if (result.tags === undefined || result.tags.length === 0) {
+ //no tags, show when no tag is enabled
+ if (DB.getSnapshot().tags?.length || 0 > 0) {
+ if (ResultFilters.getFilter("tags", "none")) tagHide = false;
+ } else {
+ tagHide = false;
+ }
+ } else {
+ //tags exist
+ const validTags = DB.getSnapshot().tags?.map((t) => t._id);
+
+ if (validTags === undefined) return;
+
+ result.tags.forEach((tag) => {
+ //check if i even need to check tags anymore
+ if (!tagHide) return;
+ //check if tag is valid
+ if (validTags?.includes(tag)) {
+ //tag valid, check if filter is on
+ if (ResultFilters.getFilter("tags", tag)) tagHide = false;
+ } else {
+ //tag not found in valid tags, meaning probably deleted
+ if (ResultFilters.getFilter("tags", "none")) tagHide = false;
+ }
+ });
+ }
+
+ if (tagHide) {
+ if (filterDebug)
+ console.log(`skipping result due to tag filter`, result);
+ return;
+ }
+
+ const timeSinceTest = Math.abs(result.timestamp - Date.now()) / 1000;
+
+ let datehide = true;
+
+ if (
+ ResultFilters.getFilter("date", "all") ||
+ (ResultFilters.getFilter("date", "last_day") &&
+ timeSinceTest <= 86400) ||
+ (ResultFilters.getFilter("date", "last_week") &&
+ timeSinceTest <= 604800) ||
+ (ResultFilters.getFilter("date", "last_month") &&
+ timeSinceTest <= 2592000) ||
+ (ResultFilters.getFilter("date", "last_3months") &&
+ timeSinceTest <= 7776000)
+ ) {
+ datehide = false;
+ }
+
+ if (datehide) {
+ if (filterDebug)
+ console.log(`skipping result due to date filter`, result);
+ return;
+ }
+
+ filteredResults.push(result);
+ } catch (e) {
+ Notifications.add(
+ "Something went wrong when filtering. Resetting filters.",
+ 0
+ );
+ console.log(result);
+ console.error(e);
+ ResultFilters.reset();
+ ResultFilters.updateActive();
+ update();
}
+ //filters done
+ //=======================================
- if (tagHide) {
- if (filterDebug)
- console.log(`skipping result due to tag filter`, result);
- return;
- }
+ const resultDate = new Date(result.timestamp);
+ resultDate.setSeconds(0);
+ resultDate.setMinutes(0);
+ resultDate.setHours(0);
+ resultDate.setMilliseconds(0);
+ const resultTimestamp = resultDate.getTime();
- const timeSinceTest = Math.abs(result.timestamp - Date.now()) / 1000;
-
- let datehide = true;
-
- if (
- ResultFilters.getFilter("date", "all") ||
- (ResultFilters.getFilter("date", "last_day") &&
- timeSinceTest <= 86400) ||
- (ResultFilters.getFilter("date", "last_week") &&
- timeSinceTest <= 604800) ||
- (ResultFilters.getFilter("date", "last_month") &&
- timeSinceTest <= 2592000) ||
- (ResultFilters.getFilter("date", "last_3months") &&
- timeSinceTest <= 7776000)
- ) {
- datehide = false;
- }
-
- if (datehide) {
- if (filterDebug)
- console.log(`skipping result due to date filter`, result);
- return;
- }
-
- filteredResults.push(result);
- } catch (e) {
- Notifications.add(
- "Something went wrong when filtering. Resetting filters.",
- 0
- );
- console.log(result);
- console.error(e);
- ResultFilters.reset();
- ResultFilters.updateActive();
- update();
- }
- //filters done
- //=======================================
-
- const resultDate = new Date(result.timestamp);
- resultDate.setSeconds(0);
- resultDate.setMinutes(0);
- resultDate.setHours(0);
- resultDate.setMilliseconds(0);
- const resultTimestamp = resultDate.getTime();
-
- if (Object.keys(activityChartData).includes(String(resultTimestamp))) {
- activityChartData[resultTimestamp].amount++;
- activityChartData[resultTimestamp].time +=
- result.testDuration +
- result.incompleteTestSeconds -
- (result.afkDuration ?? 0);
- activityChartData[resultTimestamp].totalWpm += result.wpm;
- } else {
- activityChartData[resultTimestamp] = {
- amount: 1,
- time:
+ if (Object.keys(activityChartData).includes(String(resultTimestamp))) {
+ activityChartData[resultTimestamp].amount++;
+ activityChartData[resultTimestamp].time +=
result.testDuration +
result.incompleteTestSeconds -
- (result.afkDuration ?? 0),
- totalWpm: result.wpm,
- };
- }
-
- let tt = 0;
- if (
- result.testDuration == undefined &&
- result.mode2 !== "custom" &&
- result.mode2 !== "zen"
- ) {
- //test finished before testDuration field was introduced - estimate
- if (result.mode == "time") {
- tt = result.mode2;
- } else if (result.mode == "words") {
- tt = (result.mode2 / result.wpm) * 60;
+ (result.afkDuration ?? 0);
+ activityChartData[resultTimestamp].totalWpm += result.wpm;
+ } else {
+ activityChartData[resultTimestamp] = {
+ amount: 1,
+ time:
+ result.testDuration +
+ result.incompleteTestSeconds -
+ (result.afkDuration ?? 0),
+ totalWpm: result.wpm,
+ };
}
- } else {
- tt = result.testDuration;
- }
- if (result.incompleteTestSeconds != undefined) {
- tt += result.incompleteTestSeconds;
- } else if (result.restartCount != undefined && result.restartCount > 0) {
- tt += (tt / 4) * result.restartCount;
- }
- // if (result.incompleteTestSeconds != undefined) {
- // tt += result.incompleteTestSeconds;
- // } else if (result.restartCount != undefined && result.restartCount > 0) {
- // tt += (tt / 4) * result.restartCount;
- // }
- totalSecondsFiltered += tt;
-
- if (last10 < 10) {
- last10++;
- wpmLast10total += result.wpm;
- totalAcc10 += result.acc;
- result.consistency !== undefined
- ? (totalCons10 += result.consistency)
- : 0;
- }
- testCount++;
-
- if (result.consistency !== undefined) {
- consCount++;
- totalCons += result.consistency;
- if (result.consistency > topCons) {
- topCons = result.consistency;
+ let tt = 0;
+ if (
+ result.testDuration == undefined &&
+ result.mode2 !== "custom" &&
+ result.mode2 !== "zen"
+ ) {
+ //test finished before testDuration field was introduced - estimate
+ if (result.mode == "time") {
+ tt = result.mode2;
+ } else if (result.mode == "words") {
+ tt = (result.mode2 / result.wpm) * 60;
+ }
+ } else {
+ tt = result.testDuration;
}
- }
-
- if (result.rawWpm != null) {
- if (rawWpm.last10Count < 10) {
- rawWpm.last10Count++;
- rawWpm.last10Total += result.rawWpm;
+ if (result.incompleteTestSeconds != undefined) {
+ tt += result.incompleteTestSeconds;
+ } else if (
+ result.restartCount != undefined &&
+ result.restartCount > 0
+ ) {
+ tt += (tt / 4) * result.restartCount;
}
- rawWpm.total += result.rawWpm;
- rawWpm.count++;
- if (result.rawWpm > rawWpm.max) {
- rawWpm.max = result.rawWpm;
+
+ // if (result.incompleteTestSeconds != undefined) {
+ // tt += result.incompleteTestSeconds;
+ // } else if (result.restartCount != undefined && result.restartCount > 0) {
+ // tt += (tt / 4) * result.restartCount;
+ // }
+ totalSecondsFiltered += tt;
+
+ if (last10 < 10) {
+ last10++;
+ wpmLast10total += result.wpm;
+ totalAcc10 += result.acc;
+ result.consistency !== undefined
+ ? (totalCons10 += result.consistency)
+ : 0;
}
+ testCount++;
+
+ if (result.consistency !== undefined) {
+ consCount++;
+ totalCons += result.consistency;
+ if (result.consistency > topCons) {
+ topCons = result.consistency;
+ }
+ }
+
+ if (result.rawWpm != null) {
+ if (rawWpm.last10Count < 10) {
+ rawWpm.last10Count++;
+ rawWpm.last10Total += result.rawWpm;
+ }
+ rawWpm.total += result.rawWpm;
+ rawWpm.count++;
+ if (result.rawWpm > rawWpm.max) {
+ rawWpm.max = result.rawWpm;
+ }
+ }
+
+ if (result.acc > topAcc) {
+ topAcc = result.acc;
+ }
+
+ totalAcc += result.acc;
+
+ if (result.restartCount != undefined) {
+ testRestarts += result.restartCount;
+ }
+
+ chartData.push({
+ x: result.timestamp,
+ y: Config.alwaysShowCPM ? Misc.roundTo2(result.wpm * 5) : result.wpm,
+ acc: result.acc,
+ mode: result.mode,
+ mode2: result.mode2,
+ punctuation: result.punctuation as boolean,
+ language: result.language,
+ timestamp: result.timestamp,
+ difficulty: result.difficulty,
+ raw: Config.alwaysShowCPM
+ ? Misc.roundTo2(result.rawWpm * 5)
+ : result.rawWpm,
+ });
+
+ wpmChartData.push(result.wpm);
+
+ accChartData.push({
+ x: result.timestamp,
+ y: 100 - result.acc,
+ });
+
+ if (result.wpm > topWpm) {
+ const puncsctring = result.punctuation ? ",
with punctuation" : "";
+ const numbsctring = result.numbers
+ ? ",
" + (result.punctuation ? "&" : "") + "with numbers"
+ : "";
+ topWpm = result.wpm;
+ if (result.mode == "custom") topMode = result.mode;
+ else
+ topMode =
+ result.mode + " " + result.mode2 + puncsctring + numbsctring;
+ }
+
+ totalWpm += result.wpm;
}
-
- if (result.acc > topAcc) {
- topAcc = result.acc;
- }
-
- totalAcc += result.acc;
-
- if (result.restartCount != undefined) {
- testRestarts += result.restartCount;
- }
-
- chartData.push({
- x: result.timestamp,
- y: Config.alwaysShowCPM ? Misc.roundTo2(result.wpm * 5) : result.wpm,
- acc: result.acc,
- mode: result.mode,
- mode2: result.mode2,
- punctuation: result.punctuation as boolean,
- language: result.language,
- timestamp: result.timestamp,
- difficulty: result.difficulty,
- raw: Config.alwaysShowCPM
- ? Misc.roundTo2(result.rawWpm * 5)
- : result.rawWpm,
- });
-
- wpmChartData.push(result.wpm);
-
- accChartData.push({
- x: result.timestamp,
- y: 100 - result.acc,
- });
-
- if (result.wpm > topWpm) {
- const puncsctring = result.punctuation ? ",
with punctuation" : "";
- const numbsctring = result.numbers
- ? ",
" + (result.punctuation ? "&" : "") + "with numbers"
- : "";
- topWpm = result.wpm;
- if (result.mode == "custom") topMode = result.mode;
- else
- topMode =
- result.mode + " " + result.mode2 + puncsctring + numbsctring;
- }
-
- totalWpm += result.wpm;
- });
+ );
if (Config.alwaysShowCPM) {
$(".pageAccount .group.history table thead tr td:nth-child(2)").text(
@@ -630,8 +639,10 @@ export function update(): void {
"Average Wpm";
}
- ChartController.accountActivity.data.datasets[0].data = activityChartData_time;
- ChartController.accountActivity.data.datasets[1].data = activityChartData_avgWpm;
+ ChartController.accountActivity.data.datasets[0].data =
+ activityChartData_time;
+ ChartController.accountActivity.data.datasets[1].data =
+ activityChartData_avgWpm;
if (Config.alwaysShowCPM) {
ChartController.accountHistory.options.scales.yAxes[0].scaleLabel.labelString =
@@ -653,9 +664,8 @@ export function update(): void {
Math.floor(maxWpmChartVal) + (10 - (Math.floor(maxWpmChartVal) % 10));
if (!Config.startGraphsAtZero) {
- ChartController.accountHistory.options.scales.yAxes[0].ticks.min = Math.floor(
- minWpmChartVal
- );
+ ChartController.accountHistory.options.scales.yAxes[0].ticks.min =
+ Math.floor(minWpmChartVal);
} else {
ChartController.accountHistory.options.scales.yAxes[0].ticks.min = 0;
}
@@ -963,7 +973,9 @@ $(document).on("click", ".pageAccount .miniResultChartButton", (event) => {
console.log("updating");
const filteredId = $(event.currentTarget).attr("filteredResultsId");
if (filteredId === undefined) return;
- MiniResultChart.updateData(filteredResults[parseInt(filteredId)].chartData);
+ MiniResultChart.updateData(
+ filteredResults[parseInt(filteredId)].chartData as MonkeyTypes.ChartData
+ );
MiniResultChart.show();
MiniResultChart.updatePosition(
event.pageX - ($(".pageAccount .miniResultChartWrapper").outerWidth() ?? 0),
diff --git a/frontend/src/scripts/pages/settings.ts b/frontend/src/scripts/pages/settings.ts
index 5c724ae6a..460aef147 100644
--- a/frontend/src/scripts/pages/settings.ts
+++ b/frontend/src/scripts/pages/settings.ts
@@ -587,7 +587,7 @@ function setActiveFunboxButton(): void {
function refreshTagsSettingsSection(): void {
if (firebase.auth().currentUser !== null && DB.getSnapshot() !== null) {
const tagsEl = $(".pageSettings .section.tags .tagsList").empty();
- DB.getSnapshot().tags.forEach((tag: MonkeyTypes.Tag) => {
+ DB.getSnapshot().tags?.forEach((tag) => {
// let tagPbString = "No PB found";
// if (tag.pb != undefined && tag.pb > 0) {
// tagPbString = `PB: ${tag.pb}`;
@@ -622,7 +622,7 @@ function refreshTagsSettingsSection(): void {
function refreshPresetsSettingsSection(): void {
if (firebase.auth().currentUser !== null && DB.getSnapshot() !== null) {
const presetsEl = $(".pageSettings .section.presets .presetsList").empty();
- DB.getSnapshot().presets.forEach((preset: MonkeyTypes.Preset) => {
+ DB.getSnapshot().presets?.forEach((preset: MonkeyTypes.Preset) => {
presetsEl.append(`
@@ -904,7 +904,7 @@ $(".pageSettings .section.customBackgroundSize .inputAndButton .save").on(
UpdateConfig.setCustomBackground(
$(
".pageSettings .section.customBackgroundSize .inputAndButton input"
- ).val()
+ ).val() as string
);
}
);
@@ -915,7 +915,7 @@ $(".pageSettings .section.customBackgroundSize .inputAndButton input").keypress(
UpdateConfig.setCustomBackground(
$(
".pageSettings .section.customBackgroundSize .inputAndButton input"
- ).val()
+ ).val() as string
);
}
}
@@ -925,7 +925,9 @@ $(".pageSettings .section.customLayoutfluid .inputAndButton .save").on(
"click",
() => {
UpdateConfig.setCustomLayoutfluid(
- $(".pageSettings .section.customLayoutfluid .inputAndButton input").val()
+ $(
+ ".pageSettings .section.customLayoutfluid .inputAndButton input"
+ ).val() as MonkeyTypes.CustomLayoutFluidSpaces
);
Notifications.add("Custom layoutfluid saved", 1);
}
@@ -937,7 +939,7 @@ $(".pageSettings .section.customLayoutfluid .inputAndButton .input").keypress(
UpdateConfig.setCustomLayoutfluid(
$(
".pageSettings .section.customLayoutfluid .inputAndButton input"
- ).val()
+ ).val() as MonkeyTypes.CustomLayoutFluidSpaces
);
Notifications.add("Custom layoutfluid saved", 1);
}
diff --git a/frontend/src/scripts/popups/custom-test-duration-popup.ts b/frontend/src/scripts/popups/custom-test-duration-popup.ts
index 05dcc46cc..d617e41d2 100644
--- a/frontend/src/scripts/popups/custom-test-duration-popup.ts
+++ b/frontend/src/scripts/popups/custom-test-duration-popup.ts
@@ -102,7 +102,7 @@ function apply(): void {
const val = parseInput($("#customTestDurationPopup input").val() as string);
if (val !== null && !isNaN(val) && val >= 0) {
- UpdateConfig.setTimeConfig(val);
+ UpdateConfig.setTimeConfig(val as MonkeyTypes.TimeModes);
ManualRestart.set();
TestLogic.restart();
if (val >= 1800) {
diff --git a/frontend/src/scripts/popups/custom-word-amount-popup.ts b/frontend/src/scripts/popups/custom-word-amount-popup.ts
index f0656bd90..916bd451b 100644
--- a/frontend/src/scripts/popups/custom-word-amount-popup.ts
+++ b/frontend/src/scripts/popups/custom-word-amount-popup.ts
@@ -36,7 +36,7 @@ function apply(): void {
const val = parseInt($("#customWordAmountPopup input").val() as string);
if (val !== null && !isNaN(val) && val >= 0) {
- UpdateConfig.setWordCount(val);
+ UpdateConfig.setWordCount(val as MonkeyTypes.WordsModes);
ManualRestart.set();
TestLogic.restart();
if (val > 2000) {
diff --git a/frontend/src/scripts/popups/edit-preset-popup.ts b/frontend/src/scripts/popups/edit-preset-popup.ts
index 532928392..62a672960 100644
--- a/frontend/src/scripts/popups/edit-preset-popup.ts
+++ b/frontend/src/scripts/popups/edit-preset-popup.ts
@@ -79,11 +79,11 @@ async function apply(): Promise {
);
// TODO fix this sometime
- let configChanges: ConfigChanges = (null as unknown) as ConfigChanges;
+ let configChanges: ConfigChanges = null as unknown as ConfigChanges;
if ((updateConfig && action === "edit") || action === "add") {
configChanges = Config.getConfigChanges() as ConfigChanges;
const activeTagIds: string[] = [];
- DB.getSnapshot().tags.forEach((tag: MonkeyTypes.Tag) => {
+ DB.getSnapshot().tags?.forEach((tag) => {
if (tag.active) {
activeTagIds.push(tag._id);
}
@@ -112,7 +112,7 @@ async function apply(): Promise {
Notifications.add(response.data.message);
} else {
Notifications.add("Preset added", 1, 2);
- DB.getSnapshot().presets.push({
+ DB.getSnapshot().presets?.push({
name: inputVal,
config: configChanges,
_id: response.data.insertedId,
@@ -140,12 +140,15 @@ async function apply(): Promise {
Notifications.add(response.data.message);
} else {
Notifications.add("Preset updated", 1);
- const preset: MonkeyTypes.Snapshot = DB.getSnapshot().presets.filter(
+ const preset = DB.getSnapshot().presets?.filter(
(preset: MonkeyTypes.Preset) => preset._id == presetid
)[0];
- preset.name = inputVal;
- if (updateConfig === true) preset.config = configChanges;
- Settings.update();
+
+ if (preset !== undefined) {
+ preset.name = inputVal;
+ if (updateConfig === true) preset.config = configChanges;
+ Settings.update();
+ }
}
} else if (action === "remove") {
Loader.show();
@@ -166,10 +169,10 @@ async function apply(): Promise {
Notifications.add(response.data.message);
} else {
Notifications.add("Preset removed", 1);
- DB.getSnapshot().presets.forEach(
+ DB.getSnapshot().presets?.forEach(
(preset: MonkeyTypes.Preset, index: number) => {
if (preset._id === presetid) {
- DB.getSnapshot().presets.splice(index, 1);
+ DB.getSnapshot().presets?.splice(index, 1);
}
}
);
diff --git a/frontend/src/scripts/popups/edit-tags-popup.ts b/frontend/src/scripts/popups/edit-tags-popup.ts
index 4a4089d6e..5a3144f4a 100644
--- a/frontend/src/scripts/popups/edit-tags-popup.ts
+++ b/frontend/src/scripts/popups/edit-tags-popup.ts
@@ -91,7 +91,7 @@ async function apply(): Promise {
Notifications.add(response.data.message);
} else {
Notifications.add("Tag added", 1);
- DB.getSnapshot().tags.push({
+ DB.getSnapshot().tags?.push({
name: response.data.name,
_id: response.data._id,
});
@@ -119,7 +119,7 @@ async function apply(): Promise {
Notifications.add(response.data.message);
} else {
Notifications.add("Tag updated", 1);
- DB.getSnapshot().tags.forEach((tag: MonkeyTypes.Tag) => {
+ DB.getSnapshot().tags?.forEach((tag) => {
if (tag._id === tagid) {
tag.name = inputVal;
}
@@ -145,9 +145,9 @@ async function apply(): Promise {
Notifications.add(response.data.message);
} else {
Notifications.add("Tag removed", 1);
- DB.getSnapshot().tags.forEach((tag: MonkeyTypes.Tag, index: number) => {
+ DB.getSnapshot().tags?.forEach((tag, index: number) => {
if (tag._id === tagid) {
- DB.getSnapshot().tags.splice(index, 1);
+ DB.getSnapshot().tags?.splice(index, 1);
}
});
ResultTagsPopup.updateButtons();
@@ -171,9 +171,15 @@ async function apply(): Promise {
Notifications.add(response.data.message);
} else {
Notifications.add("Tag PB cleared", 1);
- DB.getSnapshot().tags.forEach((tag: MonkeyTypes.Tag) => {
+ DB.getSnapshot().tags?.forEach((tag) => {
if (tag._id === tagid) {
- tag.personalBests = {};
+ tag.personalBests = {
+ time: {},
+ words: {},
+ custom: { custom: [] },
+ zen: { zen: [] },
+ quote: { custom: [] },
+ };
}
});
ResultTagsPopup.updateButtons();
diff --git a/frontend/src/scripts/popups/mobile-test-config-popup.ts b/frontend/src/scripts/popups/mobile-test-config-popup.ts
index d589c8e70..f958e8acc 100644
--- a/frontend/src/scripts/popups/mobile-test-config-popup.ts
+++ b/frontend/src/scripts/popups/mobile-test-config-popup.ts
@@ -95,23 +95,27 @@ $("#top .mobileConfig").click(() => {
el.find(".wordsGroup .button").on("click", (e) => {
const wrd = $(e.currentTarget).attr("words");
+
if (wrd == "custom") {
hidePopup();
CustomWordAmountPopup.show();
- } else {
- UpdateConfig.setWordCount(wrd);
+ } else if (wrd !== undefined) {
+ const wrdNum = parseInt(wrd);
+ UpdateConfig.setWordCount(wrdNum);
ManualRestart.set();
TestLogic.restart();
}
});
el.find(".timeGroup .button").on("click", (e) => {
- const mode = $(e.currentTarget).attr("time");
- if (mode == "custom") {
+ const time = $(e.currentTarget).attr("time");
+
+ if (time == "custom") {
hidePopup();
CustomTestDurationPopup.show();
- } else {
- UpdateConfig.setTimeConfig(mode);
+ } else if (time !== undefined) {
+ const timeNum = parseInt(time);
+ UpdateConfig.setTimeConfig(timeNum);
ManualRestart.set();
TestLogic.restart();
}
@@ -128,7 +132,11 @@ el.find(".quoteGroup .button").on("click", (e) => {
if (len == -1) {
len = [0, 1, 2, 3];
}
- UpdateConfig.setQuoteLength(len, false, e.shiftKey);
+ UpdateConfig.setQuoteLength(
+ len as MonkeyTypes.QuoteLength | MonkeyTypes.QuoteLengthArray,
+ false,
+ e.shiftKey
+ );
ManualRestart.set();
TestLogic.restart();
}
@@ -154,7 +162,7 @@ el.find(".numbers").on("click", () => {
el.find(".modeGroup .button").on("click", (e) => {
if ($(e.currentTarget).hasClass("active")) return;
const mode = $(e.currentTarget).attr("mode");
- UpdateConfig.setMode(mode);
+ UpdateConfig.setMode(mode as MonkeyTypes.Mode);
ManualRestart.set();
TestLogic.restart();
});
diff --git a/frontend/src/scripts/popups/pb-tables-popup.ts b/frontend/src/scripts/popups/pb-tables-popup.ts
index e24dc8a96..f4c4d2b72 100644
--- a/frontend/src/scripts/popups/pb-tables-popup.ts
+++ b/frontend/src/scripts/popups/pb-tables-popup.ts
@@ -1,47 +1,42 @@
import * as DB from "../db";
-function update(mode: string): void {
+interface PersonalBest extends MonkeyTypes.PersonalBest {
+ mode2: MonkeyTypes.Mode2;
+}
+
+function update(mode: MonkeyTypes.Mode): void {
$("#pbTablesPopup table tbody").empty();
$($("#pbTablesPopup table thead tr td")[0]).text(mode);
- type PersonalBests = {
- [key: string]: PersonalBest[];
- };
+ const snapshot = DB.getSnapshot();
- type PersonalBest = {
- acc: number;
- consistency: number;
- difficulty: MonkeyTypes.Difficulty;
- lazyMode: boolean;
- language: string;
- punctuation: boolean;
- raw: number;
- wpm: number;
- timestamp: number;
- mode2?: string;
- };
+ const allmode2 = (
+ snapshot.personalBests === undefined
+ ? undefined
+ : snapshot.personalBests[mode]
+ ) as { [quote: string]: PersonalBest[] } | undefined;
- const allmode2: PersonalBests = DB.getSnapshot().personalBests[mode];
-
- if (!allmode2) return;
+ if (allmode2 === undefined) return;
const list: PersonalBest[] = [];
- Object.keys(allmode2).forEach(function (key) {
- let pbs = allmode2[key];
- pbs = pbs.sort(function (a, b) {
- return b.wpm - a.wpm;
- // if (a.difficulty === b.difficulty) {
- // return (a.language < b.language ? -1 : 1);
- // }
- // return (a.difficulty < b.difficulty ? -1 : 1)
- });
- pbs.forEach(function (pb) {
- pb.mode2 = key;
- list.push(pb);
- });
- });
+ (Object.keys(allmode2) as MonkeyTypes.Mode2[]).forEach(
+ function (key) {
+ let pbs = allmode2[key];
+ pbs = pbs.sort(function (a, b) {
+ return b.wpm - a.wpm;
+ // if (a.difficulty === b.difficulty) {
+ // return (a.language < b.language ? -1 : 1);
+ // }
+ // return (a.difficulty < b.difficulty ? -1 : 1)
+ });
+ pbs.forEach(function (pb) {
+ pb.mode2 = key;
+ list.push(pb);
+ });
+ }
+ );
- let mode2memory: string;
+ let mode2memory: MonkeyTypes.Mode2;
list.forEach((pb) => {
let dateText = `-
-`;
@@ -74,11 +69,11 @@ function update(mode: string): void {
${dateText} |
`);
- mode2memory = pb.mode2 as string;
+ mode2memory = pb.mode2 as never;
});
}
-function show(mode: string): void {
+function show(mode: MonkeyTypes.Mode): void {
if ($("#pbTablesPopupWrapper").hasClass("hidden")) {
update(mode);
diff --git a/frontend/src/scripts/popups/quote-rate-popup.ts b/frontend/src/scripts/popups/quote-rate-popup.ts
index 2a457c5e2..09d2c9cca 100644
--- a/frontend/src/scripts/popups/quote-rate-popup.ts
+++ b/frontend/src/scripts/popups/quote-rate-popup.ts
@@ -15,12 +15,6 @@ type QuoteStats = {
language: string;
};
-type QuoteRatings = {
- [language: string]: {
- [id: string]: number;
- };
-};
-
let quoteStats: QuoteStats | null | Record = null;
let currentQuote: MonkeyTypes.Quote | null = null;
@@ -111,9 +105,13 @@ export function show(quote: MonkeyTypes.Quote, shouldReset = true): void {
currentQuote = quote;
rating = 0;
- const alreadyRated = DB.getSnapshot().quoteRatings?.[
- currentQuote.language
- ]?.[currentQuote.id];
+
+ const snapshot = DB.getSnapshot();
+
+ if (snapshot.quoteRatings === undefined) return;
+
+ const alreadyRated =
+ snapshot.quoteRatings[currentQuote.language][currentQuote.id];
if (alreadyRated) {
rating = alreadyRated;
}
@@ -174,7 +172,10 @@ async function submit(): Promise {
if (response.status !== 200) {
Notifications.add(response.data.message);
} else {
- let quoteRatings: QuoteRatings = DB.getSnapshot().quoteRatings;
+ let quoteRatings = DB.getSnapshot().quoteRatings;
+
+ if (quoteRatings === undefined) return;
+
if (quoteRatings?.[currentQuote.language]?.[currentQuote.id]) {
const oldRating = quoteRatings[currentQuote.language][currentQuote.id];
const diff = rating - oldRating;
@@ -243,5 +244,5 @@ $("#quoteRatePopup .submitButton").click(() => {
$(".pageTest #rateQuoteButton").click(async () => {
// TODO remove this when done with TestWords
- show((TestWords.randomQuote as unknown) as MonkeyTypes.Quote);
+ show(TestWords.randomQuote as unknown as MonkeyTypes.Quote);
});
diff --git a/frontend/src/scripts/popups/quote-search-popup.ts b/frontend/src/scripts/popups/quote-search-popup.ts
index ff2cbd3f8..830f77fdb 100644
--- a/frontend/src/scripts/popups/quote-search-popup.ts
+++ b/frontend/src/scripts/popups/quote-search-popup.ts
@@ -146,7 +146,7 @@ export function apply(val: number): boolean {
}
let ret;
if (val !== null && !isNaN(val) && val >= 0) {
- UpdateConfig.setQuoteLength(-2, false);
+ UpdateConfig.setQuoteLength(-2 as MonkeyTypes.QuoteLength, false);
selectedId = val;
ManualRestart.set();
ret = true;
diff --git a/frontend/src/scripts/popups/result-tags-popup.ts b/frontend/src/scripts/popups/result-tags-popup.ts
index d339da2b6..53ab97a35 100644
--- a/frontend/src/scripts/popups/result-tags-popup.ts
+++ b/frontend/src/scripts/popups/result-tags-popup.ts
@@ -32,7 +32,7 @@ function hide(): void {
export function updateButtons(): void {
$("#resultEditTagsPanel .buttons").empty();
- DB.getSnapshot().tags.forEach((tag: MonkeyTypes.Tag) => {
+ DB.getSnapshot().tags?.forEach((tag) => {
$("#resultEditTagsPanel .buttons").append(
`${tag.name}
`
);
@@ -52,7 +52,7 @@ function updateActiveButtons(active: string[]): void {
}
$(document).on("click", ".pageAccount .group.history #resultEditTags", (f) => {
- if (DB.getSnapshot().tags.length > 0) {
+ if (DB.getSnapshot().tags?.length || 0 > 0) {
const resultid = $(f.target).parents("span").attr("resultid") as string;
const tags = $(f.target).parents("span").attr("tags") as string;
$("#resultEditTagsPanel").attr("resultid", resultid);
@@ -97,17 +97,19 @@ $("#resultEditTagsPanel .confirmButton").click(() => {
Notifications.add(response.data.message);
} else {
Notifications.add("Tags updated.", 1, 2);
- DB.getSnapshot().results.forEach((result: MonkeyTypes.Result) => {
- if (result._id === resultid) {
- result.tags = newtags;
+ DB.getSnapshot().results?.forEach(
+ (result: MonkeyTypes.Result) => {
+ if (result._id === resultid) {
+ result.tags = newtags;
+ }
}
- });
+ );
let tagNames = "";
if (newtags.length > 0) {
newtags.forEach((tag) => {
- DB.getSnapshot().tags.forEach((snaptag: MonkeyTypes.Tag) => {
+ DB.getSnapshot().tags?.forEach((snaptag) => {
if (tag === snaptag._id) {
tagNames += snaptag.name + ", ";
}
diff --git a/frontend/src/scripts/popups/simple-popups.ts b/frontend/src/scripts/popups/simple-popups.ts
index 8d7587801..004dc619a 100644
--- a/frontend/src/scripts/popups/simple-popups.ts
+++ b/frontend/src/scripts/popups/simple-popups.ts
@@ -578,10 +578,16 @@ list["clearTagPb"] = new SimplePopup(
.then((res) => {
Loader.hide();
if (res.data.resultCode === 1) {
- const tag = DB.getSnapshot().tags.filter(
- (t: MonkeyTypes.Tag) => t._id === tagid
- )[0];
- tag.pb = 0;
+ const tag = DB.getSnapshot().tags?.filter((t) => t._id === tagid)[0];
+
+ if (tag === undefined) return;
+ tag.personalBests = {
+ time: {},
+ words: {},
+ zen: { zen: [] },
+ quote: { custom: [] },
+ custom: { custom: [] },
+ };
$(
`.pageSettings .section.tags .tagsList .tag[id="${tagid}"] .clearPbButton`
).attr("aria-label", "No PB found");
@@ -665,7 +671,13 @@ list["resetPersonalBests"] = new SimplePopup(
Notifications.add(response.data.message);
} else {
Notifications.add("Personal bests have been reset", 1);
- DB.getSnapshot().personalBests = {};
+ DB.getSnapshot().personalBests = {
+ time: {},
+ words: {},
+ zen: { zen: [] },
+ quote: { custom: [] },
+ custom: { custom: [] },
+ };
}
} catch (e) {
Loader.hide();
diff --git a/frontend/src/scripts/settings/settings-group.ts b/frontend/src/scripts/settings/settings-group.ts
index 1126544c5..3c3e16fec 100644
--- a/frontend/src/scripts/settings/settings-group.ts
+++ b/frontend/src/scripts/settings/settings-group.ts
@@ -9,7 +9,7 @@ export default class SettingsGroup {
public updateCallback?: () => any;
constructor(
configName: string,
- configFunction: () => any,
+ configFunction: (...values: any[]) => any,
mode: string,
setCallback?: () => any,
updateCallback?: () => any
diff --git a/frontend/src/scripts/settings/theme-picker.ts b/frontend/src/scripts/settings/theme-picker.ts
index ac7fc87be..174b3486e 100644
--- a/frontend/src/scripts/settings/theme-picker.ts
+++ b/frontend/src/scripts/settings/theme-picker.ts
@@ -212,7 +212,7 @@ $(document).on(
$(document).on("click", ".pageSettings .section.themes .theme.button", (e) => {
const theme = $(e.currentTarget).attr("theme");
- if (!$(e.target).hasClass("favButton")) {
+ if (!$(e.target).hasClass("favButton") && theme !== undefined) {
UpdateConfig.setTheme(theme);
updateActiveButton();
}
diff --git a/frontend/src/scripts/test/live-burst.ts b/frontend/src/scripts/test/live-burst.ts
index 6b33c033a..9d23d8ca3 100644
--- a/frontend/src/scripts/test/live-burst.ts
+++ b/frontend/src/scripts/test/live-burst.ts
@@ -7,12 +7,10 @@ export function update(burst: number): void {
if (Config.blindMode) {
number = 0;
}
- (document.querySelector(
- "#miniTimerAndLiveWpm .burst"
- ) as Element).innerHTML = number.toString();
- (document.querySelector(
- "#liveBurst"
- ) as Element).innerHTML = number.toString();
+ (document.querySelector("#miniTimerAndLiveWpm .burst") as Element).innerHTML =
+ number.toString();
+ (document.querySelector("#liveBurst") as Element).innerHTML =
+ number.toString();
}
export function show(): void {
diff --git a/frontend/src/scripts/test/result.js b/frontend/src/scripts/test/result.js
index f203e9bd8..00dd49ff9 100644
--- a/frontend/src/scripts/test/result.js
+++ b/frontend/src/scripts/test/result.js
@@ -35,9 +35,8 @@ async function updateGraph() {
}
ChartController.result.updateColors();
ChartController.result.data.labels = labels;
- ChartController.result.options.scales.yAxes[0].scaleLabel.labelString = Config.alwaysShowCPM
- ? "Character per Minute"
- : "Words per Minute";
+ ChartController.result.options.scales.yAxes[0].scaleLabel.labelString =
+ Config.alwaysShowCPM ? "Character per Minute" : "Words per Minute";
let chartData1 = Config.alwaysShowCPM
? TestInput.wpmHistory.map((a) => a * 5)
: TestInput.wpmHistory;
@@ -156,12 +155,10 @@ export async function updateGraphPBLine() {
) {
maxChartVal = parseFloat(chartlpb) + 20;
}
- ChartController.result.options.scales.yAxes[0].ticks.max = Math.round(
- maxChartVal
- );
- ChartController.result.options.scales.yAxes[1].ticks.max = Math.round(
- maxChartVal
- );
+ ChartController.result.options.scales.yAxes[0].ticks.max =
+ Math.round(maxChartVal);
+ ChartController.result.options.scales.yAxes[1].ticks.max =
+ Math.round(maxChartVal);
ChartController.result.update({ duration: 0 });
}
@@ -548,9 +545,8 @@ function updateOther(
export function updateRateQuote(randomQuote) {
if (Config.mode === "quote") {
- let userqr = DB.getSnapshot().quoteRatings?.[randomQuote.language]?.[
- randomQuote.id
- ];
+ let userqr =
+ DB.getSnapshot().quoteRatings?.[randomQuote.language]?.[randomQuote.id];
if (userqr) {
$(".pageTest #result #rateQuoteButton .icon")
.removeClass("far")
diff --git a/frontend/src/scripts/test/test-words.ts b/frontend/src/scripts/test/test-words.ts
index 206e29a56..85d378623 100644
--- a/frontend/src/scripts/test/test-words.ts
+++ b/frontend/src/scripts/test/test-words.ts
@@ -57,7 +57,7 @@ class Words {
}
export const words = new Words();
export let hasTab = false;
-export let randomQuote = (null as unknown) as MonkeyTypes.Quote;
+export let randomQuote = null as unknown as MonkeyTypes.Quote;
export function setRandomQuote(rq: MonkeyTypes.Quote): void {
randomQuote = rq;
diff --git a/frontend/src/scripts/types/types.d.ts b/frontend/src/scripts/types/types.d.ts
index 641d2b2eb..fbeb4b97f 100644
--- a/frontend/src/scripts/types/types.d.ts
+++ b/frontend/src/scripts/types/types.d.ts
@@ -7,17 +7,17 @@ declare namespace MonkeyTypes {
type Mode2 = keyof PersonalBests[M];
+ type Mode2Custom = Mode2 | "custom";
+
type LanguageGroup = { name: string; languages: string[] };
- // type Mode2 = 10 | 15 | 25 | 30 | 50 | 60 | 100 | 120 | 200 | "zen" | "custom";
+ type WordsModes = number;
- type NoncustomWordsModes = 10 | 25 | 50 | 100 | 200;
+ type TimeModes = number;
- type WordsModes = NoncustomWordsModes | CustomModes;
+ type DefaultWordsModes = 10 | 25 | 50 | 100;
- type NoncustomTimeModes = 15 | 30 | 60 | 120;
-
- type TimeModes = NoncustomTimeModes | CustomModes;
+ type DefaultTimeModes = 15 | 30 | 60 | 120;
type QuoteModes = "short" | "medium" | "long" | "thicc";
@@ -40,7 +40,7 @@ declare namespace MonkeyTypes {
type TimerStyle = "bar" | "text" | "mini";
- type RandomTheme = "off" | "on" | "favorite" | "light" | "dark";
+ type RandomTheme = "off" | "on" | "fav" | "light" | "dark";
type TimerColor = "black" | "sub" | "text" | "main";
@@ -61,15 +61,17 @@ declare namespace MonkeyTypes {
type SingleListCommandLine = "manual" | "on";
- type PlaySoundOnClick =
- | "off"
- | "click"
- | "beep"
- | "pop"
- | "nk_creams"
- | "typewriter"
- | "osu"
- | "hitmarker";
+ /*
+ off = off
+ 1 = click
+ 2 = beep
+ 3 = pop
+ 4 = nk creams
+ 5 = typewriter
+ 6 = osu
+ 7 = hitmarker
+ */
+ type PlaySoundOnClick = "off" | "1" | "2" | "3" | "4" | "5" | "6" | "7";
type SoundVolume = "0.1" | "0.5" | "1.0";
@@ -83,7 +85,7 @@ declare namespace MonkeyTypes {
type HighlightMode = "off" | "letter" | "word";
- type EnableAds = "off" | "on" | "sellout";
+ type EnableAds = "off" | "on" | "max";
type MinimumAccuracy = "off" | "custom";
@@ -95,12 +97,27 @@ declare namespace MonkeyTypes {
type CustomBackgroundFilter = [0 | 1, 0 | 1, 0 | 1, 0 | 1, 0 | 1];
- type MonkeyPowerLevel = "off" | "mellow" | "high" | "ultra" | "over_9000";
+ /*
+ off = off
+ 1 = mellow
+ 2 = high
+ 3 = ultra
+ 4 = over 9000
+ */
+ type MonkeyPowerLevel = "off" | "1" | "2" | "3" | "4";
type MinimumBurst = "off" | "fixed" | "flex";
type FunboxObjectType = "script" | "style";
+ type IndicateTypos = "off" | "below" | "replace";
+
+ type CustomLayoutFluid = `${string}#${string}#${string}`;
+
+ type CustomLayoutFluidSpaces =
+ | CustomLayoutFluid
+ | `${string} ${string} ${string}`;
+
interface FunboxObject {
name: string;
type: FunboxObjectType;
@@ -137,22 +154,22 @@ declare namespace MonkeyTypes {
interface PersonalBests {
time: {
[key: number]: PersonalBest[];
- custom: PersonalBest[];
};
words: {
[key: number]: PersonalBest[];
- custom: PersonalBest[];
};
quote: { [quote: string]: PersonalBest[] };
custom: { custom: PersonalBest[] };
- zen: PersonalBest[];
+ zen: {
+ zen: PersonalBest[];
+ };
}
interface Tag {
_id: string;
name: string;
- personalBests: PersonalBests | Record;
- active: boolean;
+ personalBests?: PersonalBests;
+ active?: boolean;
}
interface Stats {
@@ -172,7 +189,7 @@ declare namespace MonkeyTypes {
sd: number;
}
- interface Result {
+ interface Result {
_id: string;
wpm: number;
rawWpm: number;
@@ -180,8 +197,8 @@ declare namespace MonkeyTypes {
correctChars?: number; // --------------
incorrectChars?: number; // legacy results
acc: number;
- mode: Mode;
- mode2: number | "custom" | "zen";
+ mode: M;
+ mode2: Mode2;
quoteLength: number;
timestamp: number;
restartCount: number;
@@ -235,7 +252,7 @@ declare namespace MonkeyTypes {
layout: string;
funbox: string;
confidenceMode: ConfidenceMode;
- indicateTypos: boolean;
+ indicateTypos: IndicateTypos;
timerStyle: TimerStyle;
colorfulMode: boolean;
randomTheme: RandomTheme;
@@ -282,7 +299,7 @@ declare namespace MonkeyTypes {
customBackground: string;
customBackgroundSize: CustomBackgroundSize;
customBackgroundFilter: CustomBackgroundFilter;
- customLayoutfluid: string;
+ customLayoutfluid: CustomLayoutFluid;
monkeyPowerLevel: MonkeyPowerLevel;
minBurst: MinimumBurst;
minBurstCustomSpeed: number;
@@ -295,6 +312,14 @@ declare namespace MonkeyTypes {
wordCount: WordsModes;
}
+ interface LeaderboardMemory {
+ time: {
+ [key in 15 | 60]: {
+ [language: string]: number;
+ };
+ };
+ }
+
interface Leaderboards {
time: {
[key in 15 | 60]: LeaderboardEntry[];
@@ -319,24 +344,34 @@ declare namespace MonkeyTypes {
hidden?: boolean;
}
+ interface QuoteRatings {
+ [language: string]: {
+ [id: string | number]: any; // TODO find this
+ };
+ }
+
interface Snapshot {
banned?: boolean;
emailVerified?: boolean;
- quoteRatings?: object; // TODO find structure of quoteRatings
- results?: Result[];
+ quoteRatings?: QuoteRatings;
+ results?: Result[];
verified?: boolean;
personalBests?: PersonalBests;
name?: string;
presets?: Preset[];
tags?: Tag[];
favouriteThemes?: string[];
- lbMemory?: Leaderboards;
+ lbMemory?: LeaderboardMemory;
globalStats?: Stats;
quoteMod?: boolean;
discordId?: string;
config?: Config;
}
+ type PartialRecord = {
+ [P in K]?: T;
+ };
+
interface ResultFilters {
difficulty: {
normal: boolean;
diff --git a/package-lock.json b/package-lock.json
index d44a306da..c94bbdcbf 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -22,8 +22,8 @@
"eslint-plugin-promise": "5.1.0",
"eslint-plugin-require-path-exists": "1.1.9",
"husky": "4.3.0",
- "jsonschema": "^1.4.0",
- "prettier": "2.1.2",
+ "jsonschema": "1.4.0",
+ "prettier": "2.5.1",
"pretty-quick": "3.1.0"
},
"engines": {
@@ -4515,9 +4515,9 @@
}
},
"node_modules/prettier": {
- "version": "2.1.2",
- "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.1.2.tgz",
- "integrity": "sha512-16c7K+x4qVlJg9rEbXl7HEGmQyZlG4R9AgP+oHKRMsMsuk8s+ATStlf1NpDqyBI1HpVyfjLOeMhH2LvuNvV5Vg==",
+ "version": "2.5.1",
+ "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.5.1.tgz",
+ "integrity": "sha512-vBZcPRUR5MZJwoyi3ZoyQlc1rXeEck8KgeC9AwwOn+exuxLxq5toTRDTSaVrXHxelDMHy9zlicw8u66yxoSUFg==",
"dev": true,
"bin": {
"prettier": "bin-prettier.js"
@@ -9301,9 +9301,9 @@
"dev": true
},
"prettier": {
- "version": "2.1.2",
- "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.1.2.tgz",
- "integrity": "sha512-16c7K+x4qVlJg9rEbXl7HEGmQyZlG4R9AgP+oHKRMsMsuk8s+ATStlf1NpDqyBI1HpVyfjLOeMhH2LvuNvV5Vg==",
+ "version": "2.5.1",
+ "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.5.1.tgz",
+ "integrity": "sha512-vBZcPRUR5MZJwoyi3ZoyQlc1rXeEck8KgeC9AwwOn+exuxLxq5toTRDTSaVrXHxelDMHy9zlicw8u66yxoSUFg==",
"dev": true
},
"pretty-quick": {
diff --git a/package.json b/package.json
index 890e4e283..7ef69a370 100644
--- a/package.json
+++ b/package.json
@@ -36,8 +36,8 @@
"eslint-plugin-promise": "5.1.0",
"eslint-plugin-require-path-exists": "1.1.9",
"husky": "4.3.0",
- "jsonschema": "^1.4.0",
- "prettier": "2.1.2",
+ "jsonschema": "1.4.0",
+ "prettier": "2.5.1",
"pretty-quick": "3.1.0"
},
"husky": {