Draft code reorganisation (+ fix Alice rules + stateless VariantRules object)
[vchess.git] / sockets.js
1 const url = require('url');
2 const sqlite3 = require('sqlite3');
3 const db = new sqlite3.Database(__dirname + "/db/vchess.sqlite");
4
5 // Node version in Ubuntu 16.04 does not know about URL class
6 function getJsonFromUrl(url) {
7 var query = url.substr(2); //starts with "/?"
8 var result = {};
9 query.split("&").forEach(function(part) {
10 var item = part.split("=");
11 result[item[0]] = decodeURIComponent(item[1]);
12 });
13 return result;
14 }
15
16 module.exports = function(wss) {
17 db.serialize(function() {
18 db.all("SELECT * FROM Variants", (err,variants) => {
19 let clients = { "index": {} };
20 let games = {}; //pending games (player sid)
21 for (const v of variants)
22 clients[v.name] = {};
23 // No-op function as a callback when sending messages
24 const noop = () => { };
25 wss.on("connection", (socket, req) => {
26 // const params = new URL("http://localhost" + req.url).searchParams;
27 // const sid = params.get("sid");
28 // const page = params.get("page");
29 var query = getJsonFromUrl(req.url);
30 const sid = query["sid"];
31 const page = query["page"];
32 // Ignore duplicate connections:
33 if (!!clients[page][sid])
34 {
35 socket.send(JSON.stringify({code:"duplicate"}));
36 return;
37 }
38 clients[page][sid] = socket;
39 if (page == "index")
40 {
41 // Send counting info
42 const countings = {};
43 for (const v of variants)
44 countings[v.name] = Object.keys(clients[v.name]).length;
45 socket.send(JSON.stringify({code:"counts",counts:countings}));
46 }
47 else
48 {
49 // Send to every client connected on index an update message for counts
50 Object.keys(clients["index"]).forEach( k => {
51 clients["index"][k].send(
52 JSON.stringify({code:"increase",vname:page}), noop);
53 });
54 // Also notify potential opponents:
55 // hit all clients which check if sid corresponds
56 Object.keys(clients[page]).forEach( k => {
57 clients[page][k].send(JSON.stringify({code:"connect",id:sid}), noop);
58 });
59 socket.on("message", objtxt => {
60 let obj = JSON.parse(objtxt);
61 switch (obj.code)
62 {
63 case "newchat":
64 if (!!clients[page][obj.oppid])
65 {
66 clients[page][obj.oppid].send(
67 JSON.stringify({code:"newchat",msg:obj.msg}), noop);
68 }
69 break;
70 case "newmove":
71 if (!!clients[page][obj.oppid])
72 {
73 clients[page][obj.oppid].send(
74 JSON.stringify({code:"newmove",move:obj.move}), noop);
75 }
76 break;
77 case "ping":
78 if (!!clients[page][obj.oppid])
79 socket.send(JSON.stringify({code:"pong",gameId:obj.gameId}));
80 break;
81 case "myname":
82 // Reveal my username to opponent
83 if (!!clients[page][obj.oppid])
84 {
85 clients[page][obj.oppid].send(JSON.stringify({
86 code:"oppname", name:obj.name}));
87 }
88 break;
89 case "lastate":
90 if (!!clients[page][obj.oppid])
91 {
92 const oppId = obj.oppid;
93 obj.oppid = sid; //I'm oppid for my opponent
94 clients[page][oppId].send(JSON.stringify(obj), noop);
95 }
96 break;
97 case "newgame":
98 if (!!games[page])
99 {
100 // Start a new game
101 const oppId = games[page]["id"];
102 const fen = games[page]["fen"];
103 const gameId = games[page]["gameid"];
104 delete games[page];
105 const mycolor = (Math.random() < 0.5 ? 'w' : 'b');
106 socket.send(JSON.stringify(
107 {code:"newgame",fen:fen,oppid:oppId,color:mycolor,gameid:gameId}));
108 if (!!clients[page][oppId])
109 {
110 clients[page][oppId].send(
111 JSON.stringify(
112 {code:"newgame",fen:fen,oppid:sid,color:mycolor=="w"?"b":"w",gameid:gameId}),
113 noop);
114 }
115 }
116 else
117 games[page] = {id:sid, fen:obj.fen, gameid:obj.gameid}; //wait for opponent
118 break;
119 case "cancelnewgame": //if a user cancel his seek
120 delete games[page];
121 break;
122 case "resign":
123 if (!!clients[page][obj.oppid])
124 clients[page][obj.oppid].send(JSON.stringify({code:"resign"}), noop);
125 break;
126 }
127 });
128 }
129 socket.on("close", () => {
130 delete clients[page][sid];
131 // Remove potential pending game
132 if (!!games[page] && games[page]["id"] == sid)
133 delete games[page];
134 if (page != "index")
135 {
136 // Send to every client connected on index an update message for counts
137 Object.keys(clients["index"]).forEach( k => {
138 clients["index"][k].send(
139 JSON.stringify({code:"decrease",vname:page}), noop);
140 });
141 }
142 // Also notify potential opponents:
143 // hit all clients which check if sid corresponds
144 Object.keys(clients[page]).forEach( k => {
145 clients[page][k].send(JSON.stringify({code:"disconnect",id:sid}), noop);
146 });
147 });
148 });
149 });
150 });
151 }