Some improvements + simplify TODOs
[xogo.git] / server.js
index 7dbbaac..37a343e 100644 (file)
--- a/server.js
+++ b/server.js
@@ -10,55 +10,59 @@ const variants = require("./variants.js");
 const Crypto = require("crypto");
 const randstrSize = 8;
 
-const send = (sid, code, data) => {
+function send(sid, code, data) {
   const socket = sockets[sid];
   // If a player deletes local infos and then tries to resume a game,
   // sockets[oppSid] will probably not exist anymore:
   if (socket) socket.send(JSON.stringify(Object.assign({ code: code }, data)));
-};
+}
 
-wss.on("connection", function connection(socket, req) {
+function launchGame(vname, players, options) {
+  const gid =
+    Crypto.randomBytes(randstrSize).toString("hex").slice(0, randstrSize);
+  games[gid] = {
+    vname: vname,
+    players: players,
+    options: options,
+    time: Date.now()
+  };
+  if (players.every(p => p)) {
+    const gameInfo = Object.assign(
+      // Provide seed so that both players initialize with same FEN
+      {seed: Math.floor(Math.random() * 1984), gid: gid},
+      games[gid]);
+    for (const p of players) {
+      send(p.sid,
+           "gamestart",
+           Object.assign({randvar: p.randvar}, gameInfo));
+    }
+  }
+  else {
+    // Incomplete players array: do not start game yet
+    send(sid, "gamecreated", {gid: gid});
+    // If nobody joins within 5 minutes, delete game
+    setTimeout(
+      () => {
+        if (games[gid] && games[gid].players.some(p => !p))
+          delete games[gid];
+      },
+      5 * 60000
+    );
+  }
+}
+
+function getRandomVariant() {
+  // Pick a variant at random in the list
+  const index = Math.floor(Math.random() * variants.length);
+  return variants[index].name;
+}
+
+wss.on("connection", (socket, req) => {
   const sid = req.url.split("=")[1]; //...?sid=...
   sockets[sid] = socket;
   socket.isAlive = true;
   socket.on("pong", () => socket.isAlive = true);
 
-  function launchGame(vname, players, options) {
-    const gid =
-      Crypto.randomBytes(randstrSize).toString("hex").slice(0, randstrSize);
-    games[gid] = {
-      vname: vname,
-      players: players.map(p => {
-                 return (!p ? null : {sid: p.sid, name: p.name});
-               }),
-      options: options,
-      time: Date.now()
-    };
-    if (players.every(p => p)) {
-      const gameInfo = Object.assign(
-        // Provide seed so that both players initialize with same FEN
-        {seed: Math.floor(Math.random() * 1984), gid: gid},
-        games[gid]);
-      for (const p of players) {
-        send(p.sid,
-             "gamestart",
-             Object.assign({randvar: p.randvar}, gameInfo));
-      }
-    }
-    else {
-      // Incomplete players array: do not start game yet
-      send(sid, "gamecreated", {gid: gid});
-      // If nobody joins within 5 minutes, delete game
-      setTimeout(
-        () => {
-          if (games[gid] && games[gid].players.some(p => !p))
-            delete games[gid];
-        },
-        5 * 60000
-      );
-    }
-  }
-
   socket.on("message", (msg) => {
     const obj = JSON.parse(msg);
     switch (obj.code) {
@@ -83,11 +87,7 @@ wss.on("connection", function connection(socket, req) {
         }
         if (opponent) {
           delete challenges[choice];
-          if (choice == "_random") {
-            // Pick a variant at random in the list
-            const index = Math.floor(Math.random() * variants.length);
-            choice = variants[index].name;
-          }
+          if (choice == "_random") choice = getRandomVariant();
           // Launch game
           let players = [
             {sid: sid, name: obj.name, randvar: randvar},
@@ -120,11 +120,16 @@ wss.on("connection", function connection(socket, req) {
         if (!games[obj.gid]) send(sid, "closerematch");
         else {
           const myIndex = (games[obj.gid].players[0].sid == sid ? 0 : 1);
-          if (!games[obj.gid].rematch) games[obj.gid].rematch = [false, false];
-          games[obj.gid].rematch[myIndex] = true;
+          if (!games[obj.gid].rematch) games[obj.gid].rematch = [0, 0];
+          games[obj.gid].rematch[myIndex] = !obj.random ? 1 : 2;
           if (games[obj.gid].rematch[1-myIndex]) {
             // Launch new game, colors reversed
-            launchGame(games[obj.gid].vname,
+            let vname = games[obj.gid].vname;
+            const allrand = games[obj.gid].rematch.every(r => r == 2);
+            if (allrand) vname = getRandomVariant();
+            games[obj.gid].players.forEach(p =>
+              p.randvar = allrand ? true : false);
+            launchGame(vname,
                        games[obj.gid].players.reverse(),
                        games[obj.gid].options);
           }
@@ -196,6 +201,13 @@ wss.on("connection", function connection(socket, req) {
         break; //only one challenge per player
       }
     }
+    for (let g of Object.values(games)) {
+      const myIndex = g.players.findIndex(p => p.sid == sid);
+      if (myIndex >= 0) {
+        if (g.rematch && g.rematch[myIndex] > 0) g.rematch[myIndex] = 0;
+        break; //only one game per player
+      }
+    }
   });
 });