diff --git a/gulpfile.js b/gulpfile.js index 356f31ad6..a99782262 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -150,7 +150,7 @@ const refactoredSrc = [ "./src/js/test/manual-restart-tracker.js", "./src/js/test/test-stats.js", "./src/js/test/focus.js", - "./src/js/test/practise-missed.js", + "./src/js/test/practise-words.js", "./src/js/test/test-ui.js", "./src/js/test/keymap.js", "./src/js/test/live-wpm.js", diff --git a/src/js/commandline-lists.js b/src/js/commandline-lists.js index 46a32a744..14b299e6c 100644 --- a/src/js/commandline-lists.js +++ b/src/js/commandline-lists.js @@ -8,7 +8,7 @@ import * as ThemeController from "./theme-controller"; import * as CustomTextPopup from "./custom-text-popup"; import * as ManualRestart from "./manual-restart-tracker"; import Config, * as UpdateConfig from "./config"; -import * as PractiseMissed from "./practise-missed"; +import * as PractiseWords from "./practise-words"; import * as TestUI from "./test-ui"; import * as TestLogic from "./test-logic"; import * as Funbox from "./funbox"; @@ -2082,6 +2082,36 @@ let commandsPageWidth = { ], }; +let commandsPractiseWords = { + title: "Practice words...", + list: [ + { + id: "practiseWordsMissed", + display: "missed", + noIcon: true, + exec: () => { + PractiseWords.init(true, false); + }, + }, + { + id: "practiseWordsSlow", + display: "slow", + noIcon: true, + exec: () => { + PractiseWords.init(false, true); + }, + }, + { + id: "practiseWordsBoth", + display: "both", + noIcon: true, + exec: () => { + PractiseWords.init(true, true); + }, + }, + ], +}; + export let themeCommands = { title: "Theme...", configKey: "theme", @@ -2764,16 +2794,12 @@ export let defaultCommands = { }, }, { - id: "practiceMissedWords", - display: "Practice missed words", + id: "practiseWords", + display: "Practice words...", icon: "fa-exclamation-triangle", - exec: () => { - PractiseMissed.init(); - }, + subgroup: commandsPractiseWords, available: () => { - return ( - TestUI.resultVisible && Object.keys(TestStats.missedWords).length > 0 - ); + return TestUI.resultVisible; }, }, { diff --git a/src/js/config.js b/src/js/config.js index 4403e09fb..46e4dcd57 100644 --- a/src/js/config.js +++ b/src/js/config.js @@ -1554,8 +1554,10 @@ export function setBurstHeatmap(value, nosave) { value = false; } config.burstHeatmap = value; - TestUI.applyBurstHeatmap(); - if (!nosave) saveToLocalStorage(); + if (!nosave) { + TestUI.applyBurstHeatmap(); + saveToLocalStorage(); + } } export function apply(configObj) { diff --git a/src/js/test/practise-missed.js b/src/js/test/practise-missed.js deleted file mode 100644 index 80fc9790c..000000000 --- a/src/js/test/practise-missed.js +++ /dev/null @@ -1,43 +0,0 @@ -import * as TestStats from "./test-stats"; -import * as Notifications from "./notifications"; -import Config, * as UpdateConfig from "./config"; -import * as CustomText from "./custom-text"; -import * as TestLogic from "./test-logic"; - -export let before = { - mode: null, - punctuation: null, - numbers: null, -}; - -export function init() { - if (Object.keys(TestStats.missedWords).length == 0) { - Notifications.add("You haven't missed any words.", 0); - return; - } - let mode = before.mode === null ? Config.mode : before.mode; - let punctuation = - before.punctuation === null ? Config.punctuation : before.punctuation; - let numbers = before.numbers === null ? Config.numbers : before.numbers; - UpdateConfig.setMode("custom"); - let newCustomText = []; - Object.keys(TestStats.missedWords).forEach((missedWord) => { - for (let i = 0; i < TestStats.missedWords[missedWord]; i++) { - newCustomText.push(missedWord); - } - }); - CustomText.setText(newCustomText); - CustomText.setIsWordRandom(true); - CustomText.setWord(Object.keys(TestStats.missedWords).length * 5); - - TestLogic.restart(false, false, false, true); - before.mode = mode; - before.punctuation = punctuation; - before.numbers = numbers; -} - -export function resetBefore() { - before.mode = null; - before.punctuation = null; - before.numbers = null; -} diff --git a/src/js/test/practise-words.js b/src/js/test/practise-words.js new file mode 100644 index 000000000..fe7d21ad5 --- /dev/null +++ b/src/js/test/practise-words.js @@ -0,0 +1,139 @@ +import * as TestStats from "./test-stats"; +import * as Notifications from "./notifications"; +import Config, * as UpdateConfig from "./config"; +import * as CustomText from "./custom-text"; +import * as TestLogic from "./test-logic"; + +export let before = { + mode: null, + punctuation: null, + numbers: null, +}; + +export function init(missed, slow) { + let limit; + if ((missed && !slow) || (!missed && slow)) { + limit = 20; + } else if (missed && slow) { + limit = 10; + } + + let sortableMissedWords = []; + if (missed) { + Object.keys(TestStats.missedWords).forEach((missedWord) => { + sortableMissedWords.push([missedWord, TestStats.missedWords[missedWord]]); + }); + sortableMissedWords.sort((a, b) => { + return b[1] - a[1]; + }); + sortableMissedWords = sortableMissedWords.slice(0, limit); + } + + if (missed && !slow && sortableMissedWords.length == 0) { + Notifications.add("You haven't missed any words", 0); + return; + } + + let sortableSlowWords = []; + if (slow) { + sortableSlowWords = TestLogic.words.get().map(function (e, i) { + return [e, TestStats.burstHistory[i]]; + }); + sortableSlowWords.sort((a, b) => { + return a[1] - b[1]; + }); + sortableSlowWords = sortableSlowWords.slice( + 0, + Math.min(limit, Math.round(TestLogic.words.length * 0.2)) + ); + } + + // console.log(sortableMissedWords); + // console.log(sortableSlowWords); + + let newCustomText = []; + sortableMissedWords.forEach((missed, index) => { + for (let i = 0; i < missed[1]; i++) { + newCustomText.push(missed[0]); + } + }); + + sortableSlowWords.forEach((slow, index) => { + for (let i = 0; i < sortableSlowWords.length - index; i++) { + newCustomText.push(slow[0]); + } + }); + + // console.log(newCustomText); + + let mode = before.mode === null ? Config.mode : before.mode; + let punctuation = + before.punctuation === null ? Config.punctuation : before.punctuation; + let numbers = before.numbers === null ? Config.numbers : before.numbers; + UpdateConfig.setMode("custom"); + + CustomText.setText(newCustomText); + CustomText.setIsWordRandom(true); + CustomText.setWord( + (sortableSlowWords.length + sortableMissedWords.length) * 5 + ); + + TestLogic.restart(false, false, false, true); + before.mode = mode; + before.punctuation = punctuation; + before.numbers = numbers; +} + +export function resetBefore() { + before.mode = null; + before.punctuation = null; + before.numbers = null; +} + +export function showPopup() { + if ($("#practiseWordsPopupWrapper").hasClass("hidden")) { + $("#practiseWordsPopupWrapper") + .stop(true, true) + .css("opacity", 0) + .removeClass("hidden") + .animate({ opacity: 1 }, 100); + } +} + +function hidePopup() { + if (!$("#practiseWordsPopupWrapper").hasClass("hidden")) { + $("#practiseWordsPopupWrapper") + .stop(true, true) + .css("opacity", 1) + .animate( + { + opacity: 0, + }, + 100, + (e) => { + $("#practiseWordsPopupWrapper").addClass("hidden"); + } + ); + } +} + +$("#practiseWordsPopupWrapper").click((e) => { + if ($(e.target).attr("id") === "practiseWordsPopupWrapper") { + hidePopup(); + } +}); + +$("#practiseWordsPopup .button.missed").click(() => { + hidePopup(); + init(true, false); +}); + +$("#practiseWordsPopup .button.slow").click(() => { + hidePopup(); + init(false, true); +}); + +$("#practiseWordsPopup .button.both").click(() => { + hidePopup(); + init(true, true); +}); diff --git a/src/js/test/test-logic.js b/src/js/test/test-logic.js index 54dc52ee9..ccd42a92a 100644 --- a/src/js/test/test-logic.js +++ b/src/js/test/test-logic.js @@ -5,7 +5,7 @@ import * as Misc from "./misc"; import * as Notifications from "./notifications"; import * as CustomText from "./custom-text"; import * as TestStats from "./test-stats"; -import * as PractiseMissed from "./practise-missed"; +import * as PractiseWords from "./practise-words"; import * as ShiftTracker from "./shift-tracker"; import * as Focus from "./focus"; import * as Funbox from "./funbox"; @@ -529,7 +529,7 @@ export async function init() { randomWord = CustomText.text[i]; } else if ( Config.mode == "custom" && - (wordset.length < 3 || PractiseMissed.before.mode !== null) + (wordset.length < 3 || PractiseWords.before.mode !== null) ) { randomWord = wordset[Math.floor(Math.random() * wordset.length)]; } else { @@ -775,15 +775,15 @@ export function restart( } if ( - PractiseMissed.before.mode !== null && + PractiseWords.before.mode !== null && !withSameWordset && !practiseMissed ) { Notifications.add("Reverting to previous settings.", 0); - UpdateConfig.setMode(PractiseMissed.before.mode); - UpdateConfig.setPunctuation(PractiseMissed.before.punctuation); - UpdateConfig.setNumbers(PractiseMissed.before.numbers); - PractiseMissed.resetBefore(); + UpdateConfig.setMode(PractiseWords.before.mode); + UpdateConfig.setPunctuation(PractiseWords.before.punctuation); + UpdateConfig.setNumbers(PractiseWords.before.numbers); + PractiseWords.resetBefore(); } let repeatWithPace = false; diff --git a/src/js/test/test-ui.js b/src/js/test/test-ui.js index 8c72ee4de..a4c68f817 100644 --- a/src/js/test/test-ui.js +++ b/src/js/test/test-ui.js @@ -12,7 +12,7 @@ import * as CommandlineLists from "./commandline-lists"; import * as Commandline from "./commandline"; import * as OutOfFocus from "./out-of-focus"; import * as ManualRestart from "./manual-restart-tracker"; -import * as PractiseMissed from "./practise-missed"; +import * as PractiseWords from "./practise-words"; import * as Replay from "./replay"; import * as TestStats from "./test-stats"; import * as Misc from "./misc"; @@ -796,6 +796,16 @@ export function applyBurstHeatmap() { $("#resultWordsHistory .heatmapLegend").removeClass("hidden"); let min = Math.min(...TestStats.burstHistory); let max = Math.max(...TestStats.burstHistory); + + let burstlist = TestStats.burstHistory; + + if ( + TestLogic.input.getHistory(TestLogic.input.getHistory().length - 1) + .length !== TestLogic.words.getCurrent().length + ) { + burstlist = burstlist.splice(0, burstlist.length - 1); + } + // let step = (max - min) / 5; // let steps = [ // { @@ -819,13 +829,13 @@ export function applyBurstHeatmap() { // class: 'heatmap-4' // }, // ]; - let median = Misc.median(TestStats.burstHistory); + let median = Misc.median(burstlist); let adatm = []; - TestStats.burstHistory.forEach((burst) => { + burstlist.forEach((burst) => { adatm.push(Math.abs(median - burst)); }); let step = Misc.mean(adatm); - // let step = Misc.stdDev(TestStats.burstHistory)/2; + // let step = Misc.stdDev(burstlist)/2; let steps = [ { val: 0, @@ -994,14 +1004,16 @@ $(document.body).on("click", "#restartTestButton", () => { } }); -$(document).on("keypress", "#practiseMissedWordsButton", (event) => { - if (event.keyCode == 13) { - PractiseMissed.init(); - } +$(document).on("keypress", "#practiseWordsButton", (event) => { + // if (event.keyCode == 13) { + // PractiseWords.init(); + // } + PractiseWords.showPopup(); }); -$(document.body).on("click", "#practiseMissedWordsButton", () => { - PractiseMissed.init(); +$(document.body).on("click", "#practiseWordsButton", () => { + // PractiseWords.init(); + PractiseWords.showPopup(); }); $(document).on("keypress", "#nextTestButton", (event) => { diff --git a/src/sass/style.scss b/src/sass/style.scss index ca3af016a..ab515160b 100644 --- a/src/sass/style.scss +++ b/src/sass/style.scss @@ -714,7 +714,8 @@ label.checkbox { } #customWordAmountPopupWrapper, -#customTestDurationPopupWrapper { +#customTestDurationPopupWrapper, +#practiseWordsPopupWrapper { width: 100%; height: 100%; background: rgba(0, 0, 0, 0.75); @@ -728,7 +729,8 @@ label.checkbox { padding: 5rem 0; #customWordAmountPopup, - #customTestDurationPopup { + #customTestDurationPopup, + #practiseWordsPopup { background: var(--bg-color); border-radius: var(--roundness); padding: 2rem; @@ -745,6 +747,11 @@ label.checkbox { font-size: 0.75rem; color: var(--sub-color); } + + .text { + font-size: 1rem; + color: var(--text-color); + } } #customTestDurationPopup { @@ -2381,7 +2388,7 @@ key { #saveScreenshotButton, #restartTestButtonWithSameWordset, #nextTestButton, -#practiseMissedWordsButton, +#practiseWordsButton, #watchReplayButton { position: relative; border-radius: var(--roundness); diff --git a/static/index.html b/static/index.html index 81de5f076..ef02c277e 100644 --- a/static/index.html +++ b/static/index.html @@ -126,6 +126,20 @@
+