mirror of https://github.com/shadowfacts/type.git
WPM tracking
This commit is contained in:
parent
3d780753c4
commit
59999d084f
13
css/main.css
13
css/main.css
|
@ -33,10 +33,23 @@
|
|||
height: 20px;
|
||||
}
|
||||
|
||||
#toolbar > #info {
|
||||
float: right;
|
||||
margin-right: 14px;
|
||||
}
|
||||
|
||||
#toolbar > #info > #paused {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
#content {
|
||||
margin-top: 33px;
|
||||
}
|
||||
|
||||
#content.paused > .CodeMirror {
|
||||
opacity: 0.5;
|
||||
}
|
||||
|
||||
/* Index */
|
||||
.prev-list {
|
||||
padding: 0px;
|
||||
|
|
69
js/type.js
69
js/type.js
|
@ -4,6 +4,9 @@ var incompleteMark;
|
|||
var focused = false;
|
||||
let invalids = [];
|
||||
var fileLines;
|
||||
// WPM tracking
|
||||
var lastStartTime;
|
||||
var elapsedTime;
|
||||
|
||||
let hash = window.location.hash.substring(1);
|
||||
let hashBits = hash.split("/");
|
||||
|
@ -114,7 +117,7 @@ function setup(data, mime) {
|
|||
className: "incomplete"
|
||||
});
|
||||
|
||||
focused = true;
|
||||
resume();
|
||||
|
||||
editor.on("focus", handleFocus);
|
||||
editor.on("blur", handleBlur);
|
||||
|
@ -130,11 +133,11 @@ function setup(data, mime) {
|
|||
}
|
||||
|
||||
function handleFocus() {
|
||||
focused = true;
|
||||
resume();
|
||||
}
|
||||
|
||||
function handleBlur() {
|
||||
focused = false;
|
||||
pause();
|
||||
}
|
||||
|
||||
function handleMouseDown(instance, event) {
|
||||
|
@ -168,6 +171,14 @@ function handleKeyDown(event) {
|
|||
} else if (event.keyCode == 9) { // tab
|
||||
event.preventDefault();
|
||||
handleTab(event);
|
||||
} else if (event.keyCode == 27) { // escape
|
||||
event.preventDefault();
|
||||
pause();
|
||||
}
|
||||
} else {
|
||||
if (event.keyCode == 27) {
|
||||
event.preventDefault();
|
||||
resume();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -221,6 +232,7 @@ function handleEnter(event) {
|
|||
}
|
||||
}
|
||||
updateIncompleteMark();
|
||||
updateWPM();
|
||||
save();
|
||||
} else {
|
||||
goToNextChunk();
|
||||
|
@ -437,6 +449,7 @@ function load() {
|
|||
let chunk = val[filePath].chunks[val[filePath].chunk];
|
||||
loadInvalids(chunk);
|
||||
loadCursor(chunk);
|
||||
loadElapsedTime(chunk);
|
||||
} else {
|
||||
save();
|
||||
}
|
||||
|
@ -458,6 +471,7 @@ function save() {
|
|||
let chunk = file.chunks[file.chunk];
|
||||
saveInvalids(chunk);
|
||||
saveCursor(chunk);
|
||||
saveElapsedTime(chunk);
|
||||
|
||||
localforage.setItem(repo, val)
|
||||
.catch((e) => {
|
||||
|
@ -515,6 +529,14 @@ function saveCursor(obj) {
|
|||
obj.cursor = editor.getCursor();
|
||||
}
|
||||
|
||||
function loadElapsedTime(obj) {
|
||||
elapsedTime = obj.elapsedTime;
|
||||
}
|
||||
|
||||
function saveElapsedTime(obj) {
|
||||
obj.elapsedTime = elapsedTime;
|
||||
}
|
||||
|
||||
function setTheme(theme) {
|
||||
if (theme != "default") {
|
||||
$("head").append(`<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.19.0/theme/${theme}.min.css">`);
|
||||
|
@ -532,6 +554,47 @@ function setCursor(pos) {
|
|||
}
|
||||
}
|
||||
|
||||
function updateWPM() {
|
||||
if (focused) {
|
||||
// update elapsed time
|
||||
if (!elapsedTime || isNaN(elapsedTime)) {
|
||||
elapsedTime = Date.now() - lastStartTime;
|
||||
} else {
|
||||
elapsedTime += Date.now() - lastStartTime;
|
||||
}
|
||||
lastStartTime = Date.now();
|
||||
}
|
||||
|
||||
// calculate words typed
|
||||
let typed = editor.doc.getRange({ line: 0, ch: 0 }, editor.getCursor());
|
||||
let words = typed.split(/[\s,\.]+/).length;
|
||||
|
||||
let seconds = elapsedTime / 1000;
|
||||
if (seconds >= 60) {
|
||||
// update real WPM
|
||||
let minutes = seconds / 60;
|
||||
$("#wpm").text(Math.round(words / minutes));
|
||||
} else {
|
||||
// extrapolate forwards
|
||||
let scaledWords = words / (seconds / 60);
|
||||
$("#wpm").text(Math.round(scaledWords));
|
||||
}
|
||||
}
|
||||
|
||||
function pause() {
|
||||
focused = false;
|
||||
elapsedTime += Date.now() - lastStartTime;
|
||||
$("#paused").text("Paused");
|
||||
$("#content").addClass("paused");
|
||||
}
|
||||
|
||||
function resume() {
|
||||
focused = true;
|
||||
lastStartTime = Date.now();
|
||||
$("#paused").text("");
|
||||
$("#content").removeClass("paused");
|
||||
}
|
||||
|
||||
String.prototype.hasOnlyWhiteSpaceBeforeIndex = function(index) {
|
||||
return this.substring(index) == this.trim();
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue