-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathscript.js
314 lines (265 loc) · 10.6 KB
/
script.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
// Elements
const sentenceEl = document.getElementById("sentence");
const inputEl = document.getElementById("input");
const startBtn = document.getElementById("start-btn");
const nextRoundBtn = document.getElementById("next-round-btn");
const quitBtn = document.getElementById("quit-btn");
const wpmEl = document.getElementById("wpm");
const accuracyEl = document.getElementById("accuracy");
const countdownEl = document.getElementById("countdown");
const highScoreEl = document.getElementById("high-score");
const themeSwitch = document.getElementById("theme-switch");
const themeText = document.getElementById("theme-mode");
// New Game Button (added dynamically)
let newGameBtn = document.createElement("button");
newGameBtn.textContent = "New Game";
newGameBtn.classList.add("action-btn"); // Add the action-btn class for consistent styling
newGameBtn.style.display = "none"; // Initially hidden
newGameBtn.addEventListener("click", startNewGame);
document.querySelector(".game-buttons").appendChild(newGameBtn);
// Sentences Array
const sentences = [
"The quick brown fox jumps over the lazy dog while the sun sets behind the mountains and the stars begin to sparkle in the night sky.",
"A journey of a thousand miles begins with a single step, but it also requires courage, determination, and perseverance to reach the destination.",
"In the age of rapid technological advancements, staying updated with the latest innovations has become an essential skill for survival and growth.",
"Typing games are an excellent way to improve speed, accuracy, and confidence while also enhancing focus and hand-eye coordination.",
"The curious cat cautiously approached the garden, where butterflies danced above colorful flowers blooming under the bright summer sun.",
"If you believe in yourself and work hard every single day, success will eventually knock on your door and reward your relentless efforts.",
"The city buzzed with activity as people hurried through the streets, unaware of the magical surprise awaiting them around the next corner.",
"Learning how to code is like learning a new language, opening doors to endless possibilities, creativity, and problem-solving adventures.",
"On a cold winter morning, the little boy bundled up in a warm coat and scarf to explore the snow-covered park filled with wonders.",
"The spaceship soared into the galaxy, leaving behind the vibrant blue planet, as its crew embarked on a daring mission to uncover cosmic mysteries."
];
// Variables
let startTime, currentSentence, timer;
let timeLeft = 60;
let currentRound = 1;
let totalRounds = 10;
let roundScores = []; // Stores WPM for each round
let roundAccuracies = []; // Stores accuracy for each round
let highScore = 0; // Reset high score for the session
// Shuffle Function
function shuffleArray(array) {
for (let i = array.length - 1; i > 0; i--) {
const j = Math.floor(Math.random() * (i + 1));
[array[i], array[j]] = [array[j], array[i]]; // Swap elements
}
return array;
}
// Shuffle sentences before the game starts
let shuffledSentences = shuffleArray([...sentences]); // Create a shuffled copy
// Get the sentence for the current round
function getRandomSentence() {
return shuffledSentences[currentRound - 1]; // Use the shuffled array
}
// Start Game
startBtn.addEventListener("click", () => {
resetGame();
// Generate and display a random sentence
currentSentence = getRandomSentence();
displaySentenceProgress(""); // Initially display empty progress
inputEl.disabled = false;
inputEl.value = "";
inputEl.focus();
// Record start time and start countdown
startTime = new Date().getTime();
timer = setInterval(updateCountdown, 1000);
// Hide buttons for new round
nextRoundBtn.style.display = "none";
quitBtn.style.display = "inline-block";
newGameBtn.style.display = "none"; // Hide "New Game" button during gameplay
});
// Update Countdown Timer
function updateCountdown() {
timeLeft--;
countdownEl.textContent = `Time Left: ${timeLeft}s`;
if (timeLeft <= 0) {
endRound("Time's up! Press Next Round to continue.");
}
}
// Input Event Listener for Real-Time Updates
inputEl.addEventListener("input", () => {
const typedText = inputEl.value;
// Display typing progress
displaySentenceProgress(typedText);
// Update WPM and Accuracy in real time
updateStats(typedText);
// Stop the game automatically if the user types the sentence correctly
if (typedText === currentSentence) {
endRound("Great job! Round completed.");
}
});
// Display Typing Progress
function displaySentenceProgress(typedText) {
const sentenceArray = currentSentence.split("");
const typedArray = typedText.split("");
let formattedSentence = "";
for (let i = 0; i < sentenceArray.length; i++) {
if (typedArray[i] === undefined) {
formattedSentence += `<span>${sentenceArray[i]}</span>`;
} else if (typedArray[i] === sentenceArray[i]) {
formattedSentence += sentenceArray[i] === " "
? `<span style="color: green;"> </span>`
: `<span style="color: green;">${sentenceArray[i]}</span>`;
} else {
if (sentenceArray[i] === " ") {
formattedSentence += `<span style="color: red;">⎵</span>`;
} else {
formattedSentence += `<span style="color: red;">${sentenceArray[i]}</span>`;
}
}
}
sentenceEl.innerHTML = formattedSentence;
}
// Update WPM and Accuracy
function updateStats(typedText) {
const elapsedTime = (new Date().getTime() - startTime) / 1000; // Time in seconds
const wordCount = currentSentence.split(" ").length;
// Update WPM
const wpm = Math.round((wordCount / elapsedTime) * 60);
wpmEl.textContent = `WPM: ${wpm}`;
// Update Accuracy
const accuracy = calculateAccuracy(currentSentence, typedText);
accuracyEl.textContent = `Accuracy: ${accuracy}%`;
}
// Accuracy Calculation
function calculateAccuracy(sentence, typedText) {
const sentenceChars = sentence.split("");
const typedChars = typedText.split("");
let correctChars = 0;
for (let i = 0; i < typedChars.length; i++) {
if (typedChars[i] === sentenceChars[i]) {
correctChars++;
}
}
return Math.round((correctChars / sentenceChars.length) * 100);
}
// End Current Round
function endRound(message) {
clearInterval(timer);
inputEl.disabled = true;
// Calculate WPM and Accuracy for the round
const elapsedTime = (new Date().getTime() - startTime) / 1000;
const wordCount = currentSentence.split(" ").length;
const wpm = Math.round((wordCount / elapsedTime) * 60);
const accuracy = calculateAccuracy(currentSentence, inputEl.value);
// Add the scores to the arrays
roundScores.push(wpm);
roundAccuracies.push(accuracy);
sentenceEl.textContent = message;
startBtn.style.display = "none";
nextRoundBtn.style.display = "inline-block";
}
// Go to Next Round
nextRoundBtn.addEventListener("click", () => {
if (currentRound < totalRounds) {
currentRound++;
resetGameForNextRound();
countdownEl.textContent = `Round ${currentRound} of ${totalRounds}`;
startBtn.style.display = "inline-block";
nextRoundBtn.style.display = "none";
sentenceEl.textContent = "Press 'Start' to begin the next round!";
} else {
displayFinalScore();
}
});
// Reset Game for Next Round
function resetGameForNextRound() {
clearInterval(timer);
timeLeft = 60;
wpmEl.textContent = "WPM: 0";
accuracyEl.textContent = "Accuracy: 0%";
inputEl.value = "";
inputEl.disabled = true; // Disable typing until the next round starts
sentenceEl.textContent = "";
}
// Quit Game
quitBtn.addEventListener("click", () => {
clearInterval(timer); // Stop the timer
displayFinalScore();
});
// Display Final Score
function displayFinalScore() {
clearInterval(timer); // Stop the timer when the game ends
// Handle cases where no rounds were completed
if (roundScores.length === 0) {
sentenceEl.innerHTML = `
<div style="text-align: center;">
Game Over!<br>
No rounds were completed.<br>
Press "New Game" to start again!
</div>
`;
inputEl.disabled = true;
startBtn.style.display = "none";
nextRoundBtn.style.display = "none";
quitBtn.style.display = "none";
newGameBtn.style.display = "inline-block"; // Show "New Game" button
return;
}
// Calculate Total Score
const totalScore = roundScores.reduce((sum, score) => sum + score, 0);
// Calculate Average WPM
const averageWPM = Math.round(totalScore / roundScores.length);
// Calculate Average Accuracy
const totalAccuracy = roundAccuracies.reduce((sum, acc) => sum + acc, 0);
const averageAccuracy = Math.round(totalAccuracy / roundAccuracies.length);
// Update High Score for the current session
if (totalScore > highScore) {
highScore = totalScore;
highScoreEl.textContent = `High Score: ${highScore} WPM`;
}
// Display the final results
sentenceEl.innerHTML = `
<div style="text-align: center;">
Game Over!<br>
Total Score: <strong>${totalScore} WPM</strong><br>
Average WPM: <strong>${averageWPM}</strong><br>
Average Accuracy: <strong>${averageAccuracy}%</strong><br>
<p>Press "New Game" to start again!</p>
</div>
`;
inputEl.disabled = true;
startBtn.style.display = "none";
nextRoundBtn.style.display = "none";
quitBtn.style.display = "none";
newGameBtn.style.display = "inline-block"; // Show "New Game" button
}
// Start New Game
function startNewGame() {
// Reset everything for a fresh game
roundScores = [];
roundAccuracies = [];
currentRound = 1;
shuffledSentences = shuffleArray([...sentences]); // Shuffle again for a new game
countdownEl.textContent = `Round ${currentRound} of ${totalRounds}`;
sentenceEl.textContent = "Press 'Start' to begin!";
resetGame();
startBtn.style.display = "inline-block";
newGameBtn.style.display = "none"; // Hide "New Game" button
}
// Reset Game
function resetGame() {
clearInterval(timer);
timeLeft = 60;
wpmEl.textContent = "WPM: 0";
accuracyEl.textContent = "Accuracy: 0%";
nextRoundBtn.style.display = "none";
}
// Theme Toggle Functionality
themeSwitch.addEventListener("change", () => {
const isDarkMode = document.body.classList.toggle("dark-mode");
// Update the theme text
themeText.textContent = isDarkMode ? "Dark" : "Light";
});
// Set the initial state for "Dark" as default
window.onload = () => {
highScore = 0; // Reset high score for the session
highScoreEl.textContent = `High Score: ${highScore} WPM`;
// Initialize the theme
themeSwitch.checked = true; // Default dark mode
themeText.textContent = "Dark"; // Default text
// Disable copy-paste in the input box
inputEl.addEventListener("paste", (e) => e.preventDefault());
inputEl.addEventListener("copy", (e) => e.preventDefault());
};