From 7b1ccdf17b7259235678a08751697aa0ac5ddbd8 Mon Sep 17 00:00:00 2001 From: Jack Date: Thu, 30 Jul 2020 16:52:38 +0100 Subject: [PATCH] added consistency stat, updated the result page layout --- public/css/style.scss | 154 ++++++++++++++++++++++-------------------- public/index.html | 34 +++++++--- public/js/script.js | 72 +++++++++++++++++++- 3 files changed, 173 insertions(+), 87 deletions(-) diff --git a/public/css/style.scss b/public/css/style.scss index 2d8473940..859342a4f 100644 --- a/public/css/style.scss +++ b/public/css/style.scss @@ -1038,14 +1038,21 @@ key { #result { display: grid; // height: 200px; - gap: 1rem; - grid-template-columns: auto 1fr; - justify-content: center; + column-gap: 1rem; + // grid-template-columns: auto 1fr; + // justify-content: center; align-items: center; + grid-template-columns: auto 1fr; + grid-template-areas: "stats chart" + "morestats morestats" + "login login"; .chart { + grid-area: chart; + width: 100%; + canvas { - width: 100%; + width: 100% !important; height: 100%; } @@ -1062,23 +1069,49 @@ key { grid-column: 1/3; text-align: center; color: var(--sub-color); + grid-area: login; } .stats { + grid-area: stats; display: grid; - column-gap: 0.5rem; + // column-gap: 0.5rem; + gap: .5rem; justify-content: center; align-items: center; - grid-template-areas: - "wpm acc" - "wpm key" - "raw time" - "source source" - "leaderboards leaderboards" - "testType infoAndTags"; + // grid-template-areas: + // "wpm acc" + // "wpm key" + // "raw time" + // "consistency consistency" + // "source source" + // "leaderboards leaderboards" + // "testType infoAndTags"; + // grid-template-areas: + // "wpm acc key consistency testType leaderboards source" + // "wpm raw time nothing infoAndTags leaderboards source"; + grid-template-areas: "wpm" + "acc"; + + &.morestats { + display: grid; + grid-auto-flow: column; + grid-template-areas: none; + align-items: flex-start; + justify-content: flex-start; + column-gap: 2rem; + grid-area: morestats; + + // grid-template-areas: "raw consistency testType infoAndTags leaderboards source" + // "key time testType infoAndTags leaderboards source"; + .subgroup { + display: grid; + gap: .5rem; + } + } .group { - margin-bottom: 0.5rem; + // margin-bottom: 0.5rem; .top { color: var(--sub-color); @@ -1093,60 +1126,12 @@ key { } } - .testType { - align-self: baseline; - grid-area: testType; - color: var(--sub-color); - - .top { - font-size: 1rem; - line-height: 1.25rem; - } - - .bottom { - font-size: 1rem; - line-height: 1rem; - } - } - - .leaderboards { - align-self: baseline; - grid-area: leaderboards; - color: var(--sub-color); - - .top { - font-size: 1rem; - line-height: 1.25rem; - } - - .bottom { - font-size: 1rem; - line-height: 1rem; - } - } - - .source { - align-self: baseline; - grid-area: source; - color: var(--sub-color); - max-width: 15rem; - - .top { - font-size: 1rem; - line-height: 1.25rem; - } - - .bottom { - font-size: 1rem; - line-height: 1rem; - } - } .infoAndTags { display: grid; gap: 0.5rem; align-self: baseline; - grid-area: infoAndTags; + // grid-area: infoAndTags; color: var(--sub-color); .top { @@ -1164,17 +1149,18 @@ key { grid-area: wpm; .top { - font-size: 3rem; - line-height: 3rem; + font-size: 2rem; + line-height: 1rem; display: flex; - margin-top: -0.5rem; + // margin-top: -0.5rem; .crownWrapper { width: 1.7rem; overflow: hidden; height: 1.7rem; margin-left: 0.5rem; - margin-top: 0.98rem; + // margin-top: 0.98rem; + margin-top: -0.5rem; .crown { font-size: 0.7rem; @@ -1196,21 +1182,39 @@ key { } } + .testType, + .leaderboards { + .bottom { + font-size: 1rem; + line-height: 1rem; + } + } + .acc { grid-area: acc; + + .top { + font-size: 2rem; + line-height: 1rem; + } + + .bottom { + font-size: 4rem; + line-height: 4rem; + } } - .key { - grid-area: key; - } + // .key { + // grid-area: key; + // } - .time { - grid-area: time; - } + // .time { + // grid-area: time; + // } - .raw { - grid-area: raw; - } + // .raw { + // grid-area: raw; + // } } } diff --git a/public/index.html b/public/index.html index e7545f3bd..5ebc69f47 100644 --- a/public/index.html +++ b/public/index.html @@ -671,18 +671,32 @@
acc
-
-
-
char
-
-
+ +
+
+
+
+
char
+
-
+
+
+
raw
+
-
+
-
-
time
-
-
-
-
-
raw
-
-
+ +
+
+
consistency
+
-
+
+
+
time
+
-
+
+ +
test type
-
diff --git a/public/js/script.js b/public/js/script.js index 591bb21c1..fb5937384 100644 --- a/public/js/script.js +++ b/public/js/script.js @@ -79,6 +79,28 @@ function smooth(arr, windowSize, getter = (value) => value, setter) { return result; } +function stdDev(array) { + try { + const n = array.length; + const mean = array.reduce((a, b) => a + b) / n; + return Math.sqrt( + array.map((x) => Math.pow(x - mean, 2)).reduce((a, b) => a + b) / n + ); + } catch (e) { + return 0; + } +} + +function mean(array) { + try { + return ( + array.reduce((previous, current) => (current += previous)) / array.length + ); + } catch (e) { + return 0; + } +} + function showNotification(text, time) { let noti = $(".notification"); noti.text(text); @@ -665,7 +687,13 @@ function compareInput(showError) { ) { inputHistory.push(input); currentInput = ""; - if (!resultVisible) showResult(); + //last character typed, show result + if (!resultVisible) { + if (keypressPerSecond.length === 0) { + keypressPerSecond.push(currentKeypressCount); + } + showResult(); + } } // liveWPM() } @@ -1336,6 +1364,23 @@ function showResult(difficultyFailed = false) { rawWpmPerSecond = smooth(rawWpmPerSecond, 1); + let stddev = stdDev(rawWpmPerSecond); + let avg = mean(rawWpmPerSecond); + + function kogasa(cov) { + return ( + 100 * (1 - Math.tanh(cov + Math.pow(cov, 3) / 3 + Math.pow(cov, 5) / 5)) + ); + } + + let consistency = roundTo2(kogasa(stddev / avg)); + + $("#result .stats .consistency .bottom").text(Math.round(consistency) + "%"); + $("#result .stats .consistency .bottom").attr( + "aria-label", + consistency + "%" + ); + wpmOverTimeChart.data.datasets[0].borderColor = mainColor; wpmOverTimeChart.data.datasets[0].data = wpmHistory; wpmOverTimeChart.data.datasets[1].borderColor = subColor; @@ -1349,6 +1394,13 @@ function showResult(difficultyFailed = false) { ...[Math.max(...rawWpmPerSecond), Math.max(...wpmHistory)] ); + let minChartVal = Math.min( + ...[Math.min(...rawWpmPerSecond), Math.min(...wpmHistory)] + ); + + // wpmOverTimeChart.options.scales.yAxes[0].ticks.min = Math.round(minChartVal); + // wpmOverTimeChart.options.scales.yAxes[1].ticks.min = Math.round(minChartVal); + let errorsNoZero = []; for (let i = 0; i < errorsPerSecond.length; i++) { @@ -1396,6 +1448,7 @@ function showResult(difficultyFailed = false) { tags: activeTags, keySpacing: keypressStats.spacing.array, keyDuration: keypressStats.duration.array, + consistency: consistency, }; if ( config.difficulty == "normal" || @@ -1727,6 +1780,15 @@ function showResult(difficultyFailed = false) { $("#result .stats .tags .bottom").html(tagsText); } + if ( + $("#result .stats .tags").hasClass("hidden") && + $("#result .stats .info").hasClass("hidden") + ) { + $("#result .stats .infoAndTags").addClass("hidden"); + } else { + $("#result .stats .infoAndTags").removeClass("hidden"); + } + if (config.mode === "quote") { $("#result .stats .source").removeClass("hidden"); $("#result .stats .source .bottom").html(randomQuote.source); @@ -1738,6 +1800,7 @@ function showResult(difficultyFailed = false) { wpmOverTimeChart.options.scales.yAxes[1].ticks.max = maxChartVal; wpmOverTimeChart.update({ duration: 0 }); + swapElements($("#words"), $("#result"), 250, () => { $("#words").empty(); // if (config.blindMode) { @@ -2885,6 +2948,7 @@ $(document).keypress(function (event) { } if (config.mode == "time") { if (time >= config.time) { + //times up clearIntervals(); hideCaret(); testActive = false; @@ -2915,6 +2979,7 @@ $(document).keypress(function (event) { if (config.stopOnError && !thisCharCorrect) { if (config.difficulty == "master") { + //failed due to master diff when pressing a key showResult(true); if (!afkDetected) { let testNow = Date.now(); @@ -3110,6 +3175,7 @@ $(document).keydown((event) => { } else { if (config.stopOnError) { if (config.difficulty == "expert" || config.difficulty == "master") { + //failed due to diff when pressing space showResult(true); if (!afkDetected) { let testNow = Date.now(); @@ -3127,12 +3193,14 @@ $(document).keydown((event) => { currentWordIndex++; currentWordElementIndex++; if (currentWordIndex == wordsList.length) { + //submitted last word that is incorrect showResult(); return; } else if ( config.difficulty == "expert" || config.difficulty == "master" ) { + //submitted last word incorrect and failed test showResult(true); if (!afkDetected) { let testNow = Date.now(); @@ -3314,7 +3382,7 @@ let wpmOverTimeChart = new Chart(ctx, { }, display: true, scaleLabel: { - display: true, + display: false, labelString: "Seconds", fontFamily: "Roboto Mono", },