From: Benjamin Auder <benjamin.auder@somewhere>
Date: Tue, 3 Mar 2020 16:01:38 +0000 (+0100)
Subject: Better time control in correspondance games
X-Git-Url: https://git.auder.net/doc/html/app_dev.php/current/css/%7B%7B%20targetUrl%20%7D%7D?a=commitdiff_plain;h=92240cf0fbf76ddf8a030ba1f846d6c62b1e9979;p=vchess.git

Better time control in correspondance games
---

diff --git a/client/public/images/pieces/Check3/bk_1.svg b/client/public/images/pieces/Threechecks/bk_1.svg
similarity index 100%
rename from client/public/images/pieces/Check3/bk_1.svg
rename to client/public/images/pieces/Threechecks/bk_1.svg
diff --git a/client/public/images/pieces/Check3/bk_2.svg b/client/public/images/pieces/Threechecks/bk_2.svg
similarity index 100%
rename from client/public/images/pieces/Check3/bk_2.svg
rename to client/public/images/pieces/Threechecks/bk_2.svg
diff --git a/client/public/images/pieces/Check3/bk_3.svg b/client/public/images/pieces/Threechecks/bk_3.svg
similarity index 100%
rename from client/public/images/pieces/Check3/bk_3.svg
rename to client/public/images/pieces/Threechecks/bk_3.svg
diff --git a/client/public/images/pieces/Check3/wk_1.svg b/client/public/images/pieces/Threechecks/wk_1.svg
similarity index 100%
rename from client/public/images/pieces/Check3/wk_1.svg
rename to client/public/images/pieces/Threechecks/wk_1.svg
diff --git a/client/public/images/pieces/Check3/wk_2.svg b/client/public/images/pieces/Threechecks/wk_2.svg
similarity index 100%
rename from client/public/images/pieces/Check3/wk_2.svg
rename to client/public/images/pieces/Threechecks/wk_2.svg
diff --git a/client/public/images/pieces/Check3/wk_3.svg b/client/public/images/pieces/Threechecks/wk_3.svg
similarity index 100%
rename from client/public/images/pieces/Check3/wk_3.svg
rename to client/public/images/pieces/Threechecks/wk_3.svg
diff --git a/client/src/utils/timeControl.js b/client/src/utils/timeControl.js
index 9106b96c..b4bac053 100644
--- a/client/src/utils/timeControl.js
+++ b/client/src/utils/timeControl.js
@@ -14,9 +14,9 @@ function timeUnitToSeconds(value, unit) {
   return seconds;
 }
 
+// Used only if increment, hence live game: no "day" unit
 function isLargerUnit(unit1, unit2) {
   return (
-    (unit1 == "d" && unit2 != "d") ||
     (unit1 == "h" && ["s", "m"].includes(unit2)) ||
     (unit1 == "m" && unit2 == "s")
   );
@@ -24,9 +24,8 @@ function isLargerUnit(unit1, unit2) {
 
 export function extractTime(cadence) {
   let tcParts = cadence.replace(/ /g, "").split("+");
-  // Concatenate usual time control suffixes, in case of none is provided
+  // Concatenate usual time control suffix, in case of none is provided
   tcParts[0] += "m";
-  tcParts[1] += "s";
   const mainTimeArray = tcParts[0].match(/^([0-9]+)([smhd]+)$/);
   if (!mainTimeArray) return null;
   const mainTimeValue = parseInt(mainTimeArray[1]);
@@ -34,6 +33,7 @@ export function extractTime(cadence) {
   const mainTime = timeUnitToSeconds(mainTimeValue, mainTimeUnit);
   let increment = 0;
   if (tcParts.length >= 2) {
+    tcParts[1] += "s";
     const incrementArray = tcParts[1].match(/^([0-9]+)([smhd]+)$/);
     if (!incrementArray) return null;
     const incrementValue = parseInt(incrementArray[1]);
diff --git a/client/src/variants/Check3.js b/client/src/variants/Threechecks.js
similarity index 92%
rename from client/src/variants/Check3.js
rename to client/src/variants/Threechecks.js
index ea5ab841..78aaf1f8 100644
--- a/client/src/variants/Check3.js
+++ b/client/src/variants/Threechecks.js
@@ -1,6 +1,6 @@
 import { ChessRules } from "@/base_rules";
 
-export const VariantRules = class Check3Rules extends ChessRules {
+export const VariantRules = class ThreechecksRules extends ChessRules {
   static IsGoodFlags(flags) {
     // 4 for castle + 2 for checks (0,1 or 2)
     return !!flags.match(/^[01]{4,4}[012]{2,2}$/);
@@ -28,7 +28,7 @@ export const VariantRules = class Check3Rules extends ChessRules {
     // TODO: !!this.checkFlags condition for printDiagram, but clearly not good.
     // This is just a temporary fix.
     if (b[1] == 'k' && this.checkFlags && this.checkFlags[b[0]] > 0)
-      return "Check3/" + b[0] + 'k_' + this.checkFlags[b[0]];
+      return "Threechecks/" + b[0] + 'k_' + this.checkFlags[b[0]];
     return b;
   }
 
diff --git a/client/src/views/Game.vue b/client/src/views/Game.vue
index 1675c30b..758759dc 100644
--- a/client/src/views/Game.vue
+++ b/client/src/views/Game.vue
@@ -364,7 +364,7 @@ export default {
             move.move,
             "received",
             null,
-            {addTime:move.addTime});
+            {addTime: move.addTime});
           break;
         }
         case "resign":
@@ -405,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 != "*") {
@@ -472,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) => {
@@ -642,19 +637,20 @@ 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,
+            addTime: addTime, //undefined for corr games
             cancelDrawOffer: this.drawOffer == "",
             // Players' SID required for /mygames page
             // TODO: precompute and add this field to game object?
@@ -666,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();
diff --git a/client/src/views/Hall.vue b/client/src/views/Hall.vue
index 5ceb7e32..8d7d405f 100644
--- a/client/src/views/Hall.vue
+++ b/client/src/views/Hall.vue
@@ -45,14 +45,14 @@ main
         fieldset
           label(for="cadence") {{ st.tr["Cadence"] }} *
           div#predefinedCadences
-            button(type="button") 5+3
             button(type="button") 15+5
             button(type="button") 45+30
-            button(type="button") 7d+2d
+            button(type="button") 3d
+            button(type="button") 7d
           input#cadence(
             type="text"
             v-model="newchallenge.cadence"
-            placeholder="5+0, 1h+30s, 7d+1d ..."
+            placeholder="5+0, 1h+30s, 5d ..."
           )
         fieldset(v-if="st.user.id > 0")
           label(for="selectPlayers") {{ st.tr["Play with?"] }}
diff --git a/server/db/populate.sql b/server/db/populate.sql
index 60cd18e9..0989f716 100644
--- a/server/db/populate.sql
+++ b/server/db/populate.sql
@@ -11,7 +11,6 @@ insert or ignore into Variants (name,description) values
   ('Benedict', 'Change colors'),
   ('Berolina', 'Pawns move diagonally'),
   ('Checkered', 'Shared pieces'),
-  ('Check3', 'Give three checks'),
   ('Chess960', 'Standard rules'),
   ('Circular', 'Run forward'),
   ('Crazyhouse', 'Captures reborn'),
@@ -33,6 +32,7 @@ insert or ignore into Variants (name,description) values
   ('Recycle', 'Reuse pieces'),
   ('Shatranj', 'Ancient rules'),
   ('Suction', 'Attract opposite king'),
+  ('Threechecks', 'Give three checks'),
   ('Upsidedown', 'Board upside down'),
   ('Wildebeest', 'Balanced sliders & leapers'),
   ('Wormhole', 'Squares disappear'),