./exe/speed_typer/readme.txt
This is a training game for typing. Just type the character you see on the screen, and practice to improve your speed. Try to type without looking at the keyboard. When your speed gets above 50 characters per minute, you will begin to see capital letters and special symbols. 

In the code:

Pay attention to the use of flexboxes for layout.

This program is a good example of how JavaScript can target elements of the HTML document, dynamically changing the contents of the page for simple interactivity. 
./exe/speed_typer/main.html
<!doctype html>

<html lang="en">
<head>
  <meta charset="utf-8">

  <title>Ѭ</title>
<link href="style.css" rel="stylesheet"/>
</head>


<body>

	<div id="container">
		<div id="timer">type the characters you see</div>
		<div id="count">0</div>
		<div id="letter"></div>
	</div>
	<script src="game.js"></script>

</body>
</html>
./exe/speed_typer/style.css
body {
	background-color: #123;
	cursor: crosshair;
	display:flex;
	flex-direction : column;
	justify-content: center;
	align-items: center;
	background: linear-gradient(180deg, #123, #102030);
}

div {
	background-color: #102030;
	border: inset;
	border-color: #345;
	display:flex;
	flex-direction : column;
	justify-content: center;
	color: #abf;
	text-align: center;
	padding: 20px;
}

#letter {
	background-color: #0b1b2b;
	padding: 20px;
	border: inset;
	border-color: #345;
	font : 420px Courier;
	margin-top: 10vh;
	text-align: center;
}

#timer, #count {
	border:  ridge;
	border-color: #345;
	padding: 5px;
	padding-right: 10vw;
	padding-left: 10vw;
}

#count {
	margin-top: 5px;
	font-size: 150%;	
}

num {
	color: #297;
}

spec {
	color: #993;
}

upper {
	color: #bbf;
	text-shadow: 20px 20px #000000;
}
./exe/speed_typer/game.js
const timer  = document.querySelector("#timer");
const letter = document.querySelector("#letter");
const counter = document.querySelector("#count");
const chars = Array.from("!1@2#3$4%5^6&7*8(9)0_-+=QqWwEeRrTtYyUuIiOoPp{[}]|AaSsDdFfGgHhJjKkLl:;\"?>.<,MmNnBbVvCcXxZz");
const lower = Array.from("abcdefghijklmnopqrstuvwxyz;,.");
const special = "[]{}()|<>*&^%$#@!_-+=,.;:\"";
let prev;
let current_letter; 
let count = 0;
let started = 0;


Array.prototype.sample = function(){
	return this[Math.floor(Math.random()*this.length)];
}

function write_letter(){
	while (current_letter === prev){ // to prevent adjacent repeats
		if (cpm > 50)
			current_letter = chars.sample();
		else
			current_letter = lower.sample();
	}
	prev = current_letter;
	if (special.includes(current_letter))
		letter.innerHTML = "<spec>" + current_letter + "</spec>";
	else if (current_letter >= '0' && current_letter <= '9')
		letter.innerHTML = "<num>" + current_letter + "</num>";
	else if (current_letter >= 'A' && current_letter <= 'Z')
		letter.innerHTML = "<upper>" + current_letter + "</upper>";
	else
		letter.innerHTML = current_letter;
}

let START_TIME;

let elapsed, cps, cpm;
function updateAverage() {
	if (count < 5) // wait 5 chars before calculating average
		return;
	now = new Date().getTime()/1000;
	elapsed = now - START_TIME;
	cpm = Math.round(count/elapsed * 60);
	timer.innerHTML = cpm.toString();
	timer.innerHTML = timer.innerHTML + " characters per minute";
}

document.addEventListener("keydown", e => {
	if (started == 0){
		START_TIME = new Date().getTime()/1000;
		started = 1;
	}
	const insertedText = e.key;

	if (insertedText === current_letter) {
		write_letter();
		count++;
		counter.innerHTML = count;
		updateAverage();
	}
});

window.onload = write_letter;