From 5aa14a21484cf36838b5541afe2ee76b6d5c274b Mon Sep 17 00:00:00 2001
From: Benjamin Auder <benjamin.auder@somewhere>
Date: Sat, 7 Mar 2020 19:06:37 +0100
Subject: [PATCH] Fixes for corr games update + incomplete info (do not show
 board)

---
 client/src/components/BaseGame.vue     |  17 ++--
 client/src/components/ComputerGame.vue |  19 ++--
 client/src/views/Game.vue              | 129 ++++++++++++++++++-------
 3 files changed, 116 insertions(+), 49 deletions(-)

diff --git a/client/src/components/BaseGame.vue b/client/src/components/BaseGame.vue
index e7977eb2..0b6fa055 100644
--- a/client/src/components/BaseGame.vue
+++ b/client/src/components/BaseGame.vue
@@ -368,20 +368,21 @@ export default {
             this.emitFenIfAnalyze();
           }
           this.inMultimove = false;
-          const score = this.vr.getCurrentScore();
-          if (score != "*") {
-            const message = getScoreMessage(score);
-            if (!navigate && this.game.mode != "analyze")
-              this.$emit("gameover", score, message);
-            else if (this.game.mode == "analyze")
+          if (!noemit) {
+            var score = this.vr.getCurrentScore();
+            if (score != "*" && this.game.mode == "analyze") {
+              const message = getScoreMessage(score);
               // Just show score on screen (allow undo)
               this.showEndgameMsg(score + " . " + this.st.tr[message]);
+            }
           }
           if (!navigate && this.game.mode != "analyze") {
             const L = this.moves.length;
             if (!noemit)
-              // Post-processing (e.g. computer play)
-              this.$emit("newmove", this.moves[L-1]);
+              // Post-processing (e.g. computer play).
+              // NOTE: always emit the score, even in unfinished,
+              // to tell Game::processMove() that it's not a received move.
+              this.$emit("newmove", this.moves[L-1], { score: score });
             else {
               this.inPlay = false;
               if (this.stackToPlay.length > 0)
diff --git a/client/src/components/ComputerGame.vue b/client/src/components/ComputerGame.vue
index 5782ba6a..83b4e023 100644
--- a/client/src/components/ComputerGame.vue
+++ b/client/src/components/ComputerGame.vue
@@ -3,7 +3,6 @@ BaseGame(
   ref="basegame"
   :game="game"
   @newmove="processMove"
-  @gameover="gameOver"
 )
 </template>
 
@@ -11,6 +10,7 @@ BaseGame(
 import BaseGame from "@/components/BaseGame.vue";
 import { store } from "@/store";
 import { CompgameStorage } from "@/utils/compgameStorage";
+import { getScoreMessage } from "@/utils/scoring";
 import { playMove, getFilteredMove } from "@/utils/playUndo";
 import Worker from "worker-loader!@/playCompMove";
 export default {
@@ -85,11 +85,13 @@ export default {
       this.compThink = true;
       this.compWorker.postMessage(["askmove"]);
     },
-    processMove: function(move) {
+    processMove: function(move, scoreObj) {
       playMove(move, this.vr);
-      // This move could have ended the game: if this is the case,
-      // the game is already removed from storage (if mode == 'versus')
-      if (this.game.score != "*") return;
+      // This move could have ended the game:
+      if (scoreObj.score != "*") {
+        this.gameOver(scoreObj.score);
+        return;
+      }
       // Send the move to web worker (including his own moves)
       this.compWorker.postMessage(["newmove", move]);
       if (this.gameInfo.mode == "auto" || this.vr.turn != this.game.mycolor)
@@ -102,10 +104,11 @@ export default {
         });
       }
     },
-    gameOver: function(score, scoreMsg) {
+    gameOver: function(score) {
       this.game.score = score;
-      this.game.scoreMsg = scoreMsg;
-      if (!this.compThink) this.$emit("game-stopped"); //otherwise wait for comp
+      this.game.scoreMsg = getScoreMessage(score);
+      // If comp is thinking, let him finish:
+      if (!this.compThink) this.$emit("game-stopped");
     }
   }
 };
diff --git a/client/src/views/Game.vue b/client/src/views/Game.vue
index e0ae7e91..55b36887 100644
--- a/client/src/views/Game.vue
+++ b/client/src/views/Game.vue
@@ -103,7 +103,6 @@ main
     ref="basegame"
     :game="game"
     @newmove="processMove"
-    @gameover="gameOver"
   )
 </template>
 
@@ -116,10 +115,11 @@ import { ppt } from "@/utils/datetime";
 import { ajax } from "@/utils/ajax";
 import { extractTime } from "@/utils/timeControl";
 import { getRandString } from "@/utils/alea";
+import { getScoreMessage } from "@/utils/scoring";
+import { getFullNotation } from "@/utils/notation";
 import { getDiagram } from "@/utils/printDiagram";
 import { processModalClick } from "@/utils/modalClick";
 import { playMove, getFilteredMove } from "@/utils/playUndo";
-import { getScoreMessage } from "@/utils/scoring";
 import { ArrayFun } from "@/utils/array";
 import params from "@/parameters";
 export default {
@@ -175,6 +175,10 @@ export default {
       if (from.params["id"] != to.params["id"]) {
         // Change everything:
         this.cleanBeforeDestroy();
+        let boardDiv = document.querySelector(".game");
+        if (!!boardDiv)
+          // In case of incomplete information variant:
+          boardDiv.style.visibility = "hidden";
         this.atCreation();
       } else {
         // Same game ID
@@ -350,7 +354,6 @@ export default {
       this.send("turnchange", { target: sid, yourTurn: yourTurn });
     },
     showNextGame: function() {
-      if (this.nextIds.length == 0) return;
       // Did I play in current game? If not, add it to nextIds list
       if (this.game.score == "*" && this.vr.turn == this.game.mycolor)
         this.nextIds.unshift(this.game.id);
@@ -637,13 +640,16 @@ export default {
       this.conn.addEventListener("message", this.socketMessageListener);
       this.conn.addEventListener("close", this.socketCloseListener);
     },
-    updateCorrGame: function(obj) {
+    updateCorrGame: function(obj, callback) {
       ajax(
         "/games",
         "PUT",
         {
           gid: this.gameRef.id,
           newObj: obj
+        },
+        () => {
+          if (!!callback) callback();
         }
       );
     },
@@ -664,7 +670,9 @@ export default {
       if (data.drawSent) this.drawOffer = "received";
       if (data.score != "*") {
         this.drawOffer = "";
-        if (this.game.score == "*") this.gameOver(data.score);
+        if (this.game.score == "*")
+          // TODO: also pass scoreMsg in lastate
+          this.gameOver(data.score);
       }
     },
     clickDraw: function() {
@@ -833,9 +841,14 @@ export default {
           // Re-load game because we missed some moves:
           // artificially reset BaseGame (required if moves arrived in wrong order)
           this.$refs["basegame"].re_setVariables();
-        else
+        else {
           // Initial loading:
           this.gotMoveIdx = game.moves.length - 1;
+          // If we arrive here after 'nextGame' action, the board might be hidden
+          let boardDiv = document.querySelector(".game");
+          if (!!boardDiv && boardDiv.style.visibility == "hidden")
+            boardDiv.style.visibility = "visible";
+        }
         this.re_setClocks();
         this.$nextTick(() => {
           this.game.rendered = true;
@@ -937,6 +950,11 @@ export default {
         }
         // Update current game object:
         playMove(move, this.vr);
+        if (!data.score) {
+          // Received move, score has not been computed in BaseGame (!!noemit)
+          const score = this.vr.getCurrentScore();
+          if (score != "*") this.gameOver(score);
+        }
 // TODO: notifyTurn: "changeturn" message
         this.game.moves.push(move);
         // (add)Time indication: useful in case of lastate infos requested
@@ -1045,41 +1063,83 @@ export default {
         moveCol == this.game.mycolor &&
         !data.receiveMyMove
       ) {
-        let el = document.querySelector("#buttonsConfirm > .acceptBtn");
-        // We may play several moves in a row: in case of, remove listener:
-        let elClone = el.cloneNode(true);
-        el.parentNode.replaceChild(elClone, el);
-        elClone.addEventListener(
-          "click",
-          () => {
-            document.getElementById("modalConfirm").checked = false;
-            doProcessMove();
-            if (this.st.settings.gotonext) this.showNextGame();
-            else this.re_setClocks();
+        const afterSetScore = () => {
+          doProcessMove();
+          if (this.st.settings.gotonext && this.nextIds.length > 0)
+            this.showNextGame();
+          else {
+            this.re_setClocks();
+            // The board might have been hidden:
+            let boardDiv = document.querySelector(".game");
+            if (boardDiv.style.visibility == "hidden")
+              boardDiv.style.visibility = "visible";
           }
-        );
-        // PlayOnBoard is enough, and more appropriate for Synchrone Chess
-        V.PlayOnBoard(this.vr.board, move);
-        const position = this.vr.getBaseFen();
-        V.UndoOnBoard(this.vr.board, move);
-        this.curDiag = getDiagram({
-          position: position,
-          orientation: V.CanFlip ? this.game.mycolor : "w"
-        });
-        document.getElementById("modalConfirm").checked = true;
+        };
+        if (["all","byrow"].includes(V.ShowMoves)) {
+          let el = document.querySelector("#buttonsConfirm > .acceptBtn");
+          // We may play several moves in a row: in case of, remove listener:
+          let elClone = el.cloneNode(true);
+          el.parentNode.replaceChild(elClone, el);
+          elClone.addEventListener(
+            "click",
+            () => {
+              document.getElementById("modalConfirm").checked = false;
+              if (!!data.score && data.score != "*")
+                // Set score first
+                this.gameOver(data.score, null, afterSetScore);
+              else afterSetScore();
+            }
+          );
+          // PlayOnBoard is enough, and more appropriate for Synchrone Chess
+          V.PlayOnBoard(this.vr.board, move);
+          const position = this.vr.getBaseFen();
+          V.UndoOnBoard(this.vr.board, move);
+          this.curDiag = getDiagram({
+            position: position,
+            orientation: V.CanFlip ? this.game.mycolor : "w"
+          });
+          document.getElementById("modalConfirm").checked = true;
+        } else {
+          // Incomplete information: just ask confirmation
+          // Hide the board, because otherwise it could be revealed (TODO?)
+          let boardDiv = document.querySelector(".game");
+          boardDiv.style.visibility = "hidden";
+          if (
+            !confirm(
+              this.st.tr["Move played:"] + " " +
+              getFullNotation(move) + "\n" +
+              this.st.tr["Are you sure?"]
+            )
+          ) {
+            this.$refs["basegame"].cancelLastMove();
+            boardDiv.style.visibility = "visible";
+            return;
+          }
+          if (!!data.score && data.score != "*")
+            this.gameOver(data.score, null, afterSetScore);
+          else afterSetScore();
+        }
       }
       else {
-        doProcessMove();
-        this.re_setClocks();
+        // Normal situation
+        const afterSetScore = () => {
+          doProcessMove();
+          this.re_setClocks();
+        };
+        if (!!data.score && data.score != "*")
+          this.gameOver(data.score, null, afterSetScore);
+        else afterSetScore();
       }
     },
     cancelMove: function() {
       document.getElementById("modalConfirm").checked = false;
       this.$refs["basegame"].cancelLastMove();
     },
-    gameOver: function(score, scoreMsg) {
+    // In corr games, callback to change page only after score is set:
+    gameOver: function(score, scoreMsg, callback) {
       this.game.score = score;
-      this.$set(this.game, "scoreMsg", scoreMsg || getScoreMessage(score));
+      if (!scoreMsg) scoreMsg = getScoreMessage(score);
+      this.$set(this.game, "scoreMsg", scoreMsg);
       const myIdx = this.game.players.findIndex(p => {
         return p.sid == this.st.user.sid || p.uid == this.st.user.id;
       });
@@ -1089,12 +1149,15 @@ export default {
           score: score,
           scoreMsg: scoreMsg
         };
-        if (this.Game.type == "live")
+        if (this.game.type == "live") {
           GameStorage.update(this.gameRef.id, scoreObj);
-        else this.updateCorrGame(scoreObj);
+          if (!!callback) callback();
+        }
+        else this.updateCorrGame(scoreObj, callback);
         // Notify the score to main Hall. TODO: only one player (currently double send)
         this.send("result", { gid: this.game.id, score: score });
       }
+      else if (!!callback) callback();
     }
   }
 };
-- 
2.44.0