Want to contribute? Fork me on Codeberg.org!
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
This repo is archived. You can view files and clone it, but cannot push or open issues/pull-requests.

255 lines
6.6 KiB

2 years ago
// modified from https://stackoverflow.com/a/14051331
// Issue is keycode conversion for non-alphanumeric keys (e.g. period)
// is not accurate
function convertKeyCode(evt) {
var chara = "";
var keyCode = (evt.which) ? evt.which : evt.keyCode;
var shift = evt.shiftKey;
if (keyCode == 19)
chara = "pause/break";
if (keyCode == 48)
chara = (shift) ? ")" : "0";
if (keyCode == 49)
chara = (shift) ? "!" : "1";
if (keyCode == 50)
chara = (shift) ? "@" : "2";
if (keyCode == 51)
chara = (shift) ? "#" : "3";
if (keyCode == 52)
chara = (shift) ? "$" : "4";
if (keyCode == 53)
chara = (shift) ? "%" : "5";
if (keyCode == 54)
chara = (shift) ? "^" : "6";
if (keyCode == 55)
chara = (shift) ? "&" : "7";
if (keyCode == 56)
chara = (shift) ? "*" : "8";
if (keyCode == 57)
chara = (shift) ? "(" : "9";
if (keyCode == 65)
chara = (shift) ? "A" : "a";
if (keyCode == 66)
chara = (shift) ? "B" : "b";
if (keyCode == 67)
chara = (shift) ? "C" : "c";
if (keyCode == 68)
chara = (shift) ? "D" : "d";
if (keyCode == 69)
chara = (shift) ? "E" : "e";
if (keyCode == 70)
chara = (shift) ? "F" : "f";
if (keyCode == 71)
chara = (shift) ? "G" : "g";
if (keyCode == 72)
chara = (shift) ? "H" : "h";
if (keyCode == 73)
chara = (shift) ? "I" : "i";
if (keyCode == 74)
chara = (shift) ? "J" : "j";
if (keyCode == 75)
chara = (shift) ? "K" : "k";
if (keyCode == 76)
chara = (shift) ? "L" : "l";
if (keyCode == 77)
chara = (shift) ? "M" : "m";
if (keyCode == 78)
chara = (shift) ? "N" : "n";
if (keyCode == 79)
chara = (shift) ? "O" : "o";
if (keyCode == 80)
chara = (shift) ? "P" : "p";
if (keyCode == 81)
chara = (shift) ? "Q" : "q";
if (keyCode == 82)
chara = (shift) ? "R" : "r";
if (keyCode == 83)
chara = (shift) ? "S" : "s";
if (keyCode == 84)
chara = (shift) ? "T" : "t";
if (keyCode == 85)
chara = (shift) ? "U" : "u";
if (keyCode == 86)
chara = (shift) ? "V" : "v";
if (keyCode == 87)
chara = (shift) ? "W" : "w";
if (keyCode == 88)
chara = (shift) ? "X" : "x";
if (keyCode == 89)
2 years ago
chara = (shift) ? "Y" : "y"; if (keyCode == 90)
2 years ago
chara = (shift) ? "Z" : "z";
if (keyCode == 93)
chara = "select key";
if (keyCode == 186 || keyCode == 59)
chara = ";";
if (keyCode == 187 || keyCode == 61)
chara = "=";
if (keyCode == 188)
chara = ",";
if (keyCode == 189 || keyCode == 173)
chara = "-";
if (keyCode == 190)
chara = ".";
if (keyCode == 191)
chara = "/";
if (keyCode == 192)
chara = "`";
if (keyCode == 219)
chara = (shift) ? "{" : "[";
if (keyCode == 220)
chara = "\\";
if (keyCode == 221)
chara = (shift) ? "}" : "]";
if (keyCode == 222)
chara = "'";
return chara;
}
const wordDisplay = document.getElementById("word");
const input = document.getElementById("input");
const timer = document.getElementById("timer");
const hintDisplay = document.getElementById("hint");
const incorrect = document.getElementById("incorrectSfx");
const correct = document.getElementById("correctSfx");
const success = document.getElementById("successSfx");
2 years ago
const leftShiftCode = 32; // space
const rightShiftCode = 16; // shift key
let leftShift = false;
let rightShift = false;
addEventListener("keydown", event => {
switch(event.keyCode) {
case leftShiftCode:
leftShift = true;
event.preventDefault();
break;
case rightShiftCode:
rightShift = true;
event.preventDefault();
break;
}
});
addEventListener("keyup", event => {
switch(event.keyCode) {
case leftShiftCode:
leftShift = false;
break;
case rightShiftCode:
rightShift = false;
break;
}
});
2 years ago
const check = () => {
if (input.value == word) {
if (repeats == 0) {
success.currentTime = 0;
success.play();
} else {
correct.currentTime = 0;
correct.play();
}
clearTimeout(incorrectTimeout);
clearTimeout(timerTimeout);
2 years ago
wordDisplay.style.color = "green";
wordDisplay.innerHTML = `${word}`;
2 years ago
setTimeout(() => {
wordDisplay.style.color = "";
reset();
}, 1000);
2 years ago
}
2 years ago
};
addEventListener("compositionend", event => check());
input.addEventListener("keydown", e => {
2 years ago
const pressed = convertKeyCode(e).toLowerCase(); // String.fromCharCode(e.keyCode).toLowerCase();
if (keymap[pressed] !== undefined) {
let valueIndex = 0;
if (leftShift && keymap[pressed][1]) {
valueIndex = 1;
} else if (rightShift && keymap[pressed][2]) {
valueIndex = 2;
}
input.value += keymap[pressed][valueIndex];
2 years ago
check();
2 years ago
e.preventDefault();
} else if (pressed == " ") {
e.preventDefault();
}
});
// window.requestAnimationFrame() might be better suited
// https://developer.mozilla.org/en-US/docs/Web/API/window/requestAnimationFrame
let typeTimePerKana = 2; // in seconds
const typeTimePerKanaInput = document.getElementById("timePerKana");
typeTimePerKanaInput.value = typeTimePerKana;
typeTimePerKanaInput.addEventListener("change", (e) => {
typeTimePerKana = typeTimePerKanaInput.value;
});
const timerFPS = 60;
let incorrectTimeout = null;
2 years ago
let timerTimeout = null;
let word = null;
let repeats = 0;
let failed = false;
2 years ago
let problemWords = [];
let problemTimes = [];
2 years ago
const reset = () => {
2 years ago
failed = false;
2 years ago
input.value = "";
hint.innerHTML = "";
timer.value = 1;
if (repeats == 0) {
2 years ago
if (problemTimes.length > 0 && new Date() - problemTimes[0] > 60000) {
word = problemWords[0];
problemWords.shift();
problemTimes.shift();
} else {
word = words[Math.round(Math.random() * words.length)];
}
}
wordDisplay.innerHTML = word;
2 years ago
const typeTime = typeTimePerKana * word.length;
incorrectTimeout = setTimeout(() => {
2 years ago
if (!problemWords.includes(word)) {
problemWords.push(word);
problemTimes.push(new Date());
}
repeats += repeats == 0 ? 3 : 1;
failed = true;
wordDisplay.innerHTML = `${word}`;
incorrect.currentTime = 0;
incorrect.play();
2 years ago
for (let i = 0; i < word.length; i++) {
const letter = word[i];
let key = null;
let index = null;
for (let otherKey in keymap) {
for (let i = 0; i < keymap[otherKey].length && !key; i++) {
if (keymap[otherKey][i] == letter) {
key = otherKey;
index = i;
}
}
}
let t = `<h3>${letter.toUpperCase()}<kbd`;
2 years ago
if (index > 0) {
t += ' style="background: ';
2 years ago
if (index == 1) {
t += "yellow";
2 years ago
} else if (index == 2) {
t += "cyan";
2 years ago
} else if (index == 3) {
t += "magenta";
2 years ago
}
t += '"';
2 years ago
}
t += `>${key}</kbd></h3>`;
2 years ago
hint.innerHTML += t;
}
}, typeTime * 1000);
clearInterval(timerTimeout);
timerTimeout = setInterval(() => {
timer.value -= (1 / timerFPS) / typeTime;
}, 1000 / timerFPS);
if (repeats > 0) {
repeats--;
}
2 years ago
};
reset();