-
Total words attempted
-
+
+
Current Game Results
+
+
+
-
-
Total words completed
-
-
-
-
Total incorrect guesses
-
-
-
-
Average guesses per word
-
-
-
-
Average time per word
-
-
-
-
-
+
+
+
+
+
Overall Performance
+
+
Total words attempted
+
+
+
+
Total words completed
+
+
+
+
Total incorrect guesses
+
+
+
+
Average guesses per word
+
+
+
+
Average time per word
+
+
+
+
+
+
diff --git a/html/word-guesser/scripts/script.js b/html/word-guesser/scripts/script.js
index 863d2e8..e399c52 100644
--- a/html/word-guesser/scripts/script.js
+++ b/html/word-guesser/scripts/script.js
@@ -161,7 +161,7 @@
}
const solved = this.checkWordCompletion();
- const failed = this.getTotalGuesses() >= this.getMaxGesses();
+ const failed = this.getTotalGuesses() >= this.getMaxGuesses();
if (solved || failed) {
this.endTime = Date.now();
@@ -240,6 +240,7 @@
guessButton: "guess_button",
currentWord: "current_word",
notifications: "notifications",
+ wordlistFile: "wordlist_file",
playAgainButton: "play_again",
quitButton: "quit_game",
@@ -255,6 +256,9 @@
totalIncorrectGuesses: "total_incorrect_guesses",
avgGuessesPerWord: "average_guesses_per_word",
avgTimePerWord: "average_time_per_word",
+ currentGameResult: "current_game_result",
+ currentGameIncorrect: "current_game_incorrect",
+ currentGameTime: "current_game_time",
};
// Merge provided names with defaults
@@ -280,7 +284,8 @@
class Game {
constructor(wordChoices, fields) {
Object.assign(this, fields);
- this.wordChoices = wordChoices;
+ this.defaultWordChoices = wordChoices;
+ this.activeWordChoices = wordChoices;
this.userName.addEventListener("focus", (event) => {
if (event.target.value == "Guest") {
@@ -292,9 +297,15 @@
this.userName.value = "Guest";
}
});
- this.userInfoForm.onsubmit = (event) => {
+ this.userInfoForm.onsubmit = async (event) => {
event.preventDefault();
- this.newGame();
+ const file = this.wordlistFile.files[0];
+ if (file) {
+ this.startGameFromFile(file);
+ } else {
+ this.activeWordChoices = this.defaultWordChoices;
+ this.newGame();
+ }
};
this.playAgainButton.onclick = (event) => this.newGame();
this.quitButton.onclick = (event) => this.handleQuit();
@@ -308,23 +319,57 @@
}
};
}
+ startGameFromFile(file) {
+ try {
+ const reader = new FileReader();
+
+ reader.onload = (event) => {
+ try {
+ const words = processWordList(event.target.result);
+ validateWordList(words);
+ this.activeWordChoices = words;
+ this.updateNotifications("📁", "Custom word list loaded!");
+ this.newGame();
+ } catch (e) {
+ window.alert(e);
+ }
+ };
+
+ reader.onerror = () => {
+ window.alert(new Error("File reading failed."));
+ };
+
+ return reader.readAsText(file);
+ } catch (e) {
+ this.updateNotifications("⚠️", e.message);
+ return; // Stop if the file is invalid
+ }
+ }
async init() {
this.dialogs = await import("./dialogs.js");
}
showScoreboard() {
- this.updateScoreboard();
+ this.updateScoreboard(this.game);
this.scoreboard.style.display = "flex";
}
updateGuessButton() {
this.guessButton.value = this.randomMessage(this.dialogs.guessButton);
}
- updateScoreboard() {
- const scores = WordGuesser.getScores();
- this.totalWordsAttempted.innerText = scores.totalWordsAttempted;
- this.totalWordsCompleted.innerText = scores.totalWordsCompleted;
- this.totalIncorrectGuesses.innerText = scores.totalIncorrectGuesses;
- this.avgGuessesPerWord.innerText = scores.avgGuessesPerWord;
- this.avgTimePerWord.innerText = scores.avgTimePerWord;
+ updateScoreboard(currentGame) {
+ // 1. Update Current Game Section
+ const currentStats = currentGame._getScores();
+ this.currentGameResult.innerText = currentStats.solved ? "WON" : "LOST";
+ this.currentGameResult.className = `sb-value ${currentStats.solved ? "success-msg" : "error-msg"}`;
+ this.currentGameIncorrect.innerText = currentStats.incorrect;
+ this.currentGameTime.innerText = currentStats.time.toFixed(2);
+
+ // 2. Update Cumulative Section
+ const overallScores = WordGuesser.getScores();
+ this.totalWordsAttempted.innerText = overallScores.totalWordsAttempted;
+ this.totalWordsCompleted.innerText = overallScores.totalWordsCompleted;
+ this.totalIncorrectGuesses.innerText = overallScores.totalIncorrectGuesses;
+ this.avgGuessesPerWord.innerText = overallScores.avgGuessesPerWord;
+ this.avgTimePerWord.innerText = overallScores.avgTimePerWord;
}
renderAlphabet() {
const container = document.getElementById("alphabet_container");
@@ -366,8 +411,11 @@
}
newGame() {
this.reset();
- this.game = new WordGuesser(this.wordChoices);
+ this.game = new WordGuesser(this.activeWordChoices);
this.renderAlphabet();
+ this.updateCurrentWord(this.game.getCurrentWord());
+ this.updateGuesses(this.game.getGuesses());
+ this.updateGuessCount(this.game.guessCount());
this.userInfoForm.style.display = "none";
this.gameForm.style.display = "block";
this.scoreboard.style.display = "none";
@@ -496,6 +544,28 @@
return messages[randomChoice];
}
}
+
+function processWordList(text) {
+ const lines = text.split(/\r?\n/);
+ const processedWords = [];
+
+ for (let i = 0; i < lines.length; i++) {
+ const word = lines[i].trim();
+ if (word.length >= 5) {
+ processedWords.push(word);
+ }
+ }
+
+ return processedWords;
+}
+
+function validateWordList(words) {
+ if (words.length < 25) {
+ throw new Error(
+ "File must contain at least 25 words/phrases of 5+ characters.",
+ );
+ }
+}
document.addEventListener("DOMContentLoaded", async (_) => {
const wordChoices = (await import("./wordlist.js")).default;
const fields = new GameFields();