diff --git a/.DS_Store b/.DS_Store
index 9afe4923..35845fef 100644
Binary files a/.DS_Store and b/.DS_Store differ
diff --git a/assets/.DS_Store b/assets/.DS_Store
index 1da683b1..c0e14bf6 100644
Binary files a/assets/.DS_Store and b/assets/.DS_Store differ
diff --git a/assets/icons/Nuttall_s_spelling_bee_guide_condensed_f.pdf b/assets/icons/Nuttall_s_spelling_bee_guide_condensed_f.pdf
new file mode 100644
index 00000000..494e70b2
Binary files /dev/null and b/assets/icons/Nuttall_s_spelling_bee_guide_condensed_f.pdf differ
diff --git a/assets/scripts/spelloff.js b/assets/scripts/spelloff.js
new file mode 100644
index 00000000..2ef50114
--- /dev/null
+++ b/assets/scripts/spelloff.js
@@ -0,0 +1,293 @@
+/* https://www.freecodecamp.org/news/build-a-wordle-clone-in-javascript/ */
+const KEYBOARD_EL = document.querySelector("#keyboard")
+const attempt = document.querySelector("#attempt-box")
+var publicCount = document.querySelector('#count')
+
+var wordOne = document.querySelector("#word-one")
+var wordOnePlayer = document.querySelector("#word-one-player")
+
+var lastActiveWord = null;
+
+var wordCounter = 0;
+var numCorrect = 0;
+var attemptStr = '';
+var activeWord = null;
+var activePlayer = null;
+var wordLst;
+var levelPath;
+
+var results = '';
+var submissionLst = [];
+var correctSpellingLst = [];
+var wrongSubmission = '';
+var playerLst = [[wordOne, wordOnePlayer]];
+
+KEYBOARD_EL.innerHTML = `
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
`
+
+// CHECK LEVEL
+function checkLevel(level){
+ resetPlayer(playerLst);
+ attempt.value=attemptStr;
+ updateWord();
+}
+
+var wordLst = genSpellOffWordLst()
+console.log(wordLst)
+
+
+function updateWord(){
+ levelPath = "levelThreeNEW"
+ path = `assets/audio/${levelPath}`;
+ resetPlayer(playerLst);
+ activeWord = wordLst[wordCounter];
+ wordOnePlayer.src = `${path}/${wordLst[wordCounter]}.mp3`
+ //console.log(`levelPath: ${levelPath}\nWord Counter: ${wordCounter}.\nActive Word: ${activeWord}`)
+
+ publicCount.textContent = `Words Remaining: ${25 - wordCounter}`
+}
+
+function endGame(){
+ sessionStorage.setItem("submissionLst", submissionLst)
+ sessionStorage.setItem("correctSpellingLst",correctSpellingLst)
+ sessionStorage.setItem("numCorrect", numCorrect);
+ window.location.replace("spelloff_results.html");
+}
+
+// STOP PLAYING SOUND
+function stopSound(soundObj) {
+ soundObj.pause();
+ soundObj.currentTime = 0;
+}
+
+// UPDATE ATTEMPT STR UPON KEYPRESS
+function insertLetter(pressedKey) {
+ pressedKey = pressedKey.toUpperCase()
+ attemptStr = attemptStr + pressedKey;
+ attempt.focus();
+ attempt.value = attemptStr;
+ attempt.scrollLeft = attempt.scrollWidth;
+}
+
+// DELETE A LETER
+function deleteLetter () {
+ if (attemptStr.length > 0) {
+ attemptStr = attemptStr.slice(0,-1);
+ }
+ attempt.value = attemptStr;
+}
+
+function guessPreprocess() {
+ if ((lastActiveWord != null) & (activeWord==null)) {
+ activeWord = lastActiveWord;
+ checkGuess()
+ return;
+ } else if (activeWord == null) {
+ console.log("Attempted guess without word selected.");
+ attemptStr = '';
+ attempt.value = attemptStr;
+ return;
+ } else if (attemptStr == '') {
+ console.log("Empty string submitted as guess. Ignoring that.");
+ return;
+ } else {
+ checkGuess();
+ }
+}
+
+// CHECK IF GUESS IS CORRECT
+function checkGuess() {
+ correctSpellingLst.push(`${activeWord} | `)
+ if (attemptStr.toLowerCase() == activeWord.toLowerCase()) {
+ submissionLst.push(`${attemptStr} | `)
+ wordCounter += 1;
+ numCorrect += 1;
+
+ stopSound(activePlayer[1]);
+
+ updatePlayer(playerLst, activePlayer)
+
+ // DEACTIVATE WORD
+ activeWord = null;
+ activePlayer = null;
+
+
+ // RECURSIVE CALL FOR NEW WORD
+ updateWord();
+ } else {
+ submissionLst.push(`${attemptStr} | `)
+ wordCounter += 1;
+
+ stopSound(activePlayer[1]);
+
+ updatePlayer(playerLst, activePlayer)
+
+ // DEACTIVATE WORD
+ activeWord = null;
+ activePlayer = null;
+
+ // RECURSIVE CALL FOR NEW WORD
+ updateWord();
+ }
+
+ if (wordCounter == 25){
+ endGame();
+ }
+ attemptStr = '';
+ attempt.value = attemptStr;
+ return
+}
+
+// update players to reflect their current status
+function updatePlayer(playerLst, activePlayer) {
+ if (activePlayer[0].classList.contains("clicked")) {
+ stopSound(activePlayer[1]);
+ activePlayer[0].classList.remove("clicked","fa-circle-stop");
+ activePlayer[0].classList.add("fa-play-circle");
+
+ lastActiveWord = activeWord;
+
+ // DEACTIVATE WORD
+ activeWord = null;
+ activePlayer = null;
+ return;
+ }
+
+ playerLst.forEach((player) => {
+ if ((!player[0].classList.contains("submitted")) & player[0] != activePlayer[0]) {
+ player[0].classList.remove("clicked", "fa-circle-stop");
+ stopSound(player[1]);
+ } else if ((!player[0].classList.contains("submitted")) & player[0] == activePlayer[0]) {
+ activePlayer[0].classList.add("clicked","fa-circle-stop");
+ activePlayer[1].play();
+ }
+ })
+ return;
+}
+
+function resetPlayer(playerLst) {
+ playerLst.forEach((player) => {
+ player[0].style.backgroundColor = null;
+ player[0].classList.remove("clicked", "fa-xmark","fa-check", "fa-circle-stop", "submitted")
+ player[0].classList.add("fa-play-circle")
+ })
+}
+// PROMPT MANAGEMENT
+
+wordOne.addEventListener("click", (e) => {
+ activePlayer = [wordOne, wordOnePlayer];
+ updatePlayer(playerLst, activePlayer)
+})
+
+
+// LINK ONSCREEN KEYBOARD FUNCTIONALITY TO KEYPRESSS
+document.getElementById("keyboard-cont").addEventListener("click", (e) => {
+ const target = e.target
+
+ if (!target.classList.contains("keyboard-button")) {
+ return
+ }
+
+ let key = target.textContent
+
+ if (target.classList.contains("fa-delete-left")){
+ deleteLetter();
+ return
+ //key = "Backspace"
+ }
+
+ if (key==="submit"){
+ guessPreprocess();
+ return
+ //key = "Enter"
+ }
+
+ let pressedKey = target.innerText;
+ let found = pressedKey.match(/[a-z]/gi)
+
+ if (!found || found.length > 1) {
+ return
+ } else {
+ insertLetter(pressedKey)
+ document.querySelector(`#${pressedKey.toLowerCase()}`).classList.add("clicked")
+ setTimeout(() => {
+ setTimeout(document.querySelector(`#${pressedKey.toLowerCase()}`).classList.remove("clicked"));
+ }, 50);
+ return;
+ }
+ //document.dispatchEvent(new KeyboardEvent("keyup", {'key': key}))
+})
+
+// KEYPRESS TYPING LISTENER
+document.addEventListener("keyup", (e) => {
+
+ let pressedKey = String(e.key)
+ let found = pressedKey.match(/[a-z]/gi)
+
+ if (pressedKey === "Enter") {
+ document.querySelector(`#${pressedKey}`).classList.add("clicked")
+ setTimeout(() => {
+ setTimeout(document.querySelector(`#${pressedKey}`).classList.remove("clicked"));
+ }, 50);
+ guessPreprocess()
+ return;
+ }
+
+ if (pressedKey === "Backspace" & attemptStr.length != 0) {
+ document.querySelector(`#${pressedKey}`).classList.add("clicked")
+ setTimeout(() => {
+ setTimeout(document.querySelector(`#${pressedKey}`).classList.remove("clicked"));
+ }, 50);
+ deleteLetter()
+ return;
+ }
+
+ if (!found || found.length > 1) {
+ return
+ } else {
+ insertLetter(pressedKey)
+ document.querySelector(`#${pressedKey.toLowerCase()}`).classList.add("clicked")
+ setTimeout(() => {
+ setTimeout(document.querySelector(`#${pressedKey.toLowerCase()}`).classList.remove("clicked"));
+ }, 50);
+ return;
+ }
+})
+
+checkLevel("youtube")
\ No newline at end of file
diff --git a/assets/scripts/spelloff_results.js b/assets/scripts/spelloff_results.js
new file mode 100644
index 00000000..d16bce7e
--- /dev/null
+++ b/assets/scripts/spelloff_results.js
@@ -0,0 +1,20 @@
+var submissionLst = sessionStorage.getItem("submissionLst").split(",")
+var typos = document.querySelector("#typos")
+var numCorrect = sessionStorage.getItem('numCorrect')
+var correctSpellingLst = sessionStorage.getItem("correctSpellingLst").split(",")
+var summary = document.querySelector("#summary")
+
+innerStr = ''
+
+for (var i = 0; i
+ ${i+1} |
+ ${correctSpellingLst[i]}
+ ${submissionLst[i]}
+
+ `
+}
+
+typos.innerHTML = innerStr;
+summary.innerText = `You spelled ${numCorrect} words correctly.`
\ No newline at end of file
diff --git a/assets/scripts/wordLstGenerator.js b/assets/scripts/wordLstGenerator.js
index bb8724da..d157208a 100644
--- a/assets/scripts/wordLstGenerator.js
+++ b/assets/scripts/wordLstGenerator.js
@@ -108,6 +108,23 @@ function genYoutubeWordLst(){
return result;
}
+function genSpellOffWordLst(){
+ result = [];
+ var YTseed = cyrb128("phil");
+ // Four 32-bit component hashes provide the seed for sfc32.
+ var YTrand = sfc32(YTseed[0], YTseed[1], YTseed[2], YTseed[3]);
+
+ wordLst = hardWords
+ while (result.length < 25) {
+ var item = wordLst[Math.floor(YTrand()*wordLst.length)];
+ if (!result.includes(item)){
+ result.push(item)
+ }
+ }
+
+ return result;
+}
+
var diffTime = new Date(today).getTime() - new Date("1/12/2024").getTime();
var Difference_In_Days = Math.round(diffTime / (1000 * 3600 * 24));
var puzzleNum = Difference_In_Days
diff --git a/spelloff.html b/spelloff.html
new file mode 100644
index 00000000..037fd45f
--- /dev/null
+++ b/spelloff.html
@@ -0,0 +1,47 @@
+
+
+
+
+
+ Spellcheck - A Word Game | Spell Off
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/spelloff_results.html b/spelloff_results.html
new file mode 100644
index 00000000..398d3d7a
--- /dev/null
+++ b/spelloff_results.html
@@ -0,0 +1,48 @@
+
+
+
+
+
+ Spellcheck - A Word Game | Results
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file