]> git.cworth.org Git - lmno.games/blobdiff - tictactoe/tictactoe.jsx
Drop the game history interface.
[lmno.games] / tictactoe / tictactoe.jsx
index eff7eff32f6df572437130d0ec2c0e8ecf8c2a7b..934faa8e0cc63e37adc530c22beea642f7782fb7 100644 (file)
@@ -1,3 +1,30 @@
+function undisplay(element) {
+  element.style.display="none";
+}
+
+function add_message(severity, message) {
+  message = `<div class="message ${severity}" onclick="undisplay(this)">
+<span class="hide-button" onclick="undisplay(this.parentElement)">&times;</span>
+${message}
+</div>`;
+  const message_area = document.getElementById('message-area');
+  message_area.insertAdjacentHTML('beforeend', message);
+}
+
+const events = new EventSource("events");
+
+events.onerror = function(event) {
+  if (event.target.readyState === EventSource.CLOSED) {
+      add_message("danger", "Connection to server lost.");
+  }
+};
+
+events.addEventListener("move", event => {
+  const square = JSON.parse(event.data);
+
+  window.game.receiveMove(square);
+});
+
 function Square(props) {
   return (
     <button className="square" onClick={props.onClick}>
@@ -39,6 +66,17 @@ class Board extends React.Component {
   }
 }
 
+function fetch_post_json(api = '', data = {}) {
+  const response = fetch(api, {
+    method: 'POST',
+    headers: {
+      'Content-Type': 'application/json'
+    },
+    body: JSON.stringify(data)
+  });
+  return response;
+}
+
 class Game extends React.Component {
   constructor(props) {
     super(props);
@@ -53,7 +91,11 @@ class Game extends React.Component {
     };
   }
 
-  handleClick(i) {
+  sendMove(i) {
+    return fetch_post_json("move", { square: i });
+  }
+
+  receiveMove(i) {
     const history = this.state.history.slice(0, this.state.stepNumber + 1);
     const current = history[history.length - 1];
     const squares = current.squares.slice();
@@ -72,6 +114,17 @@ class Game extends React.Component {
     });
   }
 
+  async handleClick(i) {
+    const response = await this.sendMove(i);
+    if (response.status == 200) {
+      const legal = await response.json();
+      if (! legal)
+        add_message("danger", `Illegal move.`);
+    } else {
+      add_message("danger", `Error occurred sending move`);
+    }
+  }
+
   jumpTo(step) {
     this.setState({
       stepNumber: step,
@@ -84,17 +137,6 @@ class Game extends React.Component {
     const current = history[this.state.stepNumber];
     const winner = calculateWinner(current.squares);
 
-    const moves = history.map((step, move) => {
-      const desc = move ?
-        'Go to move #' + move :
-        'Go to game start';
-      return (
-        <li key={move}>
-          <button onClick={() => this.jumpTo(move)}>{desc}</button>
-        </li>
-      );
-    });
-
     let status;
     if (winner) {
       status = "Winner: " + winner;
@@ -112,7 +154,6 @@ class Game extends React.Component {
         </div>
         <div className="game-info">
           <div>{status}</div>
-          <ol>{moves}</ol>
         </div>
       </div>
     );
@@ -121,7 +162,9 @@ class Game extends React.Component {
 
 // ========================================
 
-ReactDOM.render(<Game />, document.getElementById("tictactoe"));
+ReactDOM.render(<Game
+                  ref={(me) => window.game = me}
+                />, document.getElementById("tictactoe"));
 
 function calculateWinner(squares) {
   const lines = [