// ==UserScript==
// @name 10fastfingers.com - Typing speed
// @namespace 10fastfingers.com
// @version 0.8.1.4
// @description Shows typing speed in wpm.
// @author puzzle
// @match https://10fastfingers.com/typing-test/*
// @match https://10fastfingers.com/advanced-typing-test/*
// @match https://10fastfingers.com/widget*/typingtest*
// @require https://cdn.jsdelivr.net/npm/canvas-gauges@2.1.7/gauge.min.js
// @run-at document-end
// @grant none
// @noframes
// ==/UserScript==
// jshint esnext: true
/* globals RadialGauge */
(async function() {
'use strict';
let page = null;
if (location.pathname.includes('typingtest')) {
page = 'custom';
} else if (location.pathname.includes('typing-test')) {
page = 'regular';
}
const WORD_LENGTH = 5,
SPACE = 1,
SPEED_TIME_UNIT = 60,
UPDATE_INTERVAL = 1000;
let appContainer = null;
if (page === 'regular') {
appContainer = document.querySelector('#speedtest-main');
} else if (page === 'custom') {
appContainer = document.querySelector('#settings-container');
}
const appHtml = `
<style>
#_app {
text-align: center;
position: relative;
z-index: 99999;
color: #1474ed;
background: transparent;
text-shadow: currentcolor 0 0 10px;
}
</style>
<div id='_app'>
<canvas id='gauge'></canvas>
</div>
`;
if (page === 'regular') {
appContainer.insertAdjacentHTML('afterBegin', appHtml);
} else if (page === 'custom') {
appContainer.insertAdjacentHTML('beforeBegin', appHtml);
}
let correctChars = 0,
prevWordPointer = 0;
document.addEventListener('keyup', e => {
if (e.keyCode === 32) {
if (prevWordPointer == window.word_pointer) return;
prevWordPointer = window.word_pointer;
let match = window.user_input_stream.match(/([^\s]*)\s$/),
lastTypedWord = match && match[1],
lastCorrectWord = window.words[window.word_pointer-1];
if (window.countdown && lastTypedWord === lastCorrectWord) {
correctChars += lastCorrectWord.length + SPACE;
}
}
});
// all config options can be found here - https://canvas-gauges.com/documentation/user-guide/configuration
window.gauge = new RadialGauge({
renderTo: 'gauge',
width: 250,
height: 250,
units: "WPM",
minValue: 0,
maxValue: 220,
majorTicks: [ "0", "20", "40", "60", "80", "100", "120", "140", "160", "180", "200", "220" ],
minorTicks: 2,
majorTicksDec: 5,
strokeTicks: true,
highlights: [
{
"from": 160,
"to": 220,
"color": "rgba(200, 50, 50, .75)"
}
],
borderShadowWidth: 0,
borders: false,
needleType: "arrow",
needleWidth: 2,
needleCircleSize: 7,
needleCircleOuter: true,
needleCircleInner: false,
animation: true,
animationRule: "linear",
animationDuration: UPDATE_INTERVAL - 100,
animatedValue: true,
valueBox: true,
valueBoxBorderRadius: 1.5,
valueBoxStroke: 5,
valueBoxWidth: 40,
valueInt: 3,
valueDec: 2,
colorPlate: "white",
//colorNeedle: 'blue',
//colorNeedleEnd: 'blue'
fontNumbersWeight: 700
}).draw();
function updateGauge(value) {
window.gauge.value = value;
/*window.gauge.update({
valueText: value.toFixed(2).padStart(6,0)
});*/
}
function resetValues() {
prevWordPointer = 0;
correctChars = 0;
window.gauge.value = 0;
/*window.gauge.update({
valueText: "000.00"
});*/
}
function waitUntilVarAssigned(v) {
return new Promise( (res,rej) => {
setTimeout(function check() {
if (Array.isArray(v)) {
if (v.every( i => !!window[i] )) {
res();
return;
}
} else {
if (window[v]) {
res();
return;
}
}
setTimeout(check, 500)
},0);
})
}
let resetDone = false;
let zeroCountdownOnceDone = false;
let avgSpeed = 0;
if (page === 'regular') {
await waitUntilVarAssigned('countdown');
} else if (page === 'custom') {
await waitUntilVarAssigned(['param_duration','countdown']);
}
setInterval(function() {
let duration = null;
if (page === 'regular') {
duration = 60;
} else if (page === 'custom') {
duration = window.param_duration;
}
if (window.countdown == duration) {
if (!resetDone) {
resetValues();
resetDone = true;
zeroCountdownOnceDone = false;
}
} else {
if (window.countdown === 0 && zeroCountdownOnceDone) return;
resetDone = false;
avgSpeed = correctChars*SPEED_TIME_UNIT/(duration-window.countdown)/WORD_LENGTH;
updateGauge(avgSpeed);
if (window.countdown === 0 && !zeroCountdownOnceDone) {
zeroCountdownOnceDone = true;
}
}
}, UPDATE_INTERVAL);
})();