server.js 6.8 KB

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