Better time control in correspondance games
[vchess.git] / client / src / views / Game.vue
index 2da8d9e..758759d 100644 (file)
@@ -24,6 +24,7 @@ main
         :pastChats="game.chats"
         :newChat="newChat"
         @mychat="processChat"
+        @chatcleared="clearChat"
       )
   .row
     #aboveBoard.col-sm-12.col-md-9.col-md-offset-3.col-lg-10.col-lg-offset-2
@@ -69,6 +70,7 @@ import Chat from "@/components/Chat.vue";
 import { store } from "@/store";
 import { GameStorage } from "@/utils/gameStorage";
 import { ppt } from "@/utils/datetime";
+import { ajax } from "@/utils/ajax";
 import { extractTime } from "@/utils/timeControl";
 import { getRandString } from "@/utils/alea";
 import { processModalClick } from "@/utils/modalClick";
@@ -193,6 +195,25 @@ export default {
         Object.values(this.people).some(p => p.id == player.uid)
       );
     },
+    resetChatColor: function() {
+      // TODO: this is called twice, once on opening an once on closing
+      document.getElementById("chatBtn").classList.remove("somethingnew");
+    },
+    processChat: function(chat) {
+      this.send("newchat", { data: chat });
+      // NOTE: anonymous chats in corr games are not stored on server (TODO?)
+      if (this.game.type == "corr" && this.st.user.id > 0)
+        GameStorage.update(this.gameRef.id, { chat: chat });
+    },
+    clearChat: function() {
+      // Nothing more to do if game is live (chats not recorded)
+      if (this.game.type == "corr") {
+        if (this.game.mycolor)
+          ajax("/chats", "DELETE", {gid: this.game.id});
+        // TODO: this.game.chats = [] could be enough here?
+        this.$set(this.game, "chats", []);
+      }
+    },
     socketMessageListener: function(msg) {
       if (!this.conn) return;
       const data = JSON.parse(msg.data);
@@ -227,12 +248,12 @@ export default {
           break;
         case "killed":
           // I logged in elsewhere:
-          alert(this.st.tr["New connexion detected: tab now offline"]);
           // TODO: this fails. See https://github.com/websockets/ws/issues/489
           //this.conn.removeEventListener("message", this.socketMessageListener);
           //this.conn.removeEventListener("close", this.socketCloseListener);
           //this.conn.close();
           this.conn = null;
+          alert(this.st.tr["New connexion detected: tab now offline"]);
           break;
         case "askidentity": {
           // Request for identification (TODO: anonymous shouldn't need to reply)
@@ -343,7 +364,7 @@ export default {
             move.move,
             "received",
             null,
-            {addTime:move.addTime});
+            {addTime: move.addTime});
           break;
         }
         case "resign":
@@ -384,7 +405,7 @@ export default {
           data.lastMove.move,
           "received",
           null,
-          {addTime:data.lastMove.addTime, initime:data.initime});
+          {addTime: data.lastMove.addTime, initime: data.initime});
       }
       if (data.drawSent) this.drawOffer = "received";
       if (data.score != "*") {
@@ -451,24 +472,19 @@ export default {
               game.players[0]
             ];
           }
-          // corr game: need to compute the clocks + initime
           // NOTE: clocks in seconds, initime in milliseconds
-          game.clocks = [tc.mainTime, tc.mainTime];
           game.moves.sort((m1, m2) => m1.idx - m2.idx); //in case of
           const L = game.moves.length;
           if (game.score == "*") {
             // Set clocks + initime
+            game.clocks = [tc.mainTime, tc.mainTime];
             game.initime = [0, 0];
-            if (L >= 3) {
-              let addTime = [0, 0];
-              for (let i = 2; i < L; i++) {
-                addTime[i % 2] +=
-                  tc.increment -
-                  (game.moves[i].played - game.moves[i - 1].played) / 1000;
-              }
-              for (let i = 0; i <= 1; i++) game.clocks[i] += addTime[i];
+            if (L >= 1) {
+              const gameLastupdate = game.moves[L-1].played;
+              game.initime[L % 2] = gameLastupdate;
+              if (L >= 2)
+                game.clocks[L % 2] = Date.now() - gameLastupdate;
             }
-            if (L >= 1) game.initime[L % 2] = game.moves[L - 1].played;
           }
           // Sort chat messages from newest to oldest
           game.chats.sort((c1, c2) => {
@@ -621,20 +637,24 @@ export default {
           var filtered_move = getFilteredMove(move);
         }
         // Send move ("newmove" event) to people in the room (if our turn)
-        let addTime = data ? data.addTime : 0;
+        let addTime = (data && this.game.type == "live") ? data.addTime : 0;
         if (moveCol == this.game.mycolor) {
           if (this.drawOffer == "received")
             // I refuse draw
             this.drawOffer = "";
-          if (this.game.movesCount >= 2) {
+          // 'addTime' is irrelevant for corr games:
+          if (this.game.type == "live" && this.game.movesCount >= 2) {
             const elapsed = Date.now() - this.game.initime[colorIdx];
             // elapsed time is measured in milliseconds
             addTime = this.game.increment - elapsed / 1000;
           }
           const sendMove = {
             move: filtered_move,
-            addTime: addTime,
-            cancelDrawOffer: this.drawOffer == ""
+            addTime: addTime, //undefined for corr games
+            cancelDrawOffer: this.drawOffer == "",
+            // Players' SID required for /mygames page
+            // TODO: precompute and add this field to game object?
+            players: this.game.players.map(p => p.sid)
           };
           this.send("newmove", { data: sendMove });
         }
@@ -642,9 +662,13 @@ export default {
         playMove(move, this.vr);
         this.game.movesCount++;
         // (add)Time indication: useful in case of lastate infos requested
-        this.game.moves.push({move:move, addTime:addTime});
+        this.game.moves.push(this.game.type == "live"
+          ? {move:move, addTime:addTime}
+          : move);
         this.game.fen = this.vr.getFen();
-        this.game.clocks[colorIdx] += addTime;
+        if (this.game.type == "live") this.game.clocks[colorIdx] += addTime;
+        // In corr games, just reset clock to mainTime:
+        else this.game.clocks[colorIdx] = extractTime(this.game.cadence).mainTime;
         // data.initime is set only when I receive a "lastate" move from opponent
         this.game.initime[nextIdx] = (data && data.initime) ? data.initime : Date.now();
         this.re_setClocks();
@@ -717,16 +741,6 @@ export default {
       }
       else doProcessMove();
     },
-    resetChatColor: function() {
-      // TODO: this is called twice, once on opening an once on closing
-      document.getElementById("chatBtn").classList.remove("somethingnew");
-    },
-    processChat: function(chat) {
-      this.send("newchat", { data: chat });
-      // NOTE: anonymous chats in corr games are not stored on server (TODO?)
-      if (this.game.type == "corr" && this.st.user.id > 0)
-        GameStorage.update(this.gameRef.id, { chat: chat });
-    },
     gameOver: function(score, scoreMsg) {
       this.game.score = score;
       this.$set(this.game, "scoreMsg", scoreMsg || getScoreMessage(score));