Fix moves update
[vchess.git] / server / models / Game.js
1 var db = require("../utils/database");
2
3 /*
4 * Structure table Games:
5 * id: game id (int)
6 * vid: integer (variant id)
7 * fenStart: varchar (initial position)
8 * fen: varchar (current position)
9 * timeControl: string
10 * score: varchar (result)
11 *
12 * Structure table Players:
13 * gid: ref game id
14 * uid: ref user id
15 * color: character
16 *
17 * Structure table Moves:
18 * gid: ref game id
19 * squares: varchar (description)
20 * message: text
21 * played: datetime
22 * idx: integer
23 * color: character
24 */
25
26 const GameModel =
27 {
28 create: function(vid, fen, timeControl, players, cb)
29 {
30 db.serialize(function() {
31 let query =
32 "INSERT INTO Games (vid, fenStart, fen, score, timeControl) VALUES " +
33 "(" + vid + ",'" + fen + "','" + fen + "','*','" + timeControl + "')";
34 db.run(query, function(err) {
35 if (!!err)
36 return cb(err);
37 players.forEach((p,idx) => {
38 const color = (idx==0 ? "w" : "b");
39 query =
40 "INSERT INTO Players VALUES " +
41 "(" + this.lastID + "," + p.id + ",'" + color + "')";
42 db.run(query);
43 });
44 cb(null, {gid: this.lastID});
45 });
46 });
47 },
48
49 // TODO: queries here could be async, and wait for all to complete
50 getOne: function(id, cb)
51 {
52 db.serialize(function() {
53 // TODO: optimize queries?
54 let query =
55 "SELECT g.id, g.vid, g.fen, g.fenStart, g.timeControl, g.score, " +
56 "v.name AS vname " +
57 "FROM Games g " +
58 "JOIN Variants v " +
59 " ON g.vid = v.id " +
60 "WHERE g.id = " + id;
61 db.get(query, (err,gameInfo) => {
62 if (!!err)
63 return cb(err);
64 query =
65 "SELECT p.uid, p.color, u.name " +
66 "FROM Players p " +
67 "JOIN Users u " +
68 " ON p.uid = u.id " +
69 "WHERE p.gid = " + id;
70 db.all(query, (err2,players) => {
71 if (!!err2)
72 return cb(err2);
73 query =
74 "SELECT squares, message, played, idx, color " +
75 "FROM Moves " +
76 "WHERE gid = " + id;
77 db.all(query, (err3,moves) => {
78 if (!!err3)
79 return cb(err3);
80 const game = Object.assign({},
81 gameInfo,
82 {
83 players: players,
84 moves: moves
85 }
86 );
87 return cb(null, game);
88 });
89 });
90 });
91 });
92 },
93
94 getByUser: function(uid, excluded, cb)
95 {
96 db.serialize(function() {
97 // Next query is fine because a player appear at most once in a game
98 const query =
99 "SELECT gid " +
100 "FROM Players " +
101 "WHERE uid " + (excluded ? "<>" : "=") + " " + uid;
102 db.run(query, (err,gameIds) => {
103 if (!!err)
104 return cb(err);
105 gameIds = gameIds || []; //might be empty
106 let gameArray = [];
107 gameIds.forEach(gidRow => {
108 GameModel.getOne(gidRow["gid"], (err2,game) => {
109 if (!!err2)
110 return cb(err2);
111 gameArray.push(game);
112 });
113 });
114 return cb(null, gameArray);
115 });
116 });
117 },
118
119 getPlayers: function(id, cb)
120 {
121 db.serialize(function() {
122 const query =
123 "SELECT id " +
124 "FROM Players " +
125 "WHERE gid = " + id;
126 db.all(query, (err,players) => {
127 return cb(err, players);
128 });
129 });
130 },
131
132 // obj can have fields move, fen and/or score
133 update: function(id, obj)
134 {
135 db.parallelize(function() {
136 let query =
137 "UPDATE Games " +
138 "SET ";
139 if (!!obj.fen)
140 query += "fen = '" + obj.fen + "',";
141 if (!!obj.score)
142 query += "score = '" + obj.score + "',";
143 query = query.slice(0,-1); //remove last comma
144 query += " WHERE id = " + id;
145 db.run(query);
146 if (!!obj.move)
147 {
148 const m = obj.move;
149 query =
150 "INSERT INTO Moves (gid,squares,message,played,idx,color) VALUES " +
151 "(" + id + ",'" + JSON.stringify(m.squares) + "','" + m.message +
152 "'," + m.played + "," + m.idx + ",'" + m.color + "')";
153 db.run(query);
154 }
155 });
156 },
157
158 remove: function(id)
159 {
160 db.parallelize(function() {
161 let query =
162 "DELETE FROM Games " +
163 "WHERE id = " + id;
164 db.run(query);
165 query =
166 "DELETE FROM Players " +
167 "WHERE gid = " + id;
168 db.run(query);
169 query =
170 "DELETE FROM Moves " +
171 "WHERE gid = " + id;
172 db.run(query);
173 });
174 },
175 }
176
177 module.exports = GameModel;