added burst heatmap to the result screen

This commit is contained in:
Miodec 2021-07-04 23:58:11 +01:00
parent a4dc77d059
commit 43fcaf5950
5 changed files with 186 additions and 9 deletions

View file

@ -371,6 +371,17 @@ export function mean(array) {
}
}
//https://www.w3resource.com/javascript-exercises/fundamental/javascript-fundamental-exercise-88.php
export function median (arr) {
try{
const mid = Math.floor(arr.length / 2),
nums = [...arr].sort((a, b) => a - b);
return arr.length % 2 !== 0 ? nums[mid] : (nums[mid - 1] + nums[mid]) / 2;
}catch(e){
return 0;
}
}
export function getReleasesFromGitHub() {
$.getJSON(
"https://api.github.com/repos/Miodec/monkeytype/releases",

View file

@ -1945,9 +1945,13 @@ export function finish(difficultyFailed = false) {
TestUI.setResultCalculating(false);
$("#words").empty();
ChartController.result.resize();
if (Config.alwaysShowWordsHistory) {
TestUI.toggleResultWords();
}
if(TestUI.heatmapEnabled){
TestUI.applyBurstHeatmap();
}
$("#testModesNotice").addClass("hidden");
},
() => {

View file

@ -15,6 +15,7 @@ import * as ManualRestart from "./manual-restart-tracker";
import * as PractiseMissed from "./practise-missed";
import * as Replay from "./replay";
import * as TestStats from "./test-stats";
import * as Misc from './misc';
export let currentWordElementIndex = 0;
export let resultVisible = false;
@ -783,6 +784,88 @@ export function toggleResultWords() {
}
}
}
export let heatmapEnabled = false;
function toggleBurstHeatmap(){
if(!heatmapEnabled){
applyBurstHeatmap();
}else{
//clear all classes
$("#resultWordsHistory .heatmapLegend").addClass('hidden');
$('#resultWordsHistory .words .word').removeClass("heatmap-0");
$('#resultWordsHistory .words .word').removeClass("heatmap-1");
$('#resultWordsHistory .words .word').removeClass("heatmap-2");
$('#resultWordsHistory .words .word').removeClass("heatmap-3");
$('#resultWordsHistory .words .word').removeClass("heatmap-4");
}
heatmapEnabled = !heatmapEnabled;
}
export function applyBurstHeatmap(){
$("#resultWordsHistory .heatmapLegend").removeClass('hidden');
let min = Math.min(...TestStats.burstHistory);
let max = Math.max(...TestStats.burstHistory);
// let step = (max - min) / 5;
// let steps = [
// {
// val: min,
// class: 'heatmap-0'
// },
// {
// val: min + (step * 1),
// class: 'heatmap-1'
// },
// {
// val: min + (step * 2),
// class: 'heatmap-2'
// },
// {
// val: min + (step * 3),
// class: 'heatmap-3'
// },
// {
// val: min + (step * 4),
// class: 'heatmap-4'
// },
// ];
let median = Misc.median(TestStats.burstHistory);
let adatm = [];
TestStats.burstHistory.forEach(burst => {
adatm.push(Math.abs(median - burst));
})
let step = Misc.mean(adatm);
// let step = Misc.stdDev(TestStats.burstHistory)/2;
let steps = [
{
val: 0,
class: 'heatmap-0'
},
{
val: median - (step * 1.5),
class: 'heatmap-1'
},
{
val: median - (step * 0.5),
class: 'heatmap-2'
},
{
val: median + (step * 0.5),
class: 'heatmap-3'
},
{
val: median + (step * 1.5),
class: 'heatmap-4'
},
];
$('#resultWordsHistory .words .word').each((index, word) => {
let wordBurstVal = parseInt($(word).attr('burst'));
let cls = '';
steps.forEach(step => {
if(wordBurstVal > step.val) cls = step.class;
})
$(word).addClass(cls);
})
}
export function highlightBadWord(index, showError) {
if (!showError) return;
@ -819,6 +902,11 @@ $(".pageTest #copyWordsListButton").click(async (event) => {
}
});
$(".pageTest #toggleBurstHeatmap").click(async (event) => {
toggleBurstHeatmap();
});
$(document).on("mouseleave", "#resultWordsHistory .words .word", (e) => {
$(".wordInputAfter").remove();
});

View file

@ -1879,6 +1879,43 @@ key {
// grid-area: wordsHistory;
color: var(--sub-color);
grid-column: 1/3;
.heatmapLegend{
display: inline-grid;
grid-template-columns: auto auto auto;
gap: 1rem;
font-size: .75rem;
color: var(--sub-color);
width: min-content;
.boxes{
display: flex;
.box{
width: 1rem;
height: 1rem;
}
.box:nth-child(1){
background: var(--colorful-error-color);
border-radius: var(--roundness) 0 0 var(--roundness);
}
.box:nth-child(2){
background: var(--colorful-error-color);
filter: opacity(0.6);
}
.box:nth-child(3){
background: var(--sub-color);
}
.box:nth-child(4){
background: var(--main-color);
filter: opacity(0.6);
}
.box:nth-child(5){
background: var(--main-color);
border-radius: 0 var(--roundness) var(--roundness) 0;
}
}
}
.title{
user-select: none;
}
.words {
display: flex;
flex-wrap: wrap;
@ -1888,6 +1925,32 @@ key {
.word {
position: relative;
margin: 0.18rem 0.6rem 0.15rem 0;
letter.correct {
color: var(--text-color);
}
letter.incorrect {
color: var(--error-color);
}
letter.incorrect.extra {
color: var(--error-extra-color);
}
&.heatmap-0 letter{
color: var(--colorful-error-color);
}
&.heatmap-1 letter{
color: var(--colorful-error-color);
filter: opacity(0.6);
}
&.heatmap-2 letter{
color: var(--sub-color);
}
&.heatmap-3 letter{
color: var(--main-color);
filter: opacity(0.6);
}
&.heatmap-4 letter{
color: var(--main-color);
}
}
&.rightToLeftTest {
//flex-direction: row-reverse; // no need for hacking 😉, CSS fully support right-to-left languages
@ -1903,15 +1966,6 @@ key {
}
}
}
.correct {
color: var(--text-color);
}
.incorrect {
color: var(--error-color);
}
.incorrect.extra {
color: var(--error-extra-color);
}
}
.chart {

View file

@ -1440,6 +1440,26 @@
>
<i class="fas fa-copy"></i>
</span>
<span
id="toggleBurstHeatmap"
class="icon-button"
aria-label="Toggle burst heatmap"
data-balloon-pos="up"
style="display: inline-block"
>
<i class="fas fa-fire-alt"></i>
</span>
<div class="heatmapLegend hidden">
<div>slow</div>
<div class="boxes">
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
</div>
<div>fast</div>
</div>
</div>
<div class="words"></div>
</div>