server.js 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302
  1. var express = require('express')
  2. , path = require('path')
  3. , crypto = require('crypto')
  4. , http = require('http')
  5. , winston = require('winston')
  6. , fs = require('fs');
  7. var app = express();
  8. app.configure(function() {
  9. app.set('ipaddress', process.env.OPENSHIFT_NODEJS_IP || '127.0.0.1');
  10. app.set('port', process.env.OPENSHIFT_NODEJS_PORT || 3000);
  11. app.set('views', __dirname + '/views');
  12. app.set('view engine', 'jade');
  13. app.use(express.favicon());
  14. app.use(express.logger('dev'));
  15. app.use(express.bodyParser());
  16. app.use(express.methodOverride());
  17. app.use(express.cookieParser('45710b553b5b7293753d03bd3601f70a'));
  18. app.use(express.session());
  19. app.use(app.router);
  20. app.use(express.static(path.join(__dirname, 'public')));
  21. });
  22. app.configure('development', function() {
  23. app.use(express.errorHandler());
  24. });
  25. app.get('/', function(req, res) {
  26. res.render('index');
  27. });
  28. app.get('/about', function(req, res) {
  29. res.render('about');
  30. });
  31. app.get('/play/:token/:time/:increment', function(req, res) {
  32. res.render('play', {
  33. 'token': req.params.token,
  34. 'time': req.params.time,
  35. 'increment': req.params.increment
  36. });
  37. });
  38. app.get('/logs', function(req, res) {
  39. fs.readFile(__dirname + '/logs/games.log', function (err, data) {
  40. if (err) {
  41. res.redirect('/');
  42. }
  43. res.set('Content-Type', 'text/plain');
  44. res.send(data);
  45. });
  46. });
  47. var server = http.createServer(app).listen(app.get('port'), app.get('ipaddress'), function() {
  48. console.log("Express server listening on port " + app.get('port'));
  49. });
  50. var games = {};
  51. var timer;
  52. /**
  53. * Winston logger
  54. */
  55. winston.add(winston.transports.File, {
  56. filename: __dirname + '/logs/games.log',
  57. handleExceptions: true,
  58. exitOnError: false,
  59. json: false
  60. });
  61. winston.remove(winston.transports.Console);
  62. winston.handleExceptions(new winston.transports.Console());
  63. winston.exitOnError = false;
  64. /**
  65. * Sockets
  66. */
  67. var io = require('socket.io').listen(server, {log: false});
  68. if (process.env.OPENSHIFT_NODEJS_IP) {
  69. io.configure(function(){
  70. io.set('transports', ['websocket']);
  71. });
  72. }
  73. io.sockets.on('connection', function (socket) {
  74. socket.on('start', function (data) {
  75. var token;
  76. var b = new Buffer(Math.random() + new Date().getTime() + socket.id);
  77. token = b.toString('base64').slice(12, 32);
  78. games[token] = {
  79. 'creator': socket,
  80. 'players': [],
  81. 'interval': null
  82. };
  83. socket.emit('created', {
  84. 'token': token
  85. });
  86. });
  87. socket.on('join', function (data) {
  88. var game, color, time = data.time;
  89. if (!(data.token in games)) {
  90. return;
  91. }
  92. game = games[data.token];
  93. if (game.players.length >= 2) {
  94. socket.emit('full');
  95. return;
  96. } else if (game.players.length === 1) {
  97. if (game.players[0].color === 'black') {
  98. color = 'white';
  99. } else {
  100. color = 'black';
  101. }
  102. winston.log('info', 'Number of currently running games', { '#': Object.keys(games).length });
  103. } else {
  104. var colors = ['black', 'white'];
  105. color = colors[Math.floor(Math.random() * 2)];
  106. }
  107. //join room
  108. socket.join(data.token);
  109. games[data.token].players.push({
  110. 'id': socket.id,
  111. 'socket': socket,
  112. 'color': color,
  113. 'time': data.time - data.increment + 1,
  114. 'increment': data.increment
  115. });
  116. game.creator.emit('ready', {});
  117. socket.emit('joined', {
  118. 'color': color
  119. });
  120. });
  121. socket.on('timer-white', function (data) {
  122. runTimer('white', data.token, socket);
  123. });
  124. socket.on('timer-black', function (data) {
  125. runTimer('black', data.token, socket);
  126. });
  127. socket.on('timer-clear-interval', function (data) {
  128. if (data.token in games) {
  129. clearInterval(games[data.token].interval);
  130. }
  131. });
  132. socket.on('new-move', function (data) {
  133. var receiver, game;
  134. if (!(data.token in games)) {
  135. return;
  136. }
  137. game = games[data.token];
  138. if (game.players[0].id == socket.id) {
  139. receiver = game.players[1].socket;
  140. } else if (game.players[1].id == socket.id) {
  141. receiver = game.players[0].socket;
  142. } else {
  143. return;
  144. }
  145. receiver.emit('move', {
  146. 'move': data.move,
  147. });
  148. });
  149. socket.on('resign', function (data) {
  150. if (data.token in games) {
  151. clearInterval(games[data.token].interval);
  152. io.sockets.in(data.token).emit('player-resigned', {
  153. 'color': data.color
  154. });
  155. }
  156. });
  157. socket.on('rematch-offer', function (data) {
  158. var opponent;
  159. if (data.token in games) {
  160. opponent = getOpponent(data.token, socket);
  161. if (opponent) {
  162. opponent.socket.emit('rematch-offered');
  163. }
  164. }
  165. });
  166. socket.on('rematch-decline', function (data) {
  167. var opponent;
  168. if (data.token in games) {
  169. opponent = getOpponent(data.token, socket);
  170. if (opponent) {
  171. opponent.socket.emit('rematch-declined');
  172. }
  173. }
  174. });
  175. socket.on('rematch-confirm', function (data) {
  176. var opponent;
  177. if (data.token in games) {
  178. for(var j in games[data.token].players) {
  179. games[data.token].players[j].time = data.time - data.increment + 1;
  180. games[data.token].players[j].increment = data.increment;
  181. games[data.token].players[j].color = games[data.token].players[j].color === 'black' ? 'white' : 'black';
  182. }
  183. opponent = getOpponent(data.token, socket);
  184. if (opponent) {
  185. io.sockets.in(data.token).emit('rematch-confirmed');
  186. }
  187. }
  188. })
  189. socket.on('disconnect', function (data) {
  190. var player, opponent, game;
  191. for (var token in games) {
  192. game = games[token];
  193. for (var j in game.players) {
  194. player = game.players[j];
  195. if (player.socket === socket) {
  196. opponent = game.players[Math.abs(j - 1)];
  197. opponent.socket.emit('opponent-disconnected');
  198. clearInterval(games[token].interval);
  199. delete games[token];
  200. }
  201. }
  202. }
  203. });
  204. socket.on('send-message', function (data) {
  205. if (data.token in games) {
  206. var opponent = getOpponent(data.token, socket);
  207. opponent.socket.emit('receive-message', data);
  208. }
  209. });
  210. });
  211. function runTimer(color, token, socket) {
  212. var player, time_left, game = games[token];
  213. if (!game) return;
  214. for (var i in game.players) {
  215. player = game.players[i];
  216. if (player.socket === socket && player.color === color) {
  217. clearInterval(games[token].interval);
  218. games[token].players[i].time += games[token].players[i].increment;
  219. return games[token].interval = setInterval(function() {
  220. games[token].players[i].time -= 1;
  221. time_left = games[token].players[i].time;
  222. if (time_left >= 0) {
  223. io.sockets.in(token).emit('countdown', {
  224. 'time': time_left,
  225. 'color': color
  226. });
  227. } else {
  228. io.sockets.in(token).emit('countdown-gameover', {
  229. 'color': color
  230. });
  231. clearInterval(games[token].interval);
  232. }
  233. }, 1000);
  234. }
  235. }
  236. }
  237. function getOpponent(token, socket) {
  238. var player, game = games[token];
  239. for (var j in game.players) {
  240. player = game.players[j];
  241. if (player.socket === socket) {
  242. var opponent = game.players[Math.abs(j - 1)];
  243. return opponent;
  244. }
  245. }
  246. }