diff --git a/config/socket.js b/config/socket.js index 0d582ce..befbd72 100644 --- a/config/socket.js +++ b/config/socket.js @@ -1,6 +1,14 @@ module.exports = function (server) { var io = require('socket.io').listen(server); + /* + socket support for chat + */ + io.on('connection', function(socket){ + socket.on('chat message', function(msg){ + io.emit('chat message', msg); + }); + }); var chess = require('chess.js'); diff --git a/public/javascripts/chess.min.update.js b/public/javascripts/chess.min.update.js new file mode 100644 index 0000000..ffb71d8 --- /dev/null +++ b/public/javascripts/chess.min.update.js @@ -0,0 +1,10 @@ +/** + * Created by kiran on 12/6/15. + */ +"use strict";/* @license + * Copyright (c) 2015, Jeff Hlywa (jhlywa@gmail.com) + * Released under the BSD license + * https://github.com/jhlywa/chess.js/blob/master/LICENSE + */ +var Chess=function(r){function e(){fr=new Array(128),ur={w:Q,b:Q},ar=K,lr={w:0,b:0},sr=Q,pr=0,cr=1,vr=[],gr={},u(i())}function n(){t(F)}function t(r){var n=r.split(/\s+/),t=n[0],f=0;if(!o(r).valid)return!1;e();for(var a=0;as?K:q;l({type:s.toLowerCase(),color:p},w(f)),f++}}return ar=n[1],n[2].indexOf("K")>-1&&(lr.w|=Y.KSIDE_CASTLE),n[2].indexOf("Q")>-1&&(lr.w|=Y.QSIDE_CASTLE),n[2].indexOf("k")>-1&&(lr.b|=Y.KSIDE_CASTLE),n[2].indexOf("q")>-1&&(lr.b|=Y.QSIDE_CASTLE),sr="-"===n[3]?Q:or[n[3]],pr=parseInt(n[4],10),cr=parseInt(n[5],10),u(i()),!0}function o(r){var e={0:"No errors.",1:"FEN string must contain six space-delimited fields.",2:"6th field (move number) must be a positive integer.",3:"5th field (half move counter) must be a non-negative integer.",4:"4th field (en-passant square) is invalid.",5:"3rd field (castling availability) is invalid.",6:"2nd field (side to move) is invalid.",7:"1st field (piece positions) does not contain 8 '/'-delimited rows.",8:"1st field (piece positions) is invalid [consecutive numbers].",9:"1st field (piece positions) is invalid [invalid piece].",10:"1st field (piece positions) is invalid [row too large]."},n=r.split(/\s+/);if(6!==n.length)return{valid:!1,error_number:1,error:e[1]};if(isNaN(n[5])||parseInt(n[5],10)<=0)return{valid:!1,error_number:2,error:e[2]};if(isNaN(n[4])||parseInt(n[4],10)<0)return{valid:!1,error_number:3,error:e[3]};if(!/^(-|[abcdefgh][36])$/.test(n[3]))return{valid:!1,error_number:4,error:e[4]};if(!/^(KQ?k?q?|Qk?q?|kq?|q|-)$/.test(n[2]))return{valid:!1,error_number:5,error:e[5]};if(!/^(w|b)$/.test(n[1]))return{valid:!1,error_number:6,error:e[6]};var t=n[0].split("/");if(8!==t.length)return{valid:!1,error_number:7,error:e[7]};for(var o=0;o0&&(e+=r,r=0);var t=fr[n].color,o=fr[n].type;e+=t===K?o.toUpperCase():o.toLowerCase()}n+1&136&&(r>0&&(e+=r),n!==or.h1&&(e+="/"),r=0,n+=8)}var i="";lr[K]&Y.KSIDE_CASTLE&&(i+="K"),lr[K]&Y.QSIDE_CASTLE&&(i+="Q"),lr[q]&Y.KSIDE_CASTLE&&(i+="k"),lr[q]&Y.QSIDE_CASTLE&&(i+="q"),i=i||"-";var f=sr===Q?"-":w(sr);return[e,ar,i,f,pr,cr].join(" ")}function f(r){for(var e=0;e0||(r!==F?(gr.SetUp="1",gr.FEN=r):(delete gr.SetUp,delete gr.FEN))}function a(r){var e=fr[or[r]];return e?{type:e.type,color:e.color}:null}function l(r,e){if(!("type"in r&&"color"in r))return!1;if(-1===G.indexOf(r.type.toLowerCase()))return!1;if(!(e in or))return!1;var n=or[e];return r.type==M&&ur[r.color]!=Q&&ur[r.color]!=n?!1:(fr[n]={type:r.type,color:r.color},r.type===M&&(ur[r.color]=n),u(i()),!0)}function s(r){var e=a(r);return fr[or[r]]=null,e&&e.type===M&&(ur[e.color]=Q),u(i()),e}function p(r,e,n,t,o){var i={color:ar,from:e,to:n,flags:t,piece:r[e].type};return o&&(i.flags|=Y.PROMOTION,i.promotion=o),r[n]?i.captured=r[n].type:t&Y.EP_CAPTURE&&(i.captured=U),i}function c(r){function e(r,e,n,t,o){if(r[n].type!==U||I(t)!==tr&&I(t)!==rr)e.push(p(r,n,t,o));else for(var i=[B,$,j,x],f=0,u=i.length;u>f;f++)e.push(p(r,n,t,o,i[f]))}var n=[],t=ar,o=L(t),i={b:nr,w:er},f=or.a8,u=or.h1,a=!1,l="undefined"!=typeof r&&"legal"in r?r.legal:!0;if("undefined"!=typeof r&&"square"in r){if(!(r.square in or))return[];f=u=or[r.square],a=!0}for(var s=f;u>=s;s++)if(136&s)s+=7;else{var c=fr[s];if(null!=c&&c.color===t)if(c.type===U){var v=s+H[t][0];if(null==fr[v]){e(fr,n,s,v,Y.NORMAL);var v=s+H[t][1];i[t]===I(s)&&null==fr[v]&&e(fr,n,s,v,Y.BIG_PAWN)}for(E=2;4>E;E++){var v=s+H[t][E];136&v||(null!=fr[v]&&fr[v].color===o?e(fr,n,s,v,Y.CAPTURE):v===sr&&e(fr,n,s,sr,Y.EP_CAPTURE))}}else for(var E=0,d=Z[c.type].length;d>E;E++)for(var b=Z[c.type][E],v=s;;){if(v+=b,136&v)break;if(null!=fr[v]){if(fr[v].color===t)break;e(fr,n,s,v,Y.CAPTURE);break}if(e(fr,n,s,v,Y.NORMAL),"n"===c.type||"k"===c.type)break}}if(!a||u===ur[t]){if(lr[t]&Y.KSIDE_CASTLE){var _=ur[t],A=_+2;null!=fr[_+1]||null!=fr[A]||g(o,ur[t])||g(o,_+1)||g(o,A)||e(fr,n,ur[t],A,Y.KSIDE_CASTLE)}if(lr[t]&Y.QSIDE_CASTLE){var _=ur[t],A=_-2;null!=fr[_-1]||null!=fr[_-2]||null!=fr[_-3]||g(o,ur[t])||g(o,_-1)||g(o,A)||e(fr,n,ur[t],A,Y.QSIDE_CASTLE)}}if(!l)return n;for(var S=[],s=0,d=n.length;d>s;s++)y(n[s]),h(t)||S.push(n[s]),m();return S}function v(r){var e="";if(r.flags&Y.KSIDE_CASTLE)e="O-O";else if(r.flags&Y.QSIDE_CASTLE)e="O-O-O";else{var n=C(r);r.piece!==U&&(e+=r.piece.toUpperCase()+n),r.flags&(Y.CAPTURE|Y.EP_CAPTURE)&&(r.piece===U&&(e+=w(r.from)[0]),e+="x"),e+=w(r.to),r.flags&Y.PROMOTION&&(e+="="+r.promotion.toUpperCase())}return y(r),E()&&(e+=d()?"#":"+"),m(),e}function g(r,e){for(var n=or.a8;n<=or.h1;n++)if(136&n)n+=7;else if(null!=fr[n]&&fr[n].color===r){var t=fr[n],o=n-e,i=o+119;if(z[i]&1<0){if(t.color===K)return!0}else if(t.color===q)return!0;continue}if("n"===t.type||"k"===t.type)return!0;for(var f=J[i],u=n+f,a=!1;u!==e;){if(null!=fr[u]){a=!0;break}u+=f}if(!a)return!0}}return!1}function h(r){return g(L(r),ur[r])}function E(){return h(ar)}function d(){return E()&&0===c().length}function b(){return!E()&&0===c().length}function _(){for(var r={},e=[],n=0,t=0,o=or.a8;o<=or.h1;o++)if(t=(t+1)%2,136&o)o+=7;else{var i=fr[o];i&&(r[i.type]=i.type in r?r[i.type]+1:1,i.type===j&&e.push(t),n++)}if(2===n)return!0;if(3===n&&(1===r[j]||1===r[x]))return!0;if(n===r[j]+2){for(var f=0,u=e.length,o=0;u>o;o++)f+=e[o];if(0===f||f===u)return!0}return!1}function A(){for(var r=[],e={},n=!1;;){var t=m();if(!t)break;r.push(t)}for(;;){var o=i().split(" ").slice(0,4).join(" ");if(e[o]=o in e?e[o]+1:1,e[o]>=3&&(n=!0),!r.length)break;y(r.pop())}return n}function S(r){vr.push({move:r,kings:{b:ur.b,w:ur.w},turn:ar,castling:{b:lr.b,w:lr.w},ep_square:sr,half_moves:pr,move_number:cr})}function y(r){var e=ar,n=L(e);if(S(r),fr[r.to]=fr[r.from],fr[r.from]=null,r.flags&Y.EP_CAPTURE&&(ar===q?fr[r.to-16]=null:fr[r.to+16]=null),r.flags&Y.PROMOTION&&(fr[r.to]={type:r.promotion,color:e}),fr[r.to].type===M){if(ur[fr[r.to].color]=r.to,r.flags&Y.KSIDE_CASTLE){var t=r.to-1,o=r.to+1;fr[t]=fr[o],fr[o]=null}else if(r.flags&Y.QSIDE_CASTLE){var t=r.to+1,o=r.to-2;fr[t]=fr[o],fr[o]=null}lr[e]=""}if(lr[e])for(var i=0,f=ir[e].length;f>i;i++)if(r.from===ir[e][i].square&&lr[e]&ir[e][i].flag){lr[e]^=ir[e][i].flag;break}if(lr[n])for(var i=0,f=ir[n].length;f>i;i++)if(r.to===ir[n][i].square&&lr[n]&ir[n][i].flag){lr[n]^=ir[n][i].flag;break}sr=r.flags&Y.BIG_PAWN?"b"===ar?r.to-16:r.to+16:Q,r.piece===U?pr=0:r.flags&(Y.CAPTURE|Y.EP_CAPTURE)?pr=0:pr++,ar===q&&cr++,ar=L(ar)}function m(){var r=vr.pop();if(null==r)return null;var e=r.move;ur=r.kings,ar=r.turn,lr=r.castling,sr=r.ep_square,pr=r.half_moves,cr=r.move_number;var n=ar,t=L(ar);if(fr[e.from]=fr[e.to],fr[e.from].type=e.piece,fr[e.to]=null,e.flags&Y.CAPTURE)fr[e.to]={type:e.captured,color:t};else if(e.flags&Y.EP_CAPTURE){var o;o=n===q?e.to-16:e.to+16,fr[o]={type:U,color:t}}if(e.flags&(Y.KSIDE_CASTLE|Y.QSIDE_CASTLE)){var i,f;e.flags&Y.KSIDE_CASTLE?(i=e.to+1,f=e.to-1):e.flags&Y.QSIDE_CASTLE&&(i=e.to-2,f=e.to+1),fr[i]=fr[f],fr[f]=null}return e}function C(r){for(var e=c(),n=r.from,t=r.to,o=r.piece,i=0,f=0,u=0,a=0,l=e.length;l>a;a++){var s=e[a].from,p=e[a].to,v=e[a].piece;o===v&&n!==s&&t===p&&(i++,I(n)===I(s)&&f++,P(n)===P(s)&&u++)}return i>0?f>0&&u>0?w(n):w(n).charAt(u>0?1:0):""}function T(){for(var r=" +------------------------+\n",e=or.a8;e<=or.h1;e++){if(0===P(e)&&(r+=" "+"87654321"[I(e)]+" |"),null==fr[e])r+=" . ";else{var n=fr[e].type,t=fr[e].color,o=t===K?n.toUpperCase():n.toLowerCase();r+=" "+o+" "}e+1&136&&(r+="|\n",e+=8)}return r+=" +------------------------+\n",r+=" a b c d e f g h\n"}function I(r){return r>>4}function P(r){return 15&r}function w(r){var e=P(r),n=I(r);return"abcdefgh".substring(e,e+1)+"87654321".substring(n,n+1)}function L(r){return r===K?q:K}function R(r){return-1!=="0123456789".indexOf(r)}function O(r){var e=N(r);e.san=v(e),e.to=w(e.to),e.from=w(e.from);var n="";for(var t in Y)Y[t]&e.flags&&(n+=X[t]);return e.flags=n,e}function N(r){var e=r instanceof Array?[]:{};for(var n in r)"object"==typeof n?e[n]=N(r[n]):e[n]=r[n];return e}function k(r){return r.replace(/^\s+|\s+$/g,"")}function D(r){for(var e=c({legal:!1}),n=0,t=ar,o=0,i=e.length;i>o;o++){if(y(e[o]),!h(t))if(r-1>0){var f=D(r-1);n+=f}else n++;m()}return n}var q="b",K="w",Q=-1,U="p",x="n",j="b",$="r",B="q",M="k",G="pnbrqkPNBRQK",F="rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1",W=["1-0","0-1","1/2-1/2","*"],H={b:[16,32,17,15],w:[-16,-32,-17,-15]},Z={n:[-18,-33,-31,-14,18,33,31,14],b:[-17,-15,17,15],r:[-16,1,16,-1],q:[-17,-16,-15,1,17,16,15,-1],k:[-17,-16,-15,1,17,16,15,-1]},z=[20,0,0,0,0,0,0,24,0,0,0,0,0,0,20,0,0,20,0,0,0,0,0,24,0,0,0,0,0,20,0,0,0,0,20,0,0,0,0,24,0,0,0,0,20,0,0,0,0,0,0,20,0,0,0,24,0,0,0,20,0,0,0,0,0,0,0,0,20,0,0,24,0,0,20,0,0,0,0,0,0,0,0,0,0,20,2,24,2,20,0,0,0,0,0,0,0,0,0,0,0,2,53,56,53,2,0,0,0,0,0,0,24,24,24,24,24,24,56,0,56,24,24,24,24,24,24,0,0,0,0,0,0,2,53,56,53,2,0,0,0,0,0,0,0,0,0,0,0,20,2,24,2,20,0,0,0,0,0,0,0,0,0,0,20,0,0,24,0,0,20,0,0,0,0,0,0,0,0,20,0,0,0,24,0,0,0,20,0,0,0,0,0,0,20,0,0,0,0,24,0,0,0,0,20,0,0,0,0,20,0,0,0,0,0,24,0,0,0,0,0,20,0,0,20,0,0,0,0,0,0,24,0,0,0,0,0,0,20],J=[17,0,0,0,0,0,0,16,0,0,0,0,0,0,15,0,0,17,0,0,0,0,0,16,0,0,0,0,0,15,0,0,0,0,17,0,0,0,0,16,0,0,0,0,15,0,0,0,0,0,0,17,0,0,0,16,0,0,0,15,0,0,0,0,0,0,0,0,17,0,0,16,0,0,15,0,0,0,0,0,0,0,0,0,0,17,0,16,0,15,0,0,0,0,0,0,0,0,0,0,0,0,17,16,15,0,0,0,0,0,0,0,1,1,1,1,1,1,1,0,-1,-1,-1,-1,-1,-1,-1,0,0,0,0,0,0,0,-15,-16,-17,0,0,0,0,0,0,0,0,0,0,0,0,-15,0,-16,0,-17,0,0,0,0,0,0,0,0,0,0,-15,0,0,-16,0,0,-17,0,0,0,0,0,0,0,0,-15,0,0,0,-16,0,0,0,-17,0,0,0,0,0,0,-15,0,0,0,0,-16,0,0,0,0,-17,0,0,0,0,-15,0,0,0,0,0,-16,0,0,0,0,0,-17,0,0,-15,0,0,0,0,0,0,-16,0,0,0,0,0,0,-17],V={p:0,n:1,b:2,r:3,q:4,k:5},X={NORMAL:"n",CAPTURE:"c",BIG_PAWN:"b",EP_CAPTURE:"e",PROMOTION:"p",KSIDE_CASTLE:"k",QSIDE_CASTLE:"q"},Y={NORMAL:1,CAPTURE:2,BIG_PAWN:4,EP_CAPTURE:8,PROMOTION:16,KSIDE_CASTLE:32,QSIDE_CASTLE:64},rr=7,er=6,nr=1,tr=0,or={a8:0,b8:1,c8:2,d8:3,e8:4,f8:5,g8:6,h8:7,a7:16,b7:17,c7:18,d7:19,e7:20,f7:21,g7:22,h7:23,a6:32,b6:33,c6:34,d6:35,e6:36,f6:37,g6:38,h6:39,a5:48,b5:49,c5:50,d5:51,e5:52,f5:53,g5:54,h5:55,a4:64,b4:65,c4:66,d4:67,e4:68,f4:69,g4:70,h4:71,a3:80,b3:81,c3:82,d3:83,e3:84,f3:85,g3:86,h3:87,a2:96,b2:97,c2:98,d2:99,e2:100,f2:101,g2:102,h2:103,a1:112,b1:113,c1:114,d1:115,e1:116,f1:117,g1:118,h1:119},ir={w:[{square:or.a1,flag:Y.QSIDE_CASTLE},{square:or.h1,flag:Y.KSIDE_CASTLE}],b:[{square:or.a8,flag:Y.QSIDE_CASTLE},{square:or.h8,flag:Y.KSIDE_CASTLE}]},fr=new Array(128),ur={w:Q,b:Q},ar=K,lr={w:0,b:0},sr=Q,pr=0,cr=1,vr=[],gr={};return t("undefined"==typeof r?F:r),{WHITE:K,BLACK:q,PAWN:U,KNIGHT:x,BISHOP:j,ROOK:$,QUEEN:B,KING:M,SQUARES:function(){for(var r=[],e=or.a8;e<=or.h1;e++)136&e?e+=7:r.push(w(e));return r}(),FLAGS:X,load:function(r){return t(r)},reset:function(){return n()},moves:function(r){for(var e=c(r),n=[],t=0,o=e.length;o>t;t++)n.push("undefined"!=typeof r&&"verbose"in r&&r.verbose?O(e[t]):v(e[t]));return n},in_check:function(){return E()},in_checkmate:function(){return d()},in_stalemate:function(){return b()},in_draw:function(){return pr>=100||b()||_()||A()},insufficient_material:function(){return _()},in_threefold_repetition:function(){return A()},game_over:function(){return pr>=100||d()||b()||_()||A()},validate_fen:function(r){return o(r)},fen:function(){return i()},pgn:function(r){var e="object"==typeof r&&"string"==typeof r.newline_char?r.newline_char:"\n",n="object"==typeof r&&"number"==typeof r.max_width?r.max_width:0,t=[],o=!1;for(var i in gr)t.push("["+i+' "'+gr[i]+'"]'+e),o=!0;o&&vr.length&&t.push(e);for(var f=[];vr.length>0;)f.push(m());for(var u=[],a="",l=1;f.length>0;){var s=f.pop();1===l&&"b"===s.color?(a="1. ...",l++):"w"===s.color&&(a.length&&u.push(a),a=l+".",l++),a=a+" "+v(s),y(s)}if(a.length&&u.push(a),"undefined"!=typeof gr.Result&&u.push(gr.Result),0===n)return t.join("")+u.join(" ");for(var p=0,i=0;in&&0!==i?(" "===t[t.length-1]&&t.pop(),t.push(e),p=0):0!==i&&(t.push(" "),p++),t.push(u[i]),p+=u[i].length;return t.join("")},load_pgn:function(r,e){function o(r){return r.replace(/\\/g,"\\")}function i(r){for(var e=r.replace(/[+#?!=]/,""),n=c(),t=0,o=n.length;o>t;t++)if(e==v(n[t]).replace(/[+#?!=]/,""))return n[t];return null}function u(r){return i(k(r))}function a(r){var e=!1;for(var n in r)e=!0;return e}function l(r,e){for(var n="object"==typeof e&&"string"==typeof e.newline_char?e.newline_char:"\r?\n",t={},i=r.split(new RegExp(o(n))),f="",u="",a=0;a0&&(t[f]=u);return t}var s="object"==typeof e&&"string"==typeof e.newline_char?e.newline_char:"\r?\n",p=new RegExp("^(\\[(.|"+o(s)+")*\\])("+o(s)+")*1.("+o(s)+"|.)*$","g"),g=r.replace(p,"$1");"["!==g[0]&&(g=""),n();var h=l(g,e);for(var E in h)f([E,h[E]]);if("1"===h.SetUp&&!("FEN"in h&&t(h.FEN)))return!1;var d=r.replace(g,"").replace(new RegExp(o(s),"g")," ");d=d.replace(/(\{[^}]+\})+?/g,""),d=d.replace(/\d+\./g,""),d=d.replace(/\.\.\./g,"");var b=k(d).split(new RegExp(/\s+/));b=b.join(",").replace(/,,+/g,",").split(",");for(var _="",A=0;A-1)a(gr)&&"undefined"==typeof gr.Result&&f(["Result",_]);else{if(_=u(_),null==_)return!1;y(_)}return!0},header:function(){return f(arguments)},ascii:function(){return T()},turn:function(){return ar},move:function(r){var e=null,n=c();if("string"==typeof r){for(var t=r.replace(/[+#?!=]/,""),o=0,i=n.length;i>o;o++)if(t===v(n[o]).replace(/[+#?!=]/,"")){e=n[o];break}}else if("object"==typeof r)for(var o=0,i=n.length;i>o;o++)if(!(r.from!==w(n[o].from)||r.to!==w(n[o].to)||"promotion"in n[o]&&r.promotion!==n[o].promotion)){e=n[o];break}if(!e)return null;var f=O(e);return y(e),f},undo:function(){var r=m();return r?O(r):null},clear:function(){return e()},put:function(r,e){return l(r,e)},get:function(r){return a(r)},remove:function(r){return s(r)},perft:function(r){return D(r)},square_color:function(r){if(r in or){var e=or[r];return(I(e)+P(e))%2===0?"light":"dark"}return null},history:function(r){for(var e=[],n=[],t=("undefined"!=typeof r&&"verbose"in r&&r.verbose);vr.length>0;)e.push(m());for(;e.length>0;){var o=e.pop();n.push(t?O(o):v(o)),y(o)}return n}}};"undefined"!=typeof exports&&(exports.Chess=Chess),"undefined"!=typeof define&&define(function(){return Chess}); + diff --git a/public/javascripts/chesshub.js b/public/javascripts/chesshub.js index 4167ea6..620a918 100644 --- a/public/javascripts/chesshub.js +++ b/public/javascripts/chesshub.js @@ -4,22 +4,62 @@ $( document ).ready(function() { * When the user is logged in, it's name is loaded in the "data" attribute of the "#loggedUser" element. * This name is then passed to the socket connection handshake query */ + //alert("hi"); var username; - var time_out=300;//5 minutes in seconds + var time_out;//5 minutes in seconds + var domain_url="http://192.168.12.77:3000";// The url where the game is to be run (dont include '/' at the end) + var enable_time_out=false;// play with timeout ? (true/false) + var enable_time_add=false;//add 10 sec to every valid move if enabled( Blitz mode rules) if($("#loggedUser").length) { username = $("#loggedUser").data("user"); } else { username = "Anonymous"; } + if(true)//$("#timeoutEnable").data('timeout')) + { + + enable_time_out=$("#timeoutEnable").data('timeout'); + time_out=$("#timeoutEnable").data('timeouttime1'); + } + + + + $('#game_timeout_enabler').checked=false; + $("#game_timeout_time").hide(); + $('#game_timeout_enabler').change( + function(){ + if ($(this).is(':checked')) { + enable_time_out=true; + $("#game_timeout_time").show(); + } + else{ + enable_time_out=false; + $("#game_timeout_time").hide(); + } + }); + + /* TIME OUT settings Bar */ + /* + if(document.getElementById('game_timeout_enabler').checked) + { + alert("tick"); + enable_time_out=$("#gameSettings").data("timeout"); + //time_out=$("timeoutTime").data('timeoutTime'); + $("#game_timeout_time").toggle(); + } + if(!document.getElementById('game_timeout_enabler').checked) { + alert("not tick"); + $("#game_timeout_time").toggle(); + }*/ // socket used for real time games - var socket = io('http://localhost:3000', { query: 'user=' + username }); + var socket = io(domain_url, { query: 'user=' + username }); //socket used to broadcast live games on tv page - var tvSocket = io('http://localhost:3000/tv'); + var tvSocket = io(domain_url+'/tv'); // socket used to broadcast events to monitoring page - var monitorSocket = io('http://localhost:3000/monitor'); + var monitorSocket = io(domain_url+'/monitor'); // Puzzle of the day: initialize a chess board with puzzle data if ($("#pod").length) { @@ -120,6 +160,47 @@ $( document ).ready(function() { }); } + /* + * Show chats to be displayed + * Chats are never stored . + * So , chats are lost if any page is reloaded . + * Chat pops up whenver there's a new message + * TODO :Store chat conversations . + */ + var socket1 = io(); + $('.chat-form').submit(function(){ + + if( $('#m').val().length>0) + { + socket1.emit('chat message', username+' : '+$('#m').val()); + } + $('#m').val(''); + return false; + }); + socket.on('chat message', function(msg){ + //new chat message ..pop the chats + $(".chat").show(); + document.getElementById('chat-active').className='active'; + $('#messages').append($('
  • ').text(msg)); + }); + + /* + * show or hide the chats window + */ + showhideChat= function () { + $(".chat").toggle(); + if($(".chat").is(":visible") == true)//if chat is visible then make Chats menu active + { + document.getElementById('chat-active').className='active'; + } + else + document.getElementById('chat-active').className='inactive'; + + }; + //initially hide chat + $(".chat").hide(); + document.getElementById('chat-active').className='inactive';//make chat inactive + /* * Game page */ @@ -134,18 +215,55 @@ $( document ).ready(function() { var side = $("#board").data('side'); var opponentSide = side === "black" ? "white" : "black"; - /* + /* * Timer : displays time taken by each player while making moves + * Displays time remaining for each player */ + var black=false; + var white=false; var timer=function(time_set) { - if(true) + /* + added condtion to checkout for gameover + */ + var possibleMoves = game.moves(); + //alert(game.game_over()); + // if the game is over, reload a new game + if (game.in_draw() === true ) { + $('#gameResult').html('Game is a draw !'); + $('#gameResultPopup').modal({ + keyboard: false, + backdrop: 'static' + }); + } + if(game.in_stalemate()==true){ + $('#gameResult').html('Stalemate !'); + $('#gameResultPopup').modal({ + keyboard: false, + backdrop: 'static' + }); + } + if(game.turn().toString()=='w') { - if(game.turn().toString()=='w') + if(game.game_over() === true || possibleMoves.length===0) { - time_set[0]+=1; - if(time_set[0]>time_out) - { + $('#gameResult').html('Game Over.Black Won !'); + $('#gameResultPopup').modal({ + keyboard: false, + backdrop: 'static' + }); + } + if(enable_time_out) + { + time_set[0] -= 1; + if (black) { + if (enable_time_add)//if enabled will add 10 sec to each valid move + time_set[1] += 10; + black = false; + + } + white = true; + if (time_set[0] <= 0) { //handle time out $('#gameResult').html('TimeOut! Black Won !'); $('#gameResultPopup').modal({ @@ -154,13 +272,28 @@ $( document ).ready(function() { }); clearInterval(timer_interval); } - $("#timew").html(("00" + Math.floor(time_set[0]/60)).slice (-2)+":"+("00" + time_set[0]%60).slice (-2)); } - if(game.turn().toString()=='b') + } + if(game.turn().toString()=='b') + { + if(game.game_over() === true || possibleMoves.length===0) + { + $('#gameResult').html('Game Over. White Won !'); + $('#gameResultPopup').modal({ + keyboard: false, + backdrop: 'static' + }); + } + if(enable_time_out) { - time_set[1]+=1; - if(time_set[1]>time_out) - { + time_set[1] -= 1; + if (white) { + if (enable_time_add)//if enabled will add 10 sec to each valid move + time_set[0] = time_set[0] + 10; + white = false; + } + black = true; + if (time_set[1] <= 0) { //handle time out $('#gameResult').html('TimeOut! White Won !'); $('#gameResultPopup').modal({ @@ -169,9 +302,13 @@ $( document ).ready(function() { }); clearInterval(timer_interval); } - $("#timeb").html(("00" + Math.floor(time_set[1]/60)).slice (-2)+":"+("00" + time_set[1]%60).slice (-2)); } } + if(enable_time_out) + { + $("#timeb").html(("00" + Math.floor(time_set[1] / 60)).slice(-2) + ":" + ("00" + time_set[1] % 60).slice(-2)); + $("#timew").html(("00" + Math.floor(time_set[0] / 60)).slice(-2) + ":" + ("00" + time_set[0] % 60).slice(-2)); + } return time_set; }; @@ -203,6 +340,8 @@ $( document ).ready(function() { pgnEl.html(game.pgn()); $('.turn').removeClass("fa fa-spinner"); $('#turn-' + game.turn()).addClass("fa fa-spinner"); + + socket.emit('new-move', { token: token, source: source, @@ -217,6 +356,7 @@ $( document ).ready(function() { // for castling, en passant, pawn promotion var onSnapEnd = function() { board.position(game.fen()); + }; /* @@ -240,14 +380,16 @@ $( document ).ready(function() { */ socket.emit('join', { 'token': token, - 'side': side + 'side': side, + + }); /* * When a new game is created, the game creator should wait for an opponent to join the game */ socket.on('wait', function () { - var url = "http:/localhost:3000/game/" + token + "/" + opponentSide; + var url = domain_url+"/game/" + token + "/" + opponentSide+'/'+time_out; $('#gameUrl').html(url); $('#gameUrlPopup').modal({ // show modal popup to wait for opponent keyboard: false, @@ -259,8 +401,11 @@ $( document ).ready(function() { * A second player has joined the game => the game can start */ socket.on('ready', function (data) { + //intialize the timer var time_sets=[0,0]; + time_sets[0]=time_out; + time_sets[1]=time_out; timer_interval=setInterval(function(){ time_sets=timer(time_sets)}, 1000);//repeat every second $('#turn-w').addClass("fa fa-spinner"); $('#player-white').html(data.white); @@ -272,7 +417,8 @@ $( document ).ready(function() { * A new move has been made by a player => update the UI */ socket.on('new-move', function(data){ - game.move({ from: data.source, to: data.target }); + + game.move({ from: data.source, to: data.target ,promotion: 'q'}); // NOTE: always promote to a queen for example simplicity}); board.position( game.fen() ); pgnEl.html(game.pgn()); $('.turn').removeClass("fa fa-spinner"); @@ -409,7 +555,7 @@ $( document ).ready(function() { $( "#searchGameFormSubmit" ).on("click", function( event ) { $.ajax({ type: "POST", - url: "http://localhost:3000/search", + url: domain_url+"/search", data: { white: $( "input[name$='white']" ).val(), black: $( "input[name$='black']" ).val(), diff --git a/public/javascripts/chesshub.js~ b/public/javascripts/chesshub.js~ new file mode 100644 index 0000000..e31a47d --- /dev/null +++ b/public/javascripts/chesshub.js~ @@ -0,0 +1,544 @@ +$( document ).ready(function() { + + /* + * When the user is logged in, it's name is loaded in the "data" attribute of the "#loggedUser" element. + * This name is then passed to the socket connection handshake query + */ + var username; + var time_out=300;//5 minutes in seconds + var domain_url="http://192.168.12.77:3000";// The url where the game is to be run (dont include '/' at the end) + var enable_time_out=false;// play with timeout ? (true/false) + var enable_time_add=false;//add 10 sec to every valid move if enabled( Blitz mode rules) + if($("#loggedUser").length) { + username = $("#loggedUser").data("user"); + } else { + username = "Anonymous"; + } + + // socket used for real time games + var socket = io(domain_url, { query: 'user=' + username }); + + //socket used to broadcast live games on tv page + var tvSocket = io(domain_url+'/tv'); + + // socket used to broadcast events to monitoring page + var monitorSocket = io(domain_url+'/monitor'); + + // Puzzle of the day: initialize a chess board with puzzle data + if ($("#pod").length) { + var pod = new ChessBoard('pod', $("#pod").data('fen')); + $('#podSolution').popover(); + } + + /* + * Show error message on login failure + */ + if ($("#loginError").length && !$("#loginError").is(':empty')) { + + Messenger({ + extraClasses: 'messenger-fixed messenger-on-right messenger-on-top' + }).post({ + message: $("#loginError").html(), + type: 'error', + showCloseButton: true, + hideAfter: 10 + }); + } + + /* + * Show error message on registration failure + */ + if ($("#registerError").length && !$("#registerError").is(':empty')) { + + Messenger({ + extraClasses: 'messenger-fixed messenger-on-right messenger-on-top' + }).post({ + message: $("#registerError").html(), + type: 'error', + showCloseButton: true, + hideAfter: 10 + }); + } + + /* + * Show message on successful logout + */ + if ($("#logoutSuccess").length && !$("#logoutSuccess").is(':empty')) { + + Messenger({ + extraClasses: 'messenger-fixed messenger-on-right messenger-on-top' + }).post({ + message: $("#logoutSuccess").html(), + type: 'success', + showCloseButton: true, + hideAfter: 10 + }); + } + + /* + * Show welcome message on registration success + */ + if ($("#registerSuccess").length && !$("#registerSuccess").is(':empty')) { + + Messenger({ + extraClasses: 'messenger-fixed messenger-on-right messenger-on-top' + }).post({ + message: $("#registerSuccess").html(), + type: 'success', + showCloseButton: true, + hideAfter: 10 + }); + } + + /* + * Show welcome message on login success + */ + if ($("#welcomeMessage").length && !$("#welcomeMessage").is(':empty')) { + + Messenger({ + extraClasses: 'messenger-fixed messenger-on-right messenger-on-top' + }).post({ + message: $("#welcomeMessage").html(), + type: 'success', + showCloseButton: true, + hideAfter: 10 + }); + } + + /* + * Show message on account update success + */ + if ($("#updateStatus").length && !$("#updateStatus").is(':empty')) { + + var ok = $("#updateStatus").data('ok'); + var message = $("#updateStatus").html(); + + Messenger({ + extraClasses: 'messenger-fixed messenger-on-right messenger-on-top' + }).post({ + message: message, + type: ok ? 'success' : 'error', + showCloseButton: true, + hideAfter: 10 + }); + } + + /* + * Show chats to be displayed + * Chats are never stored . + * So , chats are lost if any page is reloaded . + * Chat pops up whenver there's a new message + * TODO :Store chat conversations . + */ + var socket1 = io(); + $('.chat-form').submit(function(){ + + if( $('#m').val().length>0) + { + socket1.emit('chat message', username+' : '+$('#m').val()); + } + $('#m').val(''); + return false; + }); + socket.on('chat message', function(msg){ + //new chat message ..pop the chats + $(".chat").show(); + document.getElementById('chat-active').className='active'; + $('#messages').append($('
  • ').text(msg)); + }); + + /* + * show or hide the chats window + */ + showhideChat= function () { + $(".chat").toggle(); + if($(".chat").is(":visible") == true)//if chat is visible then make Chats menu active + { + document.getElementById('chat-active').className='active'; + } + else + document.getElementById('chat-active').className='inactive'; + + }; + //initially hide chat + $(".chat").hide(); + document.getElementById('chat-active').className='inactive';//make chat inactive + + /* + * Game page + */ + if ($("#board").length) { + + /* + * Initialize a new game + */ + var game = new Chess(); + var pgnEl = $('#pgn'); + var token = $("#board").data('token'); + var side = $("#board").data('side'); + var opponentSide = side === "black" ? "white" : "black"; + + /* + * Timer : displays time taken by each player while making moves + * Displays time remaining for each player + */ + var black=false; + var white=false; + var timer=function(time_set) + { + /* + added condtion to checkout for gameover + */ + var possibleMoves = game.moves(); + //alert(game.game_over()); + // if the game is over, reload a new game + if (game.in_draw() === true ) { + $('#gameResult').html('Game is a draw !'); + $('#gameResultPopup').modal({ + keyboard: false, + backdrop: 'static' + }); + } + + if(game.turn().toString()=='w') + { + if(game.game_over() === true || possibleMoves.length===0) + { + $('#gameResult').html('Game Over.Black Won !'); + $('#gameResultPopup').modal({ + keyboard: false, + backdrop: 'static' + }); + } + if(enable_time_out) + { + time_set[0] -= 1; + if (black) { + if (enable_time_add)//if enabled will add 10 sec to each valid move + time_set[1] += 10; + black = false; + + } + white = true; + if (time_set[0] <= 0) { + //handle time out + $('#gameResult').html('TimeOut! Black Won !'); + $('#gameResultPopup').modal({ + keyboard: false, + backdrop: 'static' + }); + clearInterval(timer_interval); + } + } + } + if(game.turn().toString()=='b') + { + if(game.game_over() === true || possibleMoves.length===0) + { + $('#gameResult').html('Game Over. White Won !'); + $('#gameResultPopup').modal({ + keyboard: false, + backdrop: 'static' + }); + } + if(enable_time_out) + { + time_set[1] -= 1; + if (white) { + if (enable_time_add)//if enabled will add 10 sec to each valid move + time_set[0] = time_set[0] + 10; + white = false; + } + black = true; + if (time_set[1] <= 0) { + //handle time out + $('#gameResult').html('TimeOut! White Won !'); + $('#gameResultPopup').modal({ + keyboard: false, + backdrop: 'static' + }); + clearInterval(timer_interval); + } + } + } + if(enable_time_out) + { + $("#timeb").html(("00" + Math.floor(time_set[1] / 60)).slice(-2) + ":" + ("00" + time_set[1] % 60).slice(-2)); + $("#timew").html(("00" + Math.floor(time_set[0] / 60)).slice(-2) + ":" + ("00" + time_set[0] % 60).slice(-2)); + } + return time_set; + }; + + /* + * When a piece is dragged, check if it the current player has the turn + */ + var onDragStart = function(source, piece, position, orientation) { + if (game.game_over() === true || + (game.turn() === 'w' && piece.search(/^b/) !== -1) || + (game.turn() === 'b' && piece.search(/^w/) !== -1) || + (game.turn() !== side.charAt(0) )) { + return false; + } + }; + + /* + * When a piece is dropped, check if the move is legal + */ + var onDrop = function(source, target, piece, newPos, oldPos, orientation) { + // see if the move is legal + var move = game.move({ + from: source, + to: target, + promotion: 'q' // NOTE: always promote to a queen for example simplicity + }); + + // illegal move + if (move === null) return 'snapback'; + pgnEl.html(game.pgn()); + $('.turn').removeClass("fa fa-spinner"); + $('#turn-' + game.turn()).addClass("fa fa-spinner"); + + + socket.emit('new-move', { + token: token, + source: source, + target: target, + piece: piece, + newPosition: ChessBoard.objToFen(newPos), + oldPosition: ChessBoard.objToFen(oldPos) + }); + }; + + // update the board position after the piece snap + // for castling, en passant, pawn promotion + var onSnapEnd = function() { + board.position(game.fen()); + + }; + + /* + * Initialize a new board + */ + var cfg = { + draggable: true, + position: 'start', + moveSpeed: 'slow', + onDragStart: onDragStart, + onSnapEnd: onSnapEnd, + onDrop: onDrop, + snapbackSpeed: 500, + snapSpeed: 150, + orientation: side + }; + var board = new ChessBoard('board', cfg); + + /* + * When the game page is loaded, fire a join event to join the game room + */ + socket.emit('join', { + 'token': token, + 'side': side + }); + + /* + * When a new game is created, the game creator should wait for an opponent to join the game + */ + socket.on('wait', function () { + var url = domain_url+"/game/" + token + "/" + opponentSide; + $('#gameUrl').html(url); + $('#gameUrlPopup').modal({ // show modal popup to wait for opponent + keyboard: false, + backdrop: 'static' + }); + }); + + /* + * A second player has joined the game => the game can start + */ + socket.on('ready', function (data) { + //intialize the timer + var time_sets=[0,0]; + time_sets[0]=time_out; + time_sets[1]=time_out; + timer_interval=setInterval(function(){ time_sets=timer(time_sets)}, 1000);//repeat every second + $('#turn-w').addClass("fa fa-spinner"); + $('#player-white').html(data.white); + $('#player-black').html(data.black); + $('#gameUrlPopup').modal('hide'); + }); + + /* + * A new move has been made by a player => update the UI + */ + socket.on('new-move', function(data){ + + game.move({ from: data.source, to: data.target ,promotion: 'q'}); // NOTE: always promote to a queen for example simplicity}); + board.position( game.fen() ); + pgnEl.html(game.pgn()); + $('.turn').removeClass("fa fa-spinner"); + $('#turn-' + game.turn()).addClass("fa fa-spinner"); + }); + + /* + * A player resigns the game + */ + $('#resignButton').click(function (ev) { + ev.preventDefault(); + socket.emit('resign', { + 'token': token, + 'side': side + }); + }); + + /* + * Notify opponent resignation + */ + socket.on('player-resigned', function (data) { + $('#gameResult').html(data.side + ' resigned.'); + $('#gameResultPopup').modal({ + keyboard: false, + backdrop: 'static' + }); + }); + + /* + * Notify opponent disconnection + */ + socket.on('opponent-disconnected', function () { + $('#gameResult').html('Your opponent has been disconnected.'); + $('#gameResultPopup').modal({ + keyboard: false, + backdrop: 'static' + }); + }); + + /* + * Notify that the game is full => impossible to join the game + */ + socket.on('full', function () { + alert("This game has been already joined by another person."); + window.location = '/'; + }); + + } + + /* + * TV page + */ + if ($("#trg").length) { + var trg = new ChessBoard('trg', 'start'); // initialize a chess board with the top rated live game + tvSocket.on('new-top-rated-game-move', function(data){ + trg.position(data.fen); + if ($("#tv-game-details").length) { + $("#pgn").html(data.pgn); + $("#pgn").scrollTop($("#pgn")[0].scrollHeight); + $('.turn').removeClass("fa fa-spinner"); + $('#turn-' + data.turn).addClass("fa fa-spinner"); + } + }); + } + + /* + * Monitoring page + */ + if ($("#monitor").length) { + + var nbUsers, nbGames, totalGames; + + monitorSocket.on('update', function(data) { + /* + * load monitoring event data + */ + nbUsers = data.nbUsers; + nbGames = data.nbGames; + totalGames = nbGames; // todo: should be set from data.totalGames; + $("#nbUsers").html(nbUsers); + $("#nbGames").html(nbGames); + $("#totalGames").html(totalGames); + + /* + * Update the status chart + */ + var chart = $('#chart').highcharts(); + chart.series[0].addPoint(nbUsers, true, true); + chart.series[1].addPoint(nbGames, true, true); + }); + + $('#chart').highcharts({ + chart: { + type: 'spline', + renderTo: 'container', + defaultSeriesType: 'spline', + animation: Highcharts.svg, // don't animate in old IE + marginRight: 10 + }, + title: { + text: '' + }, + yAxis: { + title: { + text: 'Total' + }, + plotLines: [{ + value: 0, + width: 1, + color: '#808080' + }] + }, + legend: { + enabled: true + }, + exporting: { + enabled: false + }, + series: [{ + name: 'active users', + data: [0,0,0,0,0,0] + },{ + name: 'active games', + data: [0,0,0,0,0,0] + }] + }); + + } + + /* + * Search page + */ + if ($("#searchGameForm")) { + $( "#searchGameFormSubmit" ).on("click", function( event ) { + $.ajax({ + type: "POST", + url: domain_url+"/search", + data: { + white: $( "input[name$='white']" ).val(), + black: $( "input[name$='black']" ).val(), + content: $( "input[name$='content']" ).val(), + result: $( "input[name$='result']" ).val() + }, + success: function (data){ + var games = data.games; + console.log(games.length); + $('#foundGamesTable tbody tr').remove(); + for (var i = 0; i < games.length; i++) { + var game = "" + + "" + games[i]._id + "" + + "" + games[i]._source.white + "" + + "" + games[i]._source.black + "" + + "" + games[i]._source.result + "" + + "" + " Preview" + "" + + ""; + $('#foundGamesTable tbody').append(game); + } + $('#totalFoundGames').html(games.length); + $("#searchResult").show(); + }, + error: function() { + alert("Error while searching games!"); + } + }); + event.preventDefault(); + }); + } +}); + diff --git a/public/stylesheets/chesshub.css b/public/stylesheets/chesshub.css index e40e074..d896dbe 100644 --- a/public/stylesheets/chesshub.css +++ b/public/stylesheets/chesshub.css @@ -103,3 +103,29 @@ body { .table td, th { text-align: center; } +/*chat css*/ +.chat { font: 15px Helvetica, Arial;padding: 0; box-sizing: border-box; border: 1px solid ;border-color: #428BCA; + right:15px;top:3px;position:fixed; + height: 99%; +} +.chat-title{text-align: center;color:#31708F;height:5%;display: block;position: relative;padding-top: 10px;background-color: #D9EDF7} +.chat-container{ border: 1px solid ;border-color: #428BCA; + display: block; + height: 87%; + position: relative; +} + +form .chat-form { + border-top:1px solid #5599ff; padding: 3px; width: 100%;;position: relative; + height: 8%; +} +.chat-input-form {width:75% ;height: 100%;margin-top:4px} +.submit-chat {width:25%;color: #111} +#messages { list-style-type: none; margin: 0; padding: 0;overflow-y: scroll; + position: relative; + width:250px; + height: 100%; +} +#messages li { padding: 5px 10px; } +#messages li:nth-child(odd) { background: #F5F5F5; } +#messages li:nth-child(even) { background: #5599ff; } \ No newline at end of file diff --git a/routes/index.js b/routes/index.js index ce1a7c1..445baa8 100644 --- a/routes/index.js +++ b/routes/index.js @@ -27,10 +27,10 @@ router.get('/', function(req, res) { }); }); }); - router.get('/game/:token/:side', function(req, res) { var token = req.params.token; var side = req.params.side; + res.render('partials/game', { title: 'Chess Hub - Game ' + token, user: req.user, @@ -40,6 +40,28 @@ router.get('/game/:token/:side', function(req, res) { }); }); +router.get('/game/:token/:side/:timeout', function(req, res) { + var token = req.params.token; + var side = req.params.side; + var timeout=req.params.timeout; + var enable=false; + if(timeout>0){ + enable=true; + } + + console.log(timeout); + console.log(enable); + res.render('partials/game', { + title: 'Chess Hub - Game ' + token, + user: req.user, + isPlayPage: true, + token: token, + side: side, + timeout:enable, + timeouttime1:timeout + }); +}); + router.get('/logout', function(req, res) { req.logout(); req.flash('logoutSuccess', 'You have been successfully logged out'); diff --git a/routes/play.js b/routes/play.js index 93c4471..c294b2e 100644 --- a/routes/play.js +++ b/routes/play.js @@ -6,15 +6,22 @@ router.get('/', function(req, res) { res.render('partials/play', { title: 'Chess Hub - Game', user: req.user, - isPlayPage: true + isPlayPage: true, + timeout:false, + timeoutTime:0 }); }); router.post('/', function(req, res) { + var side = req.body.side; //var opponent = req.body.opponent; // playing against the machine in not implemented var token = util.randomString(20); - res.redirect('/game/' + token + '/' + side); + var enable=req.body.enable; + var timeout=req.body.timeout; + if(!timeout) + timeout=0; + res.redirect('/game/' + token + '/' + side+'/'+timeout); }); module.exports = router; \ No newline at end of file diff --git a/site/Simple-chat.jpg b/site/Simple-chat.jpg new file mode 100644 index 0000000..21f6e35 Binary files /dev/null and b/site/Simple-chat.jpg differ diff --git a/views/layout.hbs b/views/layout.hbs index daff3ec..b3b0092 100644 --- a/views/layout.hbs +++ b/views/layout.hbs @@ -23,21 +23,36 @@
  • Play
  • Tv
  • Search
  • +
  • Chat
  • {{#if user}}
  • {{ user.name }}
  • + {{else}}
  • Sign in
  • {{/if}} +
    + + +

    Chess Hub

    - +
    +

    Quick Chat

    +
    +
      +
      + +
      +
      +
      {{{body}}}
      + +
      + +
      + +
      +
      + +
      +
      +