Fix accumulation of socket.close code. Ready to finish Game.js and then the website
[vchess.git] / client / src / views / Hall.vue
index 95a9e95..a16b5b5 100644 (file)
@@ -141,21 +141,21 @@ export default {
         response => {
           console.log(response.challenges);
           // TODO: post-treatment on challenges ?
-          this.challenges = this.challenges.concat(response.challenges);
+          Array.prototype.push.apply(this.challenges, response.challenges);
         }
       );
     }
     // 0.1] Ask server for room composition:
-    const socketOpenListener = () => {
+    const funcPollClients = () => {
       this.st.conn.send(JSON.stringify({code:"pollclients"}));
     };
-    this.st.conn.onopen = socketOpenListener;
-    // TODO: is this required here?
-    this.oldOnmessage = this.st.conn.onmessage || Function.prototype;
+    if (!!this.st.conn && this.st.conn.readyState == 1) //1 == OPEN state
+      funcPollClients();
+    else //socket not ready yet (initial loading)
+      this.st.conn.onopen = funcPollClients;
     this.st.conn.onmessage = this.socketMessageListener;
-    const oldOnclose = this.st.conn.onclose;
     const socketCloseListener = () => {
-      oldOnclose(); //reinitialize connexion (in store.js)
+      store.socketCloseListener(); //reinitialize connexion (in store.js)
       this.st.conn.addEventListener('message', this.socketMessageListener);
       this.st.conn.addEventListener('close', socketCloseListener);
     };
@@ -176,14 +176,12 @@ 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
-      
-// TODO: this doesn't work: choose a SID at random
-
-      let url = "/" + g.id;
+      let url = "/game/" + g.id;
       if (g.type == "live")
       {
-        const sids = g.players.map(p => p.sid).join(",");
-        url += "?sids=" + sids;
+        const remotes = g.players.filter(p => this.people.some(pl => pl.sid == p.sid));
+        const rIdx = (remotes.length == 1 ? 0 : Math.floor(Math.random()*2));
+        url += "?rid=" + remotes[rIdx].sid;
       }
       this.$router.push(url);
     },
