Finished. Now some last styling
[vchess.git] / server / models / Game.js
index fa4aea0..02e3194 100644 (file)
@@ -1,4 +1,5 @@
 var db = require("../utils/database");
+const UserModel = require("./User");
 
 /*
  * Structure table Games:
@@ -8,7 +9,9 @@ var db = require("../utils/database");
  *   fen: varchar (current position)
  *   timeControl: string
  *   score: varchar (result)
+ *   scoreMsg: varchar ("Time", "Mutual agreement"...)
  *   created: datetime
+ *   drawOffer: boolean
  *
  * Structure table Players:
  *   gid: ref game id
@@ -18,13 +21,36 @@ var db = require("../utils/database");
  * Structure table Moves:
  *   gid: ref game id
  *   squares: varchar (description)
- *   message: text
  *   played: datetime
  *   idx: integer
+ *
+ * Structure table Chats:
+ *   gid: game id (int)
+ *   msg: varchar
+ *   name: varchar
+ *   added: datetime
  */
 
 const GameModel =
 {
+  checkGameInfo: function(g) {
+    if (!g.id.toString().match(/^[0-9]+$/))
+      return "Wrong game ID";
+    if (!g.vid.toString().match(/^[0-9]+$/))
+      return "Wrong variant ID";
+    if (!g.vname.match(/^[a-zA-Z0-9]+$/))
+      return "Wrong variant name";
+    if (!g.timeControl.match(/^[0-9dhms +]+$/))
+      return "Wrong characters in time control";
+    if (!g.fen.match(/^[a-zA-Z0-9, /-]*$/))
+      return "Bad FEN string";
+    if (g.players.length != 2)
+      return "Need exactly 2 players";
+    if (g.players.some(p => !p.id.toString().match(/^[0-9]+$/)))
+      return "Wrong characters in player ID";
+    return "";
+  },
+
        create: function(vid, fen, timeControl, players, cb)
        {
                db.serialize(function() {
@@ -54,8 +80,10 @@ const GameModel =
                db.serialize(function() {
       // TODO: optimize queries?
                        let query =
+        // NOTE: g.scoreMsg can be NULL
+        // (in this case score = "*" and no reason to look at it)
                                "SELECT g.id, g.vid, g.fen, g.fenStart, g.timeControl, g.score, " +
-          "v.name AS vname " +
+          "g.scoreMsg, v.name AS vname " +
                                "FROM Games g " +
         "JOIN Variants v " +
         "  ON g.vid = v.id " +
@@ -73,20 +101,29 @@ const GameModel =
                                        if (!!err2)
                                                return cb(err2);
                                        query =
-                                               "SELECT squares, message, played, idx " +
+                                               "SELECT squares, played, idx " +
                                                "FROM Moves " +
                                                "WHERE gid = " + id;
                                        db.all(query, (err3,moves) => {
                                                if (!!err3)
                                                        return cb(err3);
-                                               const game = Object.assign({},
-              gameInfo,
-                                                 {
-                                                         players: players,
-                                                         moves: moves
-              }
-            );
-                                               return cb(null, game);
+                             query =
+              "SELECT msg, name, added " +
+              "FROM Chats " +
+              "WHERE gid = " + id;
+                             db.all(query, (err4,chats) => {
+                                                 if (!!err4)
+                                                         return cb(err4);
+                                                 const game = Object.assign({},
+                gameInfo,
+                {
+                  players: players,
+                  moves: moves,
+                  chats: chats,
+                }
+              );
+                                                 return cb(null, game);
+            });
                                        });
                                });
                        });
@@ -134,30 +171,65 @@ const GameModel =
     });
   },
 
-  // obj can have fields move, fen, drawOffer and/or score
+  checkGameUpdate: function(obj)
+  {
+    // Check all that is possible (required) in obj:
+    if (!!obj.move)
+    {
+      if (!obj.move.played.toString().match(/^[0-9]+$/))
+        return "Wrong move played time";
+      if (!obj.move.idx.toString().match(/^[0-9]+$/))
+        return "Wrong move index";
+    }
+    if (!!obj.fen && !obj.fen.match(/^[a-zA-Z0-9, /-]*$/))
+      return "Wrong FEN string";
+    if (!!obj.score && !obj.score.match(/^[012?*\/-]+$/))
+      return "Wrong characters in score";
+    if (!!obj.scoreMsg && !obj.scoreMsg.match(/^[a-zA-Z ]+$/))
+      return "Wrong characters in score message";
+    if (!!obj.chat)
+      return UserModel.checkNameEmail({name: obj.chat.name});
+    return "";
+  },
+
+  // obj can have fields move, chat, fen, drawOffer and/or score
   update: function(id, obj)
   {
                db.parallelize(function() {
       let query =
         "UPDATE Games " +
         "SET ";
-      if (!!obj.drawOffer)
-        query += "drawOffer = " + obj.drawOffer + ",";
+      let modifs = "";
+      if (!!obj.message)
+        modifs += "message = message || ' ' || '" + obj.message + "',";
+      if ([true,false].includes(obj.drawOffer))
+        modifs += "drawOffer = " + obj.drawOffer + ",";
       if (!!obj.fen)
-        query += "fen = '" + obj.fen + "',";
+        modifs += "fen = '" + obj.fen + "',";
       if (!!obj.score)
-        query += "score = '" + obj.score + "',";
-      query = query.slice(0,-1); //remove last comma
-      query += " WHERE id = " + id;
-      db.run(query);
+        modifs += "score = '" + obj.score + "',";
+      if (!!obj.scoreMsg)
+        modifs += "scoreMsg = '" + obj.scoreMsg + "',";
+      modifs = modifs.slice(0,-1); //remove last comma
+      if (modifs.length > 0)
+      {
+        query += modifs + " WHERE id = " + id;
+        db.run(query);
+      }
       if (!!obj.move)
       {
         const m = obj.move;
         query =
-          "INSERT INTO Moves (gid, squares, message, played, idx) VALUES " +
-          "(" + id + ",'" + JSON.stringify(m.squares) + "','" + m.message +
-            "'," + m.played + "," + m.idx + ")";
-        db.run(query);
+          "INSERT INTO Moves (gid, squares, played, idx) VALUES " +
+          "(" + id + ",?," + m.played + "," + m.idx + ")";
+        db.run(query, JSON.stringify(m.squares));
+      }
+      if (!!obj.chat)
+      {
+                         query =
+               "INSERT INTO Chats (gid, msg, name, added) VALUES ("
+            + id + ",?,'" + obj.chat.name + "'," + "," + Date.now() + ")";
+        db.run(query, obj.chat.msg);
       }
     });
   },
@@ -177,6 +249,10 @@ const GameModel =
                                "DELETE FROM Moves " +
                                "WHERE gid = " + id;
                        db.run(query);
+                       query =
+                               "DELETE FROM Chats " +
+                               "WHERE gid = " + id;
+                       db.run(query);
                });
        },