Show check(mate) indicators in moves list. No longer require the odd ?rid=... in...
[vchess.git] / client / src / views / Hall.vue
index b9262d1..d11da8b 100644 (file)
@@ -120,7 +120,7 @@ main
               @click="challenge(sid)"
             )
               | {{ st.tr["Challenge"] }}
-          p.anonymous @nonymous ({{ anonymousCount }})
+          p.anonymous @nonymous ({{ anonymousCount() }})
         #chat
           Chat(
             :newChat="newChat"
@@ -266,16 +266,6 @@ export default {
         this.loadNewchallVariant();
     }
   },
-  computed: {
-    anonymousCount: function() {
-      let count = 0;
-      Object.values(this.people).forEach(p => {
-        // Do not cound people who did not send their identity yet:
-        count += (!p.name && p.id === 0) ? 1 : 0;
-      });
-      return count;
-    }
-  },
   created: function() {
     if (this.st.variants.length > 0 && this.newchallenge.vid > 0)
       this.loadNewchallVariant();
@@ -338,14 +328,14 @@ export default {
           cursor: this.cursor
         },
         success: (response) => {
-          if (
-            response.games.length > 0 &&
-            this.games.length == 0 &&
-            this.gdisplay == "live"
-          ) {
-            document
-              .getElementById("btnGcorr")
-              .classList.add("somethingnew");
+          const L = response.games.length;
+          if (L > 0) {
+            this.cursor = response.games[L - 1].created;
+            if (this.games.length == 0 && this.gdisplay == "live") {
+              document
+                .getElementById("btnGcorr")
+                .classList.add("somethingnew");
+            }
           }
           this.games = this.games.concat(
             response.games.map(g => {
@@ -436,6 +426,14 @@ export default {
         ["random-" + pc.randomness]: true
       };
     },
+    anonymousCount: function() {
+      let count = 0;
+      Object.values(this.people).forEach(p => {
+        // Do not cound people who did not send their identity yet:
+        count += (!p.name && p.id === 0) ? 1 : 0;
+      });
+      return count;
+    },
     visibilityChange: function() {
       // TODO: Use document.hidden? https://webplatform.news/issues/2019-03-27
       this.send(
@@ -560,10 +558,7 @@ export default {
     showGame: function(g) {
       // NOTE: we are an observer, since only games I don't play are shown here
       // ==> Moves sent by connected remote player(s) if live game
-      let url = "/game/" + g.id;
-      if (g.type == "live")
-        url += "?rid=" + g.rids[Math.floor(Math.random() * g.rids.length)];
-      this.$router.push(url);
+      this.$router.push("/game/" + g.id);
     },
     resetSocialColor: function() {
       // TODO: this is called twice, once on opening an once on closing
@@ -605,21 +600,26 @@ export default {
             if (!s.page)
               // Peer is in Hall
               this.send("askchallenges", { target: s.sid });
-            // Peer is in Game
-            else this.send("askgame", { target: s.sid, page: page });
+            // Peer is in Game: ask only if live game
+            else if (!page.match(/\/[0-9]+$/))
+              this.send("askgame", { target: s.sid, page: page });
           });
           break;
         }
         case "connect":
         case "gconnect": {
           const page = data.page || "/";
-          // Only ask game / challenges if first connexion:
-          if (!this.people[data.from]) {
-            this.people[data.from] = { pages: [{ path: page, focus: true }] };
-            if (data.code == "connect")
+          if (data.code == "connect") {
+            // Ask challenges only on first connexion:
+            if (!this.people[data.from])
               this.send("askchallenges", { target: data.from });
-            else this.send("askgame", { target: data.from, page: page });
-          } else {
+          }
+          // Ask game only if live:
+          else if (!page.match(/\/[0-9]+$/))
+            this.send("askgame", { target: data.from, page: page });
+          if (!this.people[data.from])
+            this.people[data.from] = { pages: [{ path: page, focus: true }] };
+          else {
             // Append page if not already in list
             if (!(this.people[data.from].pages.find(p => p.path == page)))
               this.people[data.from].pages.push({ path: page, focus: true });
@@ -637,6 +637,10 @@ export default {
           // the first reload won't have time to connect but will trigger a "close" event anyway.
           // ==> Next check is required.
           if (!this.people[data.from]) return;
+          const page = data.page || "/";
+          ArrayFun.remove(this.people[data.from].pages, p => p.path == page);
+          if (this.people[data.from].pages.length == 0)
+            this.$delete(this.people, data.from);
           // Disconnect means no more tmpIds:
           if (data.code == "disconnect") {
             // Remove the live challenges sent by this player:
@@ -647,22 +651,16 @@ export default {
             );
           } else {
             // Remove the matching live game if now unreachable
-            const gid = data.page.match(/[a-zA-Z0-9]+$/)[0];
+            const gid = page.match(/[a-zA-Z0-9]+$/)[0];
             // Corr games are always reachable:
             if (!gid.match(/^[0-9]+$/)) {
-              const gidx = this.games.findIndex(g => g.id == gid);
-              // NOTE: gidx should always be >= 0 (TODO?)
-              if (gidx >= 0) {
-                const game = this.games[gidx];
-                ArrayFun.remove(game.rids, rid => rid == data.from);
-                if (game.rids.length == 0) this.games.splice(gidx, 1);
+              // Live games are reachable as long as someone is on the game page
+              if (Object.values(this.people).every(p =>
+                p.pages.every(pg => pg.path != page))) {
+                ArrayFun.remove(this.games, g => g.id == gid);
               }
             }
           }
-          const page = data.page || "/";
-          ArrayFun.remove(this.people[data.from].pages, p => p.path == page);
-          if (this.people[data.from].pages.length == 0)
-            this.$delete(this.people, data.from);
           break;
         }
         case "getfocus":
@@ -772,35 +770,30 @@ export default {
           }
           break;
         }
-        case "game": {
-          // Individual request
+        case "game": // Individual request
+        case "newgame": {
           const game = data.data;
-          // Ignore games where I play (will go in MyGames page)
-          if (game.players.every(p =>
-            p.sid != this.st.user.sid && p.id != this.st.user.id))
-          {
-            let locGame = this.games.find(g => g.id == game.id);
-            if (!locGame) {
-              let newGame = game;
-              newGame.type = this.classifyObject(game);
-              newGame.vname = this.getVname(game.vid);
-              if (!game.score)
-                // New game from Hall
-                newGame.score = "*";
-              newGame.rids = [game.rid];
-              delete newGame["rid"];
-              this.games.push(newGame);
-              if (
-                (newGame.type == "live" && this.gdisplay == "corr") ||
-                (newGame.type == "corr" && this.gdisplay == "live")
-              ) {
-                document
-                  .getElementById("btnG" + newGame.type)
-                  .classList.add("somethingnew");
-              }
-            } else {
-              // Append rid (if not already in list)
-              if (!locGame.rids.includes(game.rid)) locGame.rids.push(game.rid);
+          // Ignore games where I play (will go in MyGames page),
+          // and also games that I already received.
+          if (
+            game.players.every(p =>
+              p.sid != this.st.user.sid && p.id != this.st.user.id) &&
+            this.games.findIndex(g => g.id == game.id) == -1
+          ) {
+            let newGame = game;
+            newGame.type = this.classifyObject(game);
+            newGame.vname = this.getVname(game.vid);
+            if (!game.score)
+              // New game from Hall
+              newGame.score = "*";
+            this.games.push(newGame);
+            if (
+              (newGame.type == "live" && this.gdisplay == "corr") ||
+              (newGame.type == "corr" && this.gdisplay == "live")
+            ) {
+              document
+                .getElementById("btnG" + newGame.type)
+                .classList.add("somethingnew");
             }
           }
           break;
@@ -851,8 +844,8 @@ export default {
             cursor: this.cursor
           },
           success: (res) => {
-            if (res.games.length > 0) {
-              const L = res.games.length;
+            const L = res.games.length;
+            if (L > 0) {
               this.cursor = res.games[L - 1].created;
               let moreGames = res.games.map(g => {
                 const vname = this.getVname(g.vid);
@@ -900,10 +893,13 @@ export default {
     },
     loadNewchallVariant: async function(cb) {
       const vname = this.getVname(this.newchallenge.vid);
-      const vModule = await import("@/variants/" + vname + ".js");
-      this.newchallenge.V = vModule.VariantRules;
-      this.newchallenge.vname = vname;
-      if (!!cb) cb();
+      await import("@/variants/" + vname + ".js")
+      .then((vModule) => {
+        window.V = vModule[vname + "Rules"];
+        this.newchallenge.V = window.V;
+        this.newchallenge.vname = vname;
+        if (!!cb) cb();
+      });
     },
     trySetNewchallDiag: function() {
       if (!this.newchallenge.fen) {
@@ -1015,7 +1011,6 @@ export default {
         });
         // Add new challenge:
         chall.from = {
-          // Decompose to avoid revealing email
           sid: this.st.user.sid,
           id: this.st.user.id,
           name: this.st.user.name
@@ -1049,7 +1044,7 @@ export default {
           {
             data: { chall: chall },
             success: (response) => {
-              finishAddChallenge(response.cid);
+              finishAddChallenge(response.id);
             }
           }
         );
@@ -1065,7 +1060,6 @@ export default {
     finishProcessingChallenge: function(c) {
       if (c.accepted) {
         c.seat = {
-          // Again, avoid c.seat = st.user to not reveal email
           sid: this.st.user.sid,
           id: this.st.user.id,
           name: this.st.user.name
@@ -1102,22 +1096,24 @@ export default {
           return;
         }
         c.accepted = true;
-        const vModule = await import("@/variants/" + c.vname + ".js");
-        window.V = vModule.VariantRules;
-        if (!!c.to) {
-          // c.to == this.st.user.name (connected)
-          if (!!c.fen) {
-            const parsedFen = V.ParseFen(c.fen);
-            c.mycolor = V.GetOppCol(parsedFen.turn);
-            this.tchallDiag = getDiagram({
-              position: parsedFen.position,
-              orientation: c.mycolor
-            });
+        await import("@/variants/" + c.vname + ".js")
+        .then((vModule) => {
+          window.V = vModule[c.vname + "Rules"];
+          if (!!c.to) {
+            // c.to == this.st.user.name (connected)
+            if (!!c.fen) {
+              const parsedFen = V.ParseFen(c.fen);
+              c.mycolor = V.GetOppCol(parsedFen.turn);
+              this.tchallDiag = getDiagram({
+                position: parsedFen.position,
+                orientation: c.mycolor
+              });
+            }
+            this.curChallToAccept = c;
+            document.getElementById("modalAccept").checked = true;
           }
-          this.curChallToAccept = c;
-          document.getElementById("modalAccept").checked = true;
-        }
-        else this.finishProcessingChallenge(c);
+          else this.finishProcessingChallenge(c);
+        });
       }
       else {
         // My challenge
@@ -1135,7 +1131,8 @@ export default {
     },
     // NOTE: when launching game, the challenge is already being deleted
     launchGame: function(c) {
-      let players =
+      // White player index 0, black player index 1:
+      const players =
         !!c.mycolor
           ? (c.mycolor == "w" ? [c.seat, c.from] : [c.from, c.seat])
           : shuffle([c.from, c.seat]);
@@ -1144,10 +1141,7 @@ export default {
         id: getRandString(),
         fen: c.fen || V.GenRandInitFen(c.randomness),
         randomness: c.randomness, //for rematch
-        // White player index 0, black player index 1:
-        players: c.mycolor
-          ? (c.mycolor == "w" ? [c.seat, c.from] : [c.from, c.seat])
-          : shuffle([c.from, c.seat]),
+        players: players,
         vid: c.vid,
         cadence: c.cadence
       };
@@ -1156,14 +1150,22 @@ export default {
         if (!!oppsid)
           // Opponent is online
           this.send("startgame", { data: gameInfo, target: oppsid });
+        // If new corr game, notify Hall (except opponent and me)
+        if (c.type == "corr") {
+          this.send(
+            "newgame",
+            {
+              data: gameInfo,
+              excluded: [this.st.user.sid, oppsid]
+            }
+          );
+        }
         // Notify MyGames page:
         this.send(
           "notifynewgame",
           {
             data: gameInfo,
-            targets: gameInfo.players.map(p => {
-              return { sid: p.sid, id: p.id };
-            })
+            targets: gameInfo.players
           }
         );
         // NOTE: no need to send the game to the room, since I'll connect
@@ -1179,11 +1181,14 @@ export default {
           "POST",
           {
             // cid is useful to delete the challenge:
-            data: { gameInfo: gameInfo, cid: c.id },
+            data: {
+              gameInfo: gameInfo,
+              cid: c.id
+            },
             success: (response) => {
-              gameInfo.id = response.gameId;
+              gameInfo.id = response.id;
               notifyNewgame();
-              this.$router.push("/game/" + response.gameId);
+              this.$router.push("/game/" + response.id);
             }
           }
         );
@@ -1328,8 +1333,8 @@ tr > td
     margin: 5px 0
 
 button#loadMoreBtn
-  margin-top: 0
-  margin-bottom: 0
+  display: block
+  margin: 0 auto
 
 td.remove-preset
   background-color: lightgrey