mirror of
https://github.com/monkeytypegame/monkeytype.git
synced 2024-09-19 23:06:15 +08:00
TypeScript FrontEnd: Add Account Files (#2494)
* add account files, config, and db, fix other files, and make lint script work on cmd * fuck operating systems * remove project from eslint * Merging and fixing some bugs * fixed result ordering * fixed quote filter stopping all results * fixed words filter not working * corrected type * Update commandline-lists.ts * Update types.d.ts * removing explicit tag types * mfing prettier * small changes * stuff * fixes * fix cannot read properties of undefined * another check just to be safe * okay that works Co-authored-by: Miodec <bartnikjack@gmail.com>
This commit is contained in:
parent
c3825ab54e
commit
71cdce20e3
19
.github/ISSUE_TEMPLATE/bug_report.yaml
vendored
19
.github/ISSUE_TEMPLATE/bug_report.yaml
vendored
|
@ -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
|
||||
|
||||
|
|
11
.prettierrc
11
.prettierrc
|
@ -1,5 +1,14 @@
|
|||
{
|
||||
"tabWidth": 2,
|
||||
"useTabs": false,
|
||||
"htmlWhitespaceSensitivity": "ignore"
|
||||
"htmlWhitespaceSensitivity": "ignore",
|
||||
"endOfLine": "lf",
|
||||
"overrides": [
|
||||
{
|
||||
"files": ["*.ts"],
|
||||
"options": {
|
||||
"parser": "typescript"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
|
@ -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
|
||||
);
|
||||
}
|
||||
}
|
|
@ -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();
|
||||
});
|
|
@ -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(`
|
||||
<tr>
|
||||
<td>15</td>
|
||||
|
@ -75,10 +75,11 @@ export function update() {
|
|||
}
|
||||
|
||||
const pb = DB.getSnapshot().personalBests;
|
||||
if (pb === undefined) return;
|
||||
let pbData;
|
||||
let text;
|
||||
let dateText = `-<br><span class="sub">-</span>`;
|
||||
let multiplier = Config.alwaysShowCPM ? 5 : 1;
|
||||
const multiplier = Config.alwaysShowCPM ? 5 : 1;
|
||||
|
||||
text = "";
|
||||
try {
|
|
@ -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<G extends MonkeyTypes.Group>(
|
||||
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<G extends MonkeyTypes.Group>(
|
||||
group: G,
|
||||
filter: MonkeyTypes.Filter<G>
|
||||
): MonkeyTypes.ResultFilters[G][MonkeyTypes.Filter<G>] {
|
||||
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<typeof group>[]
|
||||
).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 += "<div class='group'>";
|
||||
if (group == "difficulty") {
|
||||
|
@ -200,21 +219,23 @@ export function updateActive() {
|
|||
} else if (group == "funbox") {
|
||||
ret += `<span aria-label="Funbox" data-balloon-pos="up"><i class="fas fa-fw fa-gamepad"></i>`;
|
||||
}
|
||||
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 += "</span></div>";
|
||||
|
@ -232,13 +253,13 @@ export function updateActive() {
|
|||
chartString += `<div class="spacer"></div>`;
|
||||
|
||||
//time
|
||||
if (aboveChartDisplay.mode.array.includes("time")) {
|
||||
if (aboveChartDisplay.mode?.array?.includes("time")) {
|
||||
chartString += addText("time");
|
||||
chartString += `<div class="spacer"></div>`;
|
||||
}
|
||||
|
||||
//words
|
||||
if (aboveChartDisplay.mode.array.includes("words")) {
|
||||
if (aboveChartDisplay.mode?.array?.includes("words")) {
|
||||
chartString += addText("words");
|
||||
chartString += `<div class="spacer"></div>`;
|
||||
}
|
||||
|
@ -271,14 +292,21 @@ export function updateActive() {
|
|||
}, 0);
|
||||
}
|
||||
|
||||
export function toggle(group, filter) {
|
||||
export function toggle<G extends MonkeyTypes.Group>(
|
||||
group: G,
|
||||
filter: MonkeyTypes.Filter<G>
|
||||
): 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(`<div class="button" filter="none">no tag</div>`);
|
||||
DB.getSnapshot().tags.forEach((tag) => {
|
||||
snapshot.tags?.forEach((tag) => {
|
||||
$(
|
||||
".pageAccount .content .filterButtons .buttonsAndTitle.tags .buttons"
|
||||
).append(`<div class="button" filter="${tag._id}">${tag.name}</div>`);
|
||||
|
@ -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<typeof group>;
|
||||
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<typeof group>[]
|
||||
).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<typeof group>[]
|
||||
).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<typeof group>[]
|
||||
).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<typeof group>[]
|
||||
).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<typeof group>[]
|
||||
).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"
|
|
@ -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({
|
File diff suppressed because it is too large
Load diff
|
@ -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");
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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<boolean> {
|
||||
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<MonkeyTypes.Mode>[];
|
||||
|
||||
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<M extends MonkeyTypes.Mode>(
|
||||
mode: M,
|
||||
mode2: MonkeyTypes.Mode2<M>,
|
||||
punctuation: boolean,
|
||||
language: string,
|
||||
difficulty: MonkeyTypes.Difficulty,
|
||||
lazyMode: boolean
|
||||
): Promise<number> {
|
||||
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<M extends MonkeyTypes.Mode>(
|
||||
mode: M,
|
||||
mode2: MonkeyTypes.Mode2<M>,
|
||||
punctuation: boolean,
|
||||
language: string,
|
||||
difficulty: MonkeyTypes.Difficulty,
|
||||
lazyMode: boolean
|
||||
): Promise<number> {
|
||||
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<M extends MonkeyTypes.Mode>(
|
||||
mode: M,
|
||||
mode2: MonkeyTypes.Mode2<M>,
|
||||
punctuation: boolean,
|
||||
language: string,
|
||||
difficulty: MonkeyTypes.Difficulty,
|
||||
lazyMode: boolean,
|
||||
funbox: string
|
||||
): Promise<number> {
|
||||
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<M extends MonkeyTypes.Mode>(
|
||||
mode: M,
|
||||
mode2: MonkeyTypes.Mode2<M>,
|
||||
punctuation: boolean,
|
||||
language: string,
|
||||
difficulty: MonkeyTypes.Difficulty,
|
||||
lazyMode: boolean,
|
||||
wpm: number,
|
||||
acc: number,
|
||||
raw: number,
|
||||
consistency: number
|
||||
): Promise<void> {
|
||||
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<typeof mode, "zen">] = {
|
||||
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<M extends MonkeyTypes.Mode>(
|
||||
tagId: string,
|
||||
mode: M,
|
||||
mode2: MonkeyTypes.Mode2<M>,
|
||||
punctuation: boolean,
|
||||
language: string,
|
||||
difficulty: MonkeyTypes.Difficulty,
|
||||
lazyMode: boolean
|
||||
): Promise<number> {
|
||||
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<M extends MonkeyTypes.Mode>(
|
||||
tagId: string,
|
||||
mode: M,
|
||||
mode2: MonkeyTypes.Mode2<M>,
|
||||
punctuation: boolean,
|
||||
language: string,
|
||||
difficulty: MonkeyTypes.Difficulty,
|
||||
lazyMode: boolean,
|
||||
wpm: number,
|
||||
acc: number,
|
||||
raw: number,
|
||||
consistency: number
|
||||
): Promise<number | undefined> {
|
||||
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<typeof mode, "zen">] = {
|
||||
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<M extends MonkeyTypes.Mode>(
|
||||
mode: M,
|
||||
mode2: MonkeyTypes.Mode2<M>,
|
||||
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<void> {
|
||||
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<MonkeyTypes.Mode>
|
||||
): 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;
|
||||
// }
|
||||
|
|
@ -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();
|
||||
},
|
||||
},
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
});
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 + ", ";
|
||||
}
|
||||
|
|
|
@ -212,7 +212,7 @@ export async function addPower(good = true, extra = false): Promise<void> {
|
|||
`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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
type SubscribeFunction = (key: string, value?: string, value2?: string) => void;
|
||||
type SubscribeFunction<V, V2> = (key: string, value?: V, value2?: V2) => void;
|
||||
|
||||
const subscribers: SubscribeFunction[] = [];
|
||||
const subscribers: SubscribeFunction<any, any>[] = [];
|
||||
|
||||
export function subscribe(fn: SubscribeFunction): void {
|
||||
export function subscribe(fn: SubscribeFunction<any, any>): void {
|
||||
subscribers.push(fn);
|
||||
}
|
||||
|
||||
export function dispatch(key: string, value: string, value2: string): void {
|
||||
export function dispatch<V, V2>(key: string, value?: V, value2?: V2): void {
|
||||
subscribers.forEach((fn) => {
|
||||
try {
|
||||
fn(key, value, value2);
|
||||
|
|
|
@ -23,7 +23,7 @@ export function toggleFilterDebug(): void {
|
|||
}
|
||||
}
|
||||
|
||||
let filteredResults: MonkeyTypes.Result[] = [];
|
||||
let filteredResults: MonkeyTypes.Result<MonkeyTypes.Mode>[] = [];
|
||||
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<MonkeyTypes.Mode>) => {
|
||||
// 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 ? ",<br>with punctuation" : "";
|
||||
const numbsctring = result.numbers
|
||||
? ",<br> " + (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 ? ",<br>with punctuation" : "";
|
||||
const numbsctring = result.numbers
|
||||
? ",<br> " + (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),
|
||||
|
|
|
@ -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(`
|
||||
<div class="buttons preset" id="${preset._id}">
|
||||
<div class="button presetButton">
|
||||
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -79,11 +79,11 @@ async function apply(): Promise<void> {
|
|||
);
|
||||
|
||||
// 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<void> {
|
|||
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<void> {
|
|||
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<void> {
|
|||
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);
|
||||
}
|
||||
}
|
||||
);
|
||||
|
|
|
@ -91,7 +91,7 @@ async function apply(): Promise<void> {
|
|||
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<void> {
|
|||
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<void> {
|
|||
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<void> {
|
|||
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();
|
||||
|
|
|
@ -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();
|
||||
});
|
||||
|
|
|
@ -1,47 +1,42 @@
|
|||
import * as DB from "../db";
|
||||
|
||||
function update(mode: string): void {
|
||||
interface PersonalBest extends MonkeyTypes.PersonalBest {
|
||||
mode2: MonkeyTypes.Mode2<MonkeyTypes.Mode>;
|
||||
}
|
||||
|
||||
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<MonkeyTypes.Mode>[]).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<MonkeyTypes.Mode>;
|
||||
|
||||
list.forEach((pb) => {
|
||||
let dateText = `-<br><span class="sub">-</span>`;
|
||||
|
@ -74,11 +69,11 @@ function update(mode: string): void {
|
|||
<td>${dateText}</td>
|
||||
</tr>
|
||||
`);
|
||||
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);
|
||||
|
||||
|
|
|
@ -15,12 +15,6 @@ type QuoteStats = {
|
|||
language: string;
|
||||
};
|
||||
|
||||
type QuoteRatings = {
|
||||
[language: string]: {
|
||||
[id: string]: number;
|
||||
};
|
||||
};
|
||||
|
||||
let quoteStats: QuoteStats | null | Record<string, never> = 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<void> {
|
|||
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);
|
||||
});
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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(
|
||||
`<div class="button tag" tagid="${tag._id}">${tag.name}</div>`
|
||||
);
|
||||
|
@ -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<MonkeyTypes.Mode>) => {
|
||||
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 + ", ";
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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")
|
||||
|
|
|
@ -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;
|
||||
|
|
97
frontend/src/scripts/types/types.d.ts
vendored
97
frontend/src/scripts/types/types.d.ts
vendored
|
@ -7,17 +7,17 @@ declare namespace MonkeyTypes {
|
|||
|
||||
type Mode2<M extends Mode> = keyof PersonalBests[M];
|
||||
|
||||
type Mode2Custom<M extends Mode> = Mode2<M> | "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<string, never>;
|
||||
active: boolean;
|
||||
personalBests?: PersonalBests;
|
||||
active?: boolean;
|
||||
}
|
||||
|
||||
interface Stats {
|
||||
|
@ -172,7 +189,7 @@ declare namespace MonkeyTypes {
|
|||
sd: number;
|
||||
}
|
||||
|
||||
interface Result {
|
||||
interface Result<M extends Mode> {
|
||||
_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<M>;
|
||||
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<Mode>[];
|
||||
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<K extends keyof any, T> = {
|
||||
[P in K]?: T;
|
||||
};
|
||||
|
||||
interface ResultFilters {
|
||||
difficulty: {
|
||||
normal: boolean;
|
||||
|
|
16
package-lock.json
generated
16
package-lock.json
generated
|
@ -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": {
|
||||
|
|
|
@ -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": {
|
||||
|
|
Loading…
Reference in a new issue