@@ -231,9 +229,6 @@ export default {
     },
     // Messaging center:
     socketMessageListener: function(msg) {
-      // Save and call current st.conn.onmessage if one was already defined
-      // --> also needed in future Game.vue (also in Chat.vue component)
-      this.oldOnmessage(msg);
       const data = JSON.parse(msg.data);
       switch (data.code)
       {
@@ -324,43 +319,33 @@ export default {
         {
           // Receive game from some player (+sid)
           // NOTE: it may be correspondance (if newgame while we are connected)
-          let newGame = data.game;
-          newGame.type = this.classifyObject(data.game);
-          newGame.rid = data.from;
-          newGame.score = "*";
-          this.games.push(newGame);
+          if (!this.games.some(g => g.id == data.game.id)) //ignore duplicates
+          {
+            let newGame = data.game;
+            newGame.type = this.classifyObject(data.game);
+            newGame.rid = data.from;
+            newGame.score = "*";
+            this.games.push(newGame);
+          }
           break;
         }
-// *  - receive "new game": if live, store locally + redirect to game
-// *    If corr: notify "new game has started", give link, but do not redirect
         case "newgame":
         {
-          // Delete corresponding challenge:
-          ArrayFun.remove(this.challenges, c => c.id == data.cid);
           // New game just started: data contain all informations
           this.startNewGame(data.gameInfo);
-          break;
-        }
-// *  - receive "accept/cancel challenge": apply action to challenges list
-        // NOTE: challenge "socket" actions accept+withdraw only for live challenges
-        case "acceptchallenge":
-        {
-          // Someone accept an open (or targeted) challenge
-          const cIdx = this.challenges.findIndex(c => c.id == data.cid);
-          let c = this.challenges[cIdx];
-          const pIdx = this.people.findIndex(p => p.sid == data.from);
-          c.seat = this.people[pIdx];
-          this.launchGame(c);
+          // TODO: if live, redirect to game
+          // if corr, notify with link but do not redirect
           break;
         }
         case "refusechallenge":
         {
-          alert(this.getPname(data.from) + " refused your challenge");
+          alert(this.getPname(data.from) + " declined your challenge");
           ArrayFun.remove(this.challenges, c => c.id == data.cid);
           break;
         }
         case "deletechallenge":
         {
+          // NOTE: the challenge may be already removed
           ArrayFun.remove(this.challenges, c => c.id == data.cid);
           break;
         }
@@ -453,68 +438,46 @@ export default {
         );
       }
     },
-// *  - accept challenge (corr or live) --> send info to challenge creator
-// *  - cancel challenge (click on sent challenge) --> send info to all concerned players
-// *    --> send info to challenge creator
-// *  - refuse challenge: send "refuse" to challenge sender, and "delete" to others
-// *  - prepare and start new game (if challenge is full after acceptation)
-// *    --> include challenge ID (so that opponents can delete the challenge too)
     clickChallenge: function(c) {
-
-      console.log("click challenge");
-      console.log(c);
-
-      if (c.from.sid == this.st.user.sid
-        || (this.st.user.id > 0 && c.from.id == this.st.user.id))
-      {
-        // It's my challenge: cancel it
-        this.sendSomethingTo(c.to, "deletechallenge", {cid:c.id});
-        ArrayFun.remove(this.challenges, ch => ch.id == c.id);
-        if (c.type == "corr")
-        {
-          ajax(
-            "/challenges",
-            "DELETE",
-            {id: this.challenges[cIdx].id}
-          );
-        }
-      }
-      else //accept (or refuse) a challenge
+      const myChallenge = (c.from.sid == this.st.user.sid //live
+        || (this.st.user.id > 0 && c.from.id == this.st.user.id)); //corr
+      if (!myChallenge)
       {
         c.accepted = true;
-        if (!!c.to[0])
+        if (!!c.to) //c.to == this.st.user.name (connected)
         {
           // TODO: if special FEN, show diagram after loading variant
           c.accepted = confirm("Accept challenge?");
         }
-        this.st.conn.send(JSON.stringify({
-          code: (c.accepted ? "accept" : "refuse") + "challenge",
-          cid: c.id, target: c.from.sid}));
-        if (c.type == "corr" && c.accepted)
+        if (c.accepted)
         {
-          ajax(
-            "/challenges",
-            "PUT",
-            {id: this.challenges[cIdx].id}
-          );
+          c.seat = this.st.user;
+          this.launchGame(c);
         }
-        if (!c.accepted)
+        else
         {
-          ArrayFun.remove(this.challenges, ch => ch.id == c.id);
-          if (c.type == "corr")
-          {
-            ajax(
-              "/challenges",
-              "DELETE",
-              {id: this.challenges[cIdx].id}
-            );
-          }
+          this.st.conn.send(JSON.stringify({
+            code: "refusechallenge",
+            cid: c.id, target: c.from.sid}));
         }
       }
+      else
+        localStorage.removeItem("challenge");
+      // In all cases, the challenge is consumed:
+      ArrayFun.remove(this.challenges, ch => ch.id == c.id);
+      // NOTE: deletechallenge event might be redundant (but it's easier this way)
+      this.sendSomethingTo(c.to, "deletechallenge", {cid:c.id});
+      if (c.type == "corr")
+      {
+        ajax(
+          "/challenges",
+          "DELETE",
+          {id: this.challenges[cIdx].id}
+        );
+      }
     },
-    // NOTE: for live games only (corr games are launched on server)
+    // NOTE: when launching game, the challenge is already deleted
     launchGame: async function(c) {
-      // Just assign colors and pass the message
       const vname = this.getVname(c.vid);
       const vModule = await import("@/variants/" + vname + ".js");
       window.V = vModule.VariantRules;
@@ -525,17 +488,23 @@ export default {
         gameId: getRandString(),
         fen: c.fen || V.GenRandInitFen(),
         // Players' names may be required if game start when a player is offline
-        // Shuffle players order (white then black then other colors).
+        // Shuffle players order (white then black).
         players: shuffle(players.map(p => { return {name:p.name, sid:p.sid} })),
         vid: c.vid,
         timeControl: c.timeControl,
       };
-      // NOTE: cid required to remove challenge
       this.st.conn.send(JSON.stringify({code:"newgame",
-        gameInfo:gameInfo, cid:c.id, target:c.seat.sid}));
-      // Delete corresponding challenge:
-      ArrayFun.remove(this.challenges, ch => ch.id == c.id);
-      this.startNewGame(gameInfo); //also!
+        gameInfo:gameInfo, target:c.seat.sid}));
+      if (c.type == "live")
+        this.startNewGame(gameInfo);
+      else //corr: game only on server
+      {
+        ajax(
+          "/games",
+          "POST",
+          {gameInfo: gameInfo}
+        );
+      }
     },
     // NOTE: for live games only (corr games are launched on server)
     startNewGame: function(gameInfo) {
@@ -572,9 +541,3 @@ export default {
 <style lang="sass">
 // TODO
 </style>
-
-<!--
-// TODO:
-// Remove duplicates if several players of one game send their game info (Hall)
-// When click on it, assign a random rid among online players (max. 4).
--->