Step toward a one-page application
[vchess.git] / routes / games.js
1 // TODO: adapt for correspondance play
2
3 var router = require("express").Router();
4 var UserModel = require("../models/User");
5 var GameModel = require('../models/Game');
6 var VariantModel = require('../models/Variant');
7 var ObjectId = require("bson-objectid");
8 var access = require("../utils/access");
9
10 // Notify about a game (start, new move)
11 function tryNotify(uid, gid, vname, subject)
12 {
13 UserModel.getOne("id", uid, (err,user) => {
14 if (!!err && user.notify)
15 {
16 maild.send({
17 from: params.mailFrom,
18 to: user.email,
19 subject: subject,
20 body: params.siteURL + "?v=" + vname + "&g=" + gid
21 }, err => {
22 // TODO: log error somewhere.
23 });
24 }
25 )};
26 }
27
28 // From variant page, start game between player 0 and 1
29 router.post("/games", access.logged, access.ajax, (req,res) => {
30 let variant = JSON.parse(req.body.variant);
31 let players = JSON.parse(req.body.players);
32 if (!players.includes(req.user._id.toString())) //TODO: should also check challenge...
33 return res.json({errmsg: "Cannot start someone else's game"});
34 let fen = req.body.fen;
35 // Randomly shuffle colors white/black
36 if (Math.random() < 0.5)
37 players = [players[1],players[0]];
38 GameModel.create(
39 ObjectId(variant._id), [ObjectId(players[0]),ObjectId(players[1])], fen,
40 (err,game) => {
41 access.checkRequest(res, err, game, "Cannot create game", () => {
42 if (!!req.body.offlineOpp)
43 UserModel.tryNotify(ObjectId(req.body.offlineOpp), game._id, variant.name, "New game");
44 game.movesLength = game.moves.length; //no need for all moves here
45 delete game["moves"];
46 res.json({game: game});
47 });
48 }
49 );
50 });
51
52 // game page
53 router.get("/games", access.ajax, (req,res) => {
54 let gameID = req.query["gid"];
55 GameModel.getById(ObjectId(gameID), (err,game) => {
56 access.checkRequest(res, err, game, "Game not found", () => {
57 res.json({game: game});
58 });
59 });
60 });
61
62 router.put("/games", access.logged, access.ajax, (req,res) => {
63 let gid = ObjectId(req.body.gid);
64 let result = req.body.result;
65 // NOTE: only game-level life update is "gameover"
66 GameModel.gameOver(gid, result, ObjectId(req.user._id), (err,game) => {
67 access.checkRequest(res, err, game, "Cannot find game", () => {
68 res.json({});
69 });
70 });
71 });
72
73 // variant page
74 router.get("/gamesbyvariant", access.logged, access.ajax, (req,res) => {
75 if (req.query["uid"] != req.user._id)
76 return res.json({errmsg: "Not your games"});
77 let uid = ObjectId(req.query["uid"]);
78 let vid = ObjectId(req.query["vid"]);
79 GameModel.getByVariant(uid, vid, (err,gameArray) => {
80 // NOTE: res.json already stringify, no need to do it manually
81 res.json(err || {games: gameArray});
82 });
83 });
84
85 // For index: only moves count + myColor
86 router.get("/gamesbyplayer", access.logged, access.ajax, (req,res) => {
87 if (req.query["uid"] != req.user._id)
88 return res.json({errmsg: "Not your games"});
89 let uid = ObjectId(req.query["uid"]);
90 GameModel.getByPlayer(uid, (err,games) => {
91 res.json(err || {games: games});
92 });
93 });
94
95 // TODO: if newmove fail, takeback in GUI
96 // TODO: check move structure
97 // TODO: for corr games, move should contain an optional "message" field ("corr chat" !)
98 router.post("/moves", access.logged, access.ajax, (req,res) => {
99 let gid = ObjectId(req.body.gid);
100 let fen = req.body.fen;
101 let vname = req.body.vname; //defined only if !!offlineOpp
102 // NOTE: storing the moves encoded lead to double stringify --> error at parsing
103 let move = JSON.parse(req.body.move);
104 GameModel.addMove(gid, move, fen, req._user._id, (err,game) => {
105 access.checkRequest(res, err, game, "Cannot find game", () => {
106 if (!!req.body.offlineOpp)
107 UserModel.tryNotify(ObjectId(req.body.offlineOpp), gid, vname, "New move");
108 res.json({});
109 });
110 });
111 });
112
113 module.exports = router;