Skip to content

Commit 24a2ff1

Browse files
committed
add timer
1 parent 9abfb46 commit 24a2ff1

12 files changed

+222
-11
lines changed

.DS_Store

6 KB
Binary file not shown.

package.json

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
{
2+
"dependencies": {
3+
"typescript": "^4.5.4"
4+
}
5+
}

public/.DS_Store

0 Bytes
Binary file not shown.

public/Media/.DS_Store

6 KB
Binary file not shown.

public/Media/TS type logo.png

78.1 KB
Loading

public/Media/wrongSound.mp3

11.6 KB
Binary file not shown.

public/app.js

+31-2
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,18 @@ let ul = document.querySelector("ul");
33
let frontOfStackElem = ul.firstElementChild;
44
const keySound = document.querySelector("#key_sound");
55
const wrongSound = document.querySelector("#wrong_sound");
6+
const statDisplay = document.querySelector("#stats");
7+
const timer = new Timer();
8+
let timerStarted = false;
9+
const snippets = {
10+
test: ["hello my name is oli", "const", "="],
11+
functions: [
12+
`const capitalize = (str: string = "", lowerRest = false): string =>
13+
str.slice(0, 1).toUpperCase() +
14+
(lowerRest ? str.slice(1).toLowerCase() : str.slice(1));`,
15+
`const compact = (arr: any[]) => arr.filter(Boolean);`,
16+
],
17+
};
618
nextSet();
719
document.addEventListener("keydown", (event) => {
820
let currPress = event.key;
@@ -21,15 +33,18 @@ document.addEventListener("keydown", (event) => {
2133
frontOfStackElem = moveToNext(frontOfStackElem);
2234
return;
2335
}
24-
else if (currPress !== "Shift" && frontOfStackElem !== null) {
36+
else if (currPress !== "Shift" &&
37+
currPress !== "Meta" &&
38+
currPress !== "Alt" &&
39+
frontOfStackElem !== null) {
2540
//incorrect key
2641
isCorrect(frontOfStackElem, false);
2742
return;
2843
}
2944
});
3045
function nextSet() {
3146
clearList();
32-
const snippet = `const wrongSound = document.querySelector("#wrong_sound") as HTMLAudioElement;`;
47+
const snippet = snippets.functions[1];
3348
const itemsArr = snippet.split("");
3449
populateList(itemsArr);
3550
frontOfStackElem = ul.firstElementChild;
@@ -67,9 +82,14 @@ function isCorrect(frontOfStackElem, correct) {
6782
wrongSound.play();
6883
frontOfStackElem.classList.add("incorrect");
6984
}
85+
if (timerStarted === false) {
86+
timer.start();
87+
timerStarted = true;
88+
}
7089
}
7190
function moveToNext(frontOfStackElem) {
7291
if (frontOfStackElem.nextElementSibling === null) {
92+
getStats();
7393
frontOfStackElem = nextSet();
7494
return frontOfStackElem;
7595
}
@@ -93,3 +113,12 @@ function convertSpecial(currPress) {
93113
return currPress;
94114
}
95115
}
116+
function getStats() {
117+
const secondsExpired = Math.ceil(timer.getTime() / 1000);
118+
let chars = snippets.functions[1].length;
119+
const speed = chars / secondsExpired;
120+
statDisplay.innerHTML = `${(speed / 5) * 60} words a minute!!`;
121+
timer.stop();
122+
timer.reset();
123+
timerStarted = false;
124+
}

public/index.html

+13-5
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,21 @@
88
<link rel="stylesheet" href="./styles.css" />
99
</head>
1010
<body>
11-
<pre>
12-
<ul>
13-
</ul>
14-
</pre>
11+
<main>
12+
<header>
13+
<h1>Touch-Typed!</h1>
14+
<img src="Media/TS type logo.png" />
15+
</header>
16+
17+
<pre>
18+
<ul>
19+
</ul>
20+
</pre>
21+
<p id="stats"></p>
22+
</main>
1523
<audio id="key_sound" src="Media/keySound.m4a"></audio>
1624
<audio id="wrong_sound" src="Media/wrongSound.mp3"></audio>
17-
25+
<script src="timer.js"></script>
1826
<script src="app.js"></script>
1927
</body>
2028
</html>

public/styles.css

+28-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,27 @@
11
body {
2-
background-color: rgb(49, 42, 89);
2+
font-family: monospace;
3+
background-color: #2f74c0;
4+
}
5+
6+
main {
7+
display: flex;
8+
flex-direction: column;
9+
}
10+
11+
header {
12+
display: flex;
13+
flex-direction: row;
14+
justify-content: space-between;
15+
}
16+
17+
h1 {
18+
margin: 1rem;
19+
color: white;
20+
font-size: 60px;
21+
}
22+
23+
img {
24+
max-height: 200px;
325
}
426

527
ul {
@@ -20,3 +42,8 @@ ul > li {
2042
.incorrect {
2143
color: rgb(247, 93, 76);
2244
}
45+
46+
#stats {
47+
font-size: x-large;
48+
color: aqua;
49+
}

public/timer.js

+45
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
"use strict";
2+
class Timer {
3+
constructor() {
4+
this.isRunning = false;
5+
this.startTime = 0;
6+
this.overallTime = 0;
7+
}
8+
_getTimeElapsedSinceLastStart() {
9+
if (!this.startTime) {
10+
return 0;
11+
}
12+
return Date.now() - this.startTime;
13+
}
14+
start() {
15+
if (this.isRunning) {
16+
return console.error("Timer is already running");
17+
}
18+
this.isRunning = true;
19+
this.startTime = Date.now();
20+
}
21+
stop() {
22+
if (!this.isRunning) {
23+
return console.error("Timer is already stopped");
24+
}
25+
this.isRunning = false;
26+
this.overallTime = this.overallTime + this._getTimeElapsedSinceLastStart();
27+
}
28+
reset() {
29+
this.overallTime = 0;
30+
if (this.isRunning) {
31+
this.startTime = Date.now();
32+
return;
33+
}
34+
this.startTime = 0;
35+
}
36+
getTime() {
37+
if (!this.startTime) {
38+
return 0;
39+
}
40+
if (this.isRunning) {
41+
return this.overallTime + this._getTimeElapsedSinceLastStart();
42+
}
43+
return this.overallTime;
44+
}
45+
}

src/app.ts

+38-3
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,21 @@
1-
let ul = document.querySelector("ul")!;
1+
let ul = document.querySelector("ul")! as HTMLUListElement;
22
let frontOfStackElem = ul.firstElementChild!;
33
const keySound = document.querySelector("#key_sound") as HTMLAudioElement;
44
const wrongSound = document.querySelector("#wrong_sound") as HTMLAudioElement;
5+
const statDisplay = document.querySelector("#stats") as HTMLParagraphElement;
6+
const timer = new Timer();
7+
8+
let timerStarted = false;
9+
10+
const snippets = {
11+
test: ["hello my name is oli", "const", "="],
12+
functions: [
13+
`const capitalize = (str: string = "", lowerRest = false): string =>
14+
str.slice(0, 1).toUpperCase() +
15+
(lowerRest ? str.slice(1).toLowerCase() : str.slice(1));`,
16+
`const compact = (arr: any[]) => arr.filter(Boolean);`,
17+
],
18+
};
519

620
nextSet();
721

@@ -24,7 +38,12 @@ document.addEventListener("keydown", (event) => {
2438
//correct space key
2539
frontOfStackElem = moveToNext(frontOfStackElem);
2640
return;
27-
} else if (currPress !== "Shift" && frontOfStackElem !== null) {
41+
} else if (
42+
currPress !== "Shift" &&
43+
currPress !== "Meta" &&
44+
currPress !== "Alt" &&
45+
frontOfStackElem !== null
46+
) {
2847
//incorrect key
2948
isCorrect(frontOfStackElem, false);
3049
return;
@@ -33,7 +52,7 @@ document.addEventListener("keydown", (event) => {
3352

3453
function nextSet() {
3554
clearList();
36-
const snippet = `const wrongSound = document.querySelector("#wrong_sound") as HTMLAudioElement;`;
55+
const snippet = snippets.functions[1];
3756
const itemsArr = snippet.split("");
3857
populateList(itemsArr);
3958
frontOfStackElem = ul.firstElementChild!;
@@ -72,10 +91,16 @@ function isCorrect(frontOfStackElem: Element, correct: Boolean) {
7291
wrongSound.play();
7392
frontOfStackElem.classList.add("incorrect");
7493
}
94+
95+
if (timerStarted === false) {
96+
timer.start();
97+
timerStarted = true;
98+
}
7599
}
76100

77101
function moveToNext(frontOfStackElem: Element) {
78102
if (frontOfStackElem.nextElementSibling === null) {
103+
getStats();
79104
frontOfStackElem = nextSet();
80105
return frontOfStackElem;
81106
}
@@ -100,3 +125,13 @@ function convertSpecial(currPress: string) {
100125
return currPress;
101126
}
102127
}
128+
129+
function getStats() {
130+
const secondsExpired = Math.ceil(timer.getTime() / 1000);
131+
let chars = snippets.functions[1].length;
132+
const speed = chars / secondsExpired;
133+
statDisplay.innerHTML = `${(speed / 5) * 60} words a minute!!`;
134+
timer.stop();
135+
timer.reset();
136+
timerStarted = false;
137+
}

src/timer.ts

+62
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
class Timer {
2+
isRunning: boolean;
3+
startTime: number;
4+
overallTime: number;
5+
6+
constructor() {
7+
this.isRunning = false;
8+
this.startTime = 0;
9+
this.overallTime = 0;
10+
}
11+
12+
_getTimeElapsedSinceLastStart() {
13+
if (!this.startTime) {
14+
return 0;
15+
}
16+
17+
return Date.now() - this.startTime;
18+
}
19+
20+
start() {
21+
if (this.isRunning) {
22+
return console.error("Timer is already running");
23+
}
24+
25+
this.isRunning = true;
26+
27+
this.startTime = Date.now();
28+
}
29+
30+
stop() {
31+
if (!this.isRunning) {
32+
return console.error("Timer is already stopped");
33+
}
34+
35+
this.isRunning = false;
36+
37+
this.overallTime = this.overallTime + this._getTimeElapsedSinceLastStart();
38+
}
39+
40+
reset() {
41+
this.overallTime = 0;
42+
43+
if (this.isRunning) {
44+
this.startTime = Date.now();
45+
return;
46+
}
47+
48+
this.startTime = 0;
49+
}
50+
51+
getTime() {
52+
if (!this.startTime) {
53+
return 0;
54+
}
55+
56+
if (this.isRunning) {
57+
return this.overallTime + this._getTimeElapsedSinceLastStart();
58+
}
59+
60+
return this.overallTime;
61+
}
62+
}

0 commit comments

Comments
 (0)