mirror of
https://github.com/monkeytypegame/monkeytype.git
synced 2025-11-09 13:44:29 +08:00
added consistency stat, updated the result page layout
This commit is contained in:
parent
a3025e310f
commit
7b1ccdf17b
3 changed files with 173 additions and 87 deletions
|
|
@ -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;
|
||||
// }
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -671,18 +671,32 @@
|
|||
<div class="top">acc</div>
|
||||
<div class="bottom" aria-label="" data-balloon-pos="up">-</div>
|
||||
</div>
|
||||
<div class="group key">
|
||||
<div class="top">char</div>
|
||||
<div class="bottom">-</div>
|
||||
|
||||
</div>
|
||||
<div class="stats morestats">
|
||||
<div class="subgroup">
|
||||
<div class="group key">
|
||||
<div class="top">char</div>
|
||||
<div class="bottom">-</div>
|
||||
</div>
|
||||
<div class="group raw">
|
||||
<div class="top">raw</div>
|
||||
<div class="bottom" aria-label="" data-balloon-pos="up">-</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="group time">
|
||||
<div class="top">time</div>
|
||||
<div class="bottom">-</div>
|
||||
</div>
|
||||
<div class="group raw">
|
||||
<div class="top">raw</div>
|
||||
<div class="bottom" aria-label="" data-balloon-pos="up">-</div>
|
||||
|
||||
<div class="subgroup">
|
||||
<div class="group flat consistency">
|
||||
<div class="top">consistency</div>
|
||||
<div class="bottom" aria-label="" data-balloon-pos="up">-</div>
|
||||
</div>
|
||||
<div class="group time">
|
||||
<div class="top">time</div>
|
||||
<div class="bottom">-</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="group testType">
|
||||
<div class="top">test type</div>
|
||||
<div class="bottom">-</div>
|
||||
|
|
|
|||
|
|
@ -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",
|
||||
},
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue