From 2cad321b858e4fc9f77f4a420dd219713bbb90db Mon Sep 17 00:00:00 2001
From: Carl Worth <cworth@cworth.org>
Date: Wed, 21 Dec 2022 18:59:20 -0800
Subject: [PATCH] Add answer checking and level advancement

This is now very close to a complete puzzle.

All that's really missing is the final message from the Doctor and an
implementation of the reset button.
---
 index.js    | 54 ++++++++++++++++++++++++++++++++++++++++++++--
 tardis.html | 62 ++++++++++++++++++++++++++++++++++++++++++++---------
 2 files changed, 104 insertions(+), 12 deletions(-)

diff --git a/index.js b/index.js
index cc1bcda..91a74ae 100644
--- a/index.js
+++ b/index.js
@@ -179,7 +179,7 @@ const levels = [
     }
 ];
 
-var show_word_interval;
+var show_word_interval = 0;
 
 function show_word() {
     const tardis = state.tardis;
@@ -191,6 +191,40 @@ function show_word() {
 	tardis.word = 0;
 }
 
+function start_level() {
+    const tardis = state.tardis;
+
+    // Inform all players of the new level
+    io_tardis.emit("level", levels[tardis.level].title);
+
+    // Then start the timer that shows the words
+    show_word_interval = setInterval(show_word, 1200);
+}
+
+function level_up() {
+    const tardis = state.tardis;
+
+    if (show_word_interval) {
+	clearInterval(show_word_interval);
+	show_word_interval = 0;
+    }
+
+    if (tardis.state === "game") {
+	tardis.level = tardis.level + 1;
+	tardis.word = 0;
+
+	if (tardis.level >= levels.length) {
+	    tardis.state = "over";
+	    io_tardis.emit("state", tardis.state);
+	} else {
+	    setTimeout(() => {
+		start_level();
+	    }, 2000);
+	}
+
+    }
+}
+
 function start_game() {
     const tardis = state.tardis;
 
@@ -201,7 +235,8 @@ function start_game() {
     // Let all companions know the state of the game
     io_tardis.emit("level", levels[tardis.level].title);
     io_tardis.emit("state", tardis.state);
-    show_word_interval = setInterval(show_word, 1200);
+
+    start_level();
 }
 
 function emit_tardis_timer() {
@@ -263,6 +298,21 @@ io_tardis.on("connection", (socket) => {
     }
     tardis.companions.names.push(name);
 
+    socket.on('answer', answer => {
+	const tardis = state.tardis;
+
+	if (tardis.state != "game") {
+	    return;
+	}
+
+	if (answer == levels[tardis.level].answer) {
+	    io_tardis.emit('correct');
+	    level_up();
+	} else {
+	    io_tardis.emit('incorrect');
+	}
+    });
+
     socket.on('disconnect', () => {
 	const names = tardis.companions.names;
 
diff --git a/tardis.html b/tardis.html
index cca4e97..1e9e057 100644
--- a/tardis.html
+++ b/tardis.html
@@ -72,6 +72,15 @@
 	font-weight: bold;
 	text-align: center;
     }
+    #result {
+	position: fixed;
+	width: 100%;
+	top: 50%;
+	left: 50%;
+	transform: translate(-50%, -50%);
+	font-size: 500%;
+	text-align: center;
+    }
   </style>
 </head>
 
@@ -101,9 +110,15 @@
 	&nbsp;
       </div>
       <div id="interface">
-	<input id="input">
-        </input>
+	<form id="form">
+	  <input id="input">
+          </input>
+	</form>
+      </div>
+
+      <div id="result">
       </div>
+      
       <button id="reboot">
 	Reboot Tardis
       </button>
@@ -124,6 +139,26 @@
     const timer_div = document.getElementById("timer_div");
     const timer = document.getElementById("timer");
     const welcome_message = document.getElementById("welcome-message");
+    const form = document.getElementById("form");
+    const input = document.getElementById("input");
+    const result = document.getElementById("result");
+
+    function fade_element(elt) {
+	elt.style.opacity = "100%";
+	elt.className = "fade-out";
+	// Arrange to clear the class name when the animation is over
+	// This will allow for it to be restarted on the next word.
+	setTimeout(() => {
+	    elt.style.opacity = "0%";
+	    elt.className = "";
+	}, 900);
+    }
+
+    form.addEventListener('submit', event => {
+	event.preventDefault();
+	socket.emit('answer', input.value);
+	input.value = "";
+    });
 
     socket.on('companions', (count) => {
 	companions.textContent = count.toString();
@@ -150,18 +185,25 @@
 
     socket.on('level', (level) => {
 	level_div.textContent = level;
+	level_div.style.visibility = "visible";
     });
 
     socket.on('show-word', (word) => {
 	word_div.textContent = word;
-	word_div.style.opacity = "100%";
-	word_div.className = "fade-out";
-	// Arrange to clear the class name when the animation is over
-	// This will allow for it to be restarted on the next word.
-	setTimeout(() => {
-	    word_div.style.opacity = "0%";
-	    word_div.className = "";
-	}, 900);
+	fade_element(word_div);
+    });
+
+    socket.on('correct', () => {
+	level_div.style.visibility = "hidden";
+	result.textContent = "Complete!";
+	result.style.color = "green";
+	fade_element(result);
+    });
+
+    socket.on('incorrect', () => {
+	result.textContent = "Nope!";
+	result.style.color = "red";
+	fade_element(result);
     });
 
   </script>
-- 
2.45.2