if (!ChessOKBoard) 
{

var ChessOKBoard = "defined";

jQuery.fn.mousehold = function(timeout, f) {
	if (timeout && typeof timeout == 'function') {
		f = timeout;
		timeout = 100;
	}
	if (f && typeof f == 'function') {
		var timer = 0;
		var fireStep = 0;
		return this.each(function() {
			jQuery(this).mousedown(function() {
				fireStep = 1;
				var ctr = 0;
				var t = this;
				timer = setInterval(function() {
					ctr++;
					f.call(t, ctr);
					fireStep = 2;
				}, timeout);
			})

			clearMousehold = function() {
				clearInterval(timer);
				if (fireStep == 1) f.call(this, 1);
				fireStep = 0;
			}
			
			jQuery(this).mouseout(clearMousehold);
			jQuery(this).mouseup(clearMousehold);
		})
	}
}

function SvgToString(){this.svgString="";this.moveTo=function(x,y){this.svgString=this.svgString+"M"+x+","+y;return this;};this.curveTo=function(x1,y1,x2,y2,x,y){this.svgString=this.svgString+"C"+x1+","+y1+","+x2+","+y2+","+x+","+y;return this;};this.lineTo=function(x,y){this.svgString=this.svgString+"L"+x+","+y;return this;};return this;}function BoardMarkers(boardWrapper){this.markers=[];var letter=[];letter.a=1;letter.b=2;letter.c=3;letter.d=4;letter.e=5;letter.f=6;letter.g=7;letter.h=8;var colors=[];colors.A="#f00";colors.D="#0f0";colors.I="#ff0";colors.C="#00f";var opacities=[];opacities.N=0.6;opacities.L=0.6;opacities.E=0.4;opacities.H=0.3;opacities.H=0.1;var squareSize=boardWrapper.squareSize;var lastMarkers;var canvas=null;this.getCanvas=function(){if(canvas==null){var brdMarker=boardWrapper.markersView;var board=boardWrapper.boardTable;canvas=Raphael(brdMarker,boardWrapper.visibleCols*squareSize,boardWrapper.visibleRows*squareSize);}return canvas;};this.calculatePos=function(x,y){if(boardWrapper.gui.flipped){x=9-x;y=9-y;}if(boardWrapper.isBoardrect){x-=letter[boardWrapper.startX]-1;y-=8-boardWrapper.finishY;}return{x:(x-0.5)*(squareSize),y:(y-0.5)*(squareSize)};};this.drawPoint=function(pointX,pointY,color,opacity){var x=letter[pointX];var y=9-pointY;CirclePos=this.calculatePos(x,y);isSmall=boardWrapper.className.indexOf("small")!=-1;var circRad;if(isSmall){circRad=5;}else{circRad=10;}var markerPoint=this.getCanvas().circle(CirclePos.x,CirclePos.y,circRad);markerPoint.attr({fill:color,stroke:"#000",opacity:opacity});this.markers.push(markerPoint);};this.drawCircle=function(pointX,pointY,color,opacity){var x=letter[pointX];var y=9-pointY;CirclePos=this.calculatePos(x,y);var isSmall=boardWrapper.className.indexOf("small")!=-1;var circRad=squareSize/2;if(isSmall){opacWidth=3;}else{opacWidth=4;}var markerPoint=this.getCanvas().circle(CirclePos.x,CirclePos.y,circRad-opacWidth/2);markerPoint.attr({stroke:color,opacity:1,"stroke-width":opacWidth,"stroke-opacity":opacity});this.markers.push(markerPoint);};this.drawSolidRectangle=function(pointX,pointY,color,opacity){var x=letter[pointX];var y=9-pointY;if(boardWrapper.gui.flipped){x=9-x;y=9-y;}if(boardWrapper.isBoardrect){x-=letter[boardWrapper.startX]-1;y-=8-boardWrapper.finishY;}RecPos={x:(x)*(squareSize),y:(y)*(squareSize)};var isSmall=boardWrapper.className.indexOf("small")!=-1;if(isSmall){rectRad=3;}else{rectRad=4;}if(isSmall){opacWidth=3;}else{opacWidth=4;}var markerRect=this.getCanvas().rect(RecPos.x,RecPos.y,squareSize,squareSize-opacWidth/2,rectRad);markerRect.attr({opacity:opacity,color:color});this.markers.push(markerRect);};this.drawRectangle=function(pointX,pointY,color,opacity){var x=letter[pointX];var y=9-pointY;if(boardWrapper.gui.flipped){x=9-x;y=9-y;}if(boardWrapper.isBoardrect){x-=letter[boardWrapper.startX]-1;y-=8-boardWrapper.finishY;}RecPos={x:(x-1)*(squareSize),y:(y-1)*(squareSize)};var isSmall=boardWrapper.className.indexOf("small")!=-1;if(isSmall){rectRad=3;}else{rectRad=4;}if(isSmall){opacWidth=3;}else{opacWidth=4;}var markerRect=this.getCanvas().rect(RecPos.x,RecPos.y,squareSize-opacWidth/2,squareSize-opacWidth/2,rectRad);markerRect.attr({stroke:color,opacity:1,"stroke-width":opacWidth,"stroke-opacity":opacity});this.markers.push(markerRect);};this.drawText=function(fromX,fromY,toX,toY,opacity,text){var fX=letter[fromX];var fY=9-fromY;var tX=letter[toX];var tY=9-toY;if(boardWrapper.gui.flipped){fX=9-fX;fY=9-fY;tX=9-tX;tY=9-tY;}if(boardWrapper.isBoardrect){fX-=letter[boardWrapper.startX]-1;fY-=8-boardWrapper.finishY;tX-=letter[boardWrapper.startX]-1;tY-=8-boardWrapper.finishY;}isSmall=boardWrapper.className.indexOf("small")!=-1;var fontSize;if(isSmall){fontSize="20px";}else{fontSize="40px";}fX=(fX-0.5)*(squareSize);fY=(fY-0.5)*(squareSize);tX=(tX-0.5)*(squareSize);tY=(tY-0.5)*(squareSize);var markerText=this.getCanvas().print(fx,fy,"text",paper.getFont("Times",800),30).attr({fill:"#f00"});this.getCanvas().text(200,450,"Example:getBBox.Works on .",60).attr({fill:"#000000","font-size":24,"stroke-width":1});this.markers.push(markerText);};this.drawArrow=function(fromX,fromY,toX,toY,rounded,color,opacity){var fX=letter[fromX];var fY=9-fromY;var tX=letter[toX];var tY=9-toY;if(boardWrapper.gui.flipped){fX=9-fX;fY=9-fY;tX=9-tX;tY=9-tY;}if(boardWrapper.isBoardrect){fX-=letter[boardWrapper.startX]-1;fY-=8-boardWrapper.finishY;tX-=letter[boardWrapper.startX]-1;tY-=8-boardWrapper.finishY;}isSmall=boardWrapper.className.indexOf("small")!=-1;if(isSmall){arrowX=3;arrowY=8;arrowZ=10;}else{arrowX=5;arrowY=15;arrowZ=20;}fX=(fX-0.5)*(squareSize);fY=(fY-0.5)*(squareSize);tX=(tX-0.5)*(squareSize);tY=(tY-0.5)*(squareSize);var lX=Math.abs(tX-fX);var lY=Math.abs(tY-fY);var tL=Math.sqrt(lX*lX+lY*lY);var mod=-1*lX/(tX-fX);var rotationAngle;if(lX==0){rotationAngle=0;}else{rotationAngle=-Math.atan((tX-fX)/(tY-fY));}if(lY==0){rotationAngle=-rotationAngle;}else{if(tY>fY){rotationAngle=Math.PI+rotationAngle;}}rotationAngle=rotationAngle/Math.PI*180;var markerArrow;try{if(rounded){var sq=Math.sqrt(squareSize*squareSize/2);var ArrowSVG=SvgToString();ArrowSVG.moveTo(fX,fY).curveTo(fX-2+0.5*mod*sq,fY-sq,fX-arrowX+mod*sq,fY-1.5*sq,fX-arrowX+mod*sq,fY-3*sq+arrowY).lineTo(fX-arrowY+mod*sq,fY-3*sq+arrowZ).lineTo(fX+mod*sq,fY-3*sq).lineTo(fX+arrowY+mod*sq,fY-3*sq+arrowZ).lineTo(fX+arrowX+mod*sq,fY-3*sq+arrowY).curveTo(fX+arrowX+mod*sq,fY-1.5*sq,fX+2+0.5*mod*sq,fY-sq,fX,fY);markerArrow=this.getCanvas().path(ArrowSVG.svgString);markerArrow.attr({fill:color,stroke:"#000",opacity:opacity});var knightAngle=Math.atan(1/3)/Math.PI*180;markerArrow.rotate(rotationAngle-mod*knightAngle,fX,fY);}else{var ArrowSVG=SvgToString();ArrowSVG.moveTo(fX,fY).lineTo(fX-arrowX,fY-tL+arrowY).lineTo(fX-arrowY,fY-tL+arrowZ).lineTo(fX,fY-tL).lineTo(fX+arrowY,fY-tL+arrowZ).lineTo(fX+arrowX,fY-tL+arrowY).lineTo(fX,fY);markerArrow=this.getCanvas().path(ArrowSVG.svgString);markerArrow.attr({fill:color,stroke:"#000",opacity:opacity});markerArrow.rotate(rotationAngle,fX,fY);}}catch(e){}this.markers.push(markerArrow);};this.drawMarkerArrow=function(marker){var opacity=opacities[marker.charAt(0)];var color=colors[marker.charAt(1)];fromX=marker.charAt(2);fromY=marker.charAt(3);toX=marker.charAt(4);toY=marker.charAt(5);rounded=false;this.drawArrow(fromX,fromY,toX,toY,rounded,color,opacity);};this.drawMarkerSquare=function(marker){var opacity=opacities[marker.charAt(0)];var color=colors[marker.charAt(1)];x=marker.charAt(2);y=marker.charAt(3);if((marker.length==6)&&(marker.charAt(5)=="1")){this.drawRectangle(x,y,color,opacity);}else{this.drawCircle(x,y,color,opacity);}};this.drawMarkerRectangle=function(marker){var opacity=opacities[marker.charAt(0)];var color=colors[marker.charAt(1)];x=marker.charAt(2);y=marker.charAt(3);this.drawRectangle(x,y,color,opacity);};this.drawMarkerText=function(marker){var opacity=opacities[marker.charAt(0)];fromX=marker.charAt(1);fromY=marker.charAt(2);toX=marker.charAt(3);toY=marker.charAt(4);var pos=marker.indexOf("'")+1;this.drawText(fromX,fromY,toX,toY,opacity,marker.substr(pos,marker.length-2));};this.drawMarker=function(marker){switch(marker.charAt(0)){case"A":this.drawMarkerArrow(marker.substr(1));break;case"S":this.drawMarkerSquare(marker.substr(1));break;case"R":this.drawMarkerRectangle(marker.substr(1));break;case"T":this.drawMarkerText(marker.substr(1));break;default:break;}};this.clearMarkers=function(){for(var i = 0; i < this.markers.length; i++){this.markers[i].remove();}this.markers=[];};this.notaDrawArrow=function(fromX,fromY,toX,toY,knight){this.clearMarkers();var color=colors.I;var opacity=opacities.L;this.drawArrow(fromX,fromY,toX,toY,knight,color,opacity);this.drawPoint(fromX,fromY,color,opacity);};this.drawMarkers=function(markersString){this.clearMarkers();lastMarkers=markersString;if(markersString){markers=markersString.split(" ");}else{markers=[];}for(var marker in markers){this.drawMarker(markers[marker]);}};this.redrawMarkers=function(){this.drawMarkers(lastMarkers);};}

function chessBoard(){this.letter=[];this.letter.a=1;this.letter.b=2;this.letter.c=3;this.letter.d=4;this.letter.e=5;this.letter.f=6;this.letter.g=7;this.letter.h=8;this.numbers=[0,8,7,6,5,4,3,2,1];this.letters=["0","a","b","c","d","e","f","g","h"];this.currentMove;this.castling;this.enPassant;this.halfMoves;this.fullMoves;this.pieces=[];this.squares=[];this.squares.a=[];this.squares.b=[];this.squares.c=[];this.squares.d=[];this.squares.e=[];this.squares.f=[];this.squares.g=[];this.squares.h=[];for(var c in this.squares){for(var d=1;d<=8;d++){this.squares[c][d]=new boardSquare(c,d);}}}chessBoard.prototype.loadFEN=function(p){for(var u in this.squares){for(var v=1;v<=8;v++){this.squares[u][v].piece=null;}}delete this.pieces;this.pieces=[];var y=p.split(" ");var t=y[0].split("/");for(var o=1;o<=8;o++){var j=t[o-1].split("");var z=1;for(var r=1;r<=j.length;r++){var x=j[r-1];var w;if(/[rbqkpn]/.test(x)){w="black";}else{if(/[RBQKPN]/.test(x)){w="white";}else{z=parseInt(z)+parseInt(x);continue;}}switch(x.toLowerCase()){case"r":name="rook";break;case"b":name="bishop";break;case"q":name="queen";break;case"k":name="king";break;case"p":name="pawn";break;case"n":name="knight";break;default:break;}var q=this.letters[z];var s=this.numbers[o];this.addPiece(name,w,q,s);z++;}}if(y[1]=="b"){this.currentMove="black";}else{this.currentMove="white";}this.castling=y[2];this.enPassant=y[3];this.halfMoves=y[4];this.fullMoves=y[5];};chessBoard.prototype.addPiece=function(j,f,g,h){var i=new boardPiece(j,f);i.square=this.squares[g][h];this.pieces.push(i);this.squares[g][h].piece=i;};chessBoard.prototype.moveHandler=function(k,n,p,m,o,l,t,r,s){if(k=="king"&&(Math.abs(this.letter[n]-this.letter[m])>1)){if(this.letter[n]>this.letter[m]){this.castle("O-O-O");}else{this.castle("O-O");}return;}this.makeMove(n,p,m,o,l);if(k=="pawn"){var q;if(this.currentMove=="white"){q=1;}else{q=-1;}if(l&&m+o==this.enPassant){this.squares[m][o-q].piece.square=null;this.squares[m][o-q].piece=null;}if(Math.abs(o-p)==2){this.enPassant=m+(parseInt(o)-q);}else{this.enPassant="-";}if(t){this.squares[m][o].piece.name=r;}}else{this.enPassant="-";if(k=="rook"&&this.castling!="-"){if(n=="a"&&p==8){this.castling=this.castling.replace(/q/,"");}else{if(n=="h"&&p==8){this.castling=this.castling.replace(/k/,"");}else{if(n=="a"&&p==1){this.castling=this.castling.replace(/Q/,"");}else{if(n=="h"&&p==1){this.castling=this.castling.replace(/K/,"");}}}}}if(k=="king"&&this.castling!="-"){if(this.currentMove=="white"){this.castling=this.castling.replace(/K/,"");this.castling=this.castling.replace(/Q/,"");}else{this.castling=this.castling.replace(/k/,"");this.castling=this.castling.replace(/q/,"");}}if(this.castling==""){this.castling="-";}}if(k=="pawn"||t||l){this.halfMoves=0;}else{this.halfMoves++;}if(this.currentMove=="black"){this.fullMoves++;}this.switchMove();};chessBoard.prototype.castleMove=function(f,h,i){var j;if(f=="king"&&(Math.abs(this.letter[h]-this.letter[i])>1)){if(this.letter[h]>this.letter[i]){j="O-O-O";}else{j="O-O";}}else{return{castling:false};}var g;if(this.currentMove=="white"){g=1;}else{g=8;}if(/^O-O\+?$/.test(j)){return{fromX:"h",fromY:g,toX:"f",toY:g,piece:"rook",castling:true};}else{return{fromX:"a",fromY:g,toX:"d",toY:g,piece:"rook",castling:true};}};chessBoard.prototype.castle=function(f){var e;if(this.currentMove=="white"){e=1;}else{e=8;}if(/^O-O\+?$/.test(f)){this.makeMove("e",e,"g",e);this.makeMove("h",e,"f",e);}else{this.makeMove("e",e,"c",e);this.makeMove("a",e,"d",e);}var d;if(this.currentMove=="white"){d=/[KQ]/g;}else{d=/[kq]/g;}this.enPassant="-";this.halfMoves++;if(this.currentMove=="black"){this.fullMoves++;}this.castling=this.castling.replace(d,"");if(this.castling==""){this.castling="-";}this.switchMove();};chessBoard.prototype.getPiece=function(k,l,g,i){var h=new Array();for(var j=0;j<this.pieces.length;j++){if(this.pieces[j].name==k&&this.pieces[j].color==l&&this.pieces[j].square!=null&&((g&&this.pieces[j].square.x==g)||!g)&&((i&&this.pieces[j].square.y==i)||!i)){h.push(j);}}return h;};chessBoard.prototype.switchMove=function(){if(this.currentMove=="white"){this.currentMove="black";}else{this.currentMove="white";}};chessBoard.prototype.makeMove=function(i,l,j,g,h){var k=this.squares[i][l].piece;k.square=this.squares[j][g];if(h&&this.squares[j][g].piece!=null){this.squares[j][g].piece.square=null;}this.squares[j][g].piece=k;this.squares[i][l].piece=null;};chessBoard.prototype.currentFEN=function(i){var j="";for(var h=8;h>=1;h--){var l=0;for(var m in this.squares){if(this.squares[m][h].piece!=null){if(l!=0){j+=l;l=0;}var k=this.squares[m][h].piece.name;var n=this.squares[m][h].piece.color;switch(k){case"rook":name="r";break;case"bishop":name="b";break;case"queen":name="q";break;case"king":name="k";break;case"pawn":name="p";break;case"knight":name="n";break;default:break;}if(n=="white"){name=name.toUpperCase();j+=name;}else{j+=name;}}else{l++;}}if(l!=0){j+=l;}if(h!=1){j+="/";}}j+=" "+this.currentMove.substr(0,1);j+=" "+this.castling;j+=" "+this.enPassant;if(!i){j+=" "+this.halfMoves;j+=" "+this.fullMoves;}return j;};function boardSquare(d,c){this.x=d;this.y=c;this.piece;}function boardPiece(c,d){this.square;this.name=c;this.color=d;}

function isin(element,set){for(var j=0;j<set.length;j++){if(element==set[j]){return true;}}return false;}function chessRules(aBoard){var board=aBoard;var checking=false;var letters=["a","b","c","d","e","f","g","h"];var letter=[];letter.a=1;letter.b=2;letter.c=3;letter.d=4;letter.e=5;letter.f=6;letter.g=7;letter.h=8;this.pawn=function(fromX,fromY,color){var toX;var toY;var toYlong;var fromXnum;var result=[];var mod;fromXnum=letter[fromX];if(color=="white"){mod=1;}else{mod=-1;}toX=fromX;toY=parseInt(fromY+mod);var oldFEN=board.currentFEN();if(board.squares[toX][toY].piece==null){if(!checking){board.makeMove(fromX,fromY,toX,toY,false);if(!this.check(color)){result.push(toX+toY);}board.loadFEN(oldFEN);}else{result.push(toX+toY);}}toYlong=parseInt(toY+mod);if(((fromY==2&&color=="white")||(fromY==7&&color=="black"))&&board.squares[toX][toY].piece==null&&board.squares[toX][toYlong].piece==null){if(!checking){board.makeMove(fromX,fromY,toX,toYlong,false);if(!this.check(color)){result.push(toX+toYlong);}board.loadFEN(oldFEN);}else{result.push(toX+toYlong);}}if(fromXnum>1){toX=letters[fromXnum-1-1];capturePiece=board.squares[toX][toY].piece;if(capturePiece!=null&&capturePiece.color!=color){if(!checking){board.makeMove(fromX,fromY,toX,toY,true);if(!this.check(color)){result.push(toX+toY);}board.loadFEN(oldFEN);}else{result.push(toX+toY);}}if(toX+toY==board.enPassant){if(!checking){board.makeMove(fromX,fromY,toX,toY,true);board.squares[toX][toY-mod].piece.square=null;board.squares[toX][toY-mod].piece=null;if(!this.check(color)){result.push(toX+toY);}board.loadFEN(oldFEN);}else{result.push(toX+toY);}}}if(fromXnum<8){toX=letters[fromXnum+1-1];capturePiece=board.squares[toX][toY].piece;if(capturePiece!=null&&capturePiece.color!=color&&capturePiece!="king"){if(!checking){board.makeMove(fromX,fromY,toX,toY,true);if(!this.check(color)){result.push(toX+toY);}board.loadFEN(oldFEN);}else{result.push(toX+toY);}}if(toX+toY==board.enPassant){if(!checking){board.makeMove(fromX,fromY,toX,toY,true);board.squares[toX][toY-mod].piece.square=null;board.squares[toX][toY-mod].piece=null;if(!this.check(color)){result.push(toX+toY);}board.loadFEN(oldFEN);}else{result.push(toX+toY);}}}return result;};this.knight=function(fromX,fromY,color){var oldFEN=board.currentFEN();var fromXnum;var toX;var toY;var toXnum;var result=[];fromXnum=letter[fromX];for(var i=-2;i<=2;i++){for(var j=-2;j<=2;j++){if(Math.abs(i)!=Math.abs(j)&&i!=0&&j!=0){toXnum=parseInt(fromXnum+i);toX=letters[toXnum-1];toY=parseInt(fromY+j);if(toXnum>0&&toXnum<=8&&toY>0&&toY<=8){var pieceTo=board.squares[toX][toY].piece;if(pieceTo==null||pieceTo.color!=color){if(pieceTo!=null){capture=true;}else{capture=false;}if(!checking){board.makeMove(fromX,fromY,toX,toY,capture);if(!this.check(color)){result.push(toX+toY);}board.loadFEN(oldFEN);}else{result.push(toX+toY);}}}}}}return result;};this.bishop=function(fromX,fromY,color,range){var oldFEN=board.currentFEN();var toXnum;var toX;var toY;var fromXnum;if(range==undefined){range=7;}var result=[];fromXnum=letter[fromX];for(var i=1;i<=range;i++){var j=i;toXnum=parseInt(fromXnum+i);toX=letters[toXnum-1];toY=parseInt(fromY+j);if(toXnum>0&&toXnum<=8&&toY>0&&toY<=8){var pieceTo=board.squares[toX][toY].piece;if(pieceTo==null||pieceTo.color!=color){if(pieceTo!=null){capture=true;}else{capture=false;}if(!checking){board.makeMove(fromX,fromY,toX,toY,capture);if(!this.check(color)){result.push(toX+toY);}board.loadFEN(oldFEN);}else{result.push(toX+toY);}}if(pieceTo!=null){break;}}}for(var i=1;i<=range;i++){var j=-i;toXnum=parseInt(fromXnum+i);toX=letters[toXnum-1];toY=parseInt(fromY+j);if(toXnum>0&&toXnum<=8&&toY>0&&toY<=8){var pieceTo=board.squares[toX][toY].piece;if(pieceTo==null||pieceTo.color!=color){if(pieceTo!=null){capture=true;}else{capture=false;}if(!checking){board.makeMove(fromX,fromY,toX,toY,capture);if(!this.check(color)){result.push(toX+toY);}board.loadFEN(oldFEN);}else{result.push(toX+toY);}}if(pieceTo!=null){break;}}}for(var i=-1;i>=-range;i--){var j=i;toXnum=parseInt(fromXnum+i);toX=letters[toXnum-1];toY=parseInt(fromY+j);if(toXnum>0&&toXnum<=8&&toY>0&&toY<=8){var pieceTo=board.squares[toX][toY].piece;if(pieceTo==null||pieceTo.color!=color){if(pieceTo!=null){capture=true;}else{capture=false;}if(!checking){board.makeMove(fromX,fromY,toX,toY,capture);if(!this.check(color)){result.push(toX+toY);}board.loadFEN(oldFEN);}else{result.push(toX+toY);}}if(pieceTo!=null){break;}}}for(var i=-1;i>=-range;i--){var j=-i;toXnum=parseInt(fromXnum+i);toX=letters[toXnum-1];toY=parseInt(fromY+j);if(toXnum>0&&toXnum<=8&&toY>0&&toY<=8){var pieceTo=board.squares[toX][toY].piece;if(pieceTo==null||pieceTo.color!=color){if(pieceTo!=null){capture=true;}else{capture=false;}if(!checking){board.makeMove(fromX,fromY,toX,toY,capture);if(!this.check(color)){result.push(toX+toY);}board.loadFEN(oldFEN);}else{result.push(toX+toY);}}if(pieceTo!=null){break;}}}return result;};this.rook=function(fromX,fromY,color,range){var oldFEN=board.currentFEN();var toXnum;var toX;var toY;var fromXnum;if(range==undefined){range=7;}var result=[];fromXnum=letter[fromX];for(var i=1;i<=range;i++){toXnum=parseInt(fromXnum+i);toX=letters[toXnum-1];toY=fromY;if(toXnum>0&&toXnum<=8&&toY>0&&toY<=8){var pieceTo=board.squares[toX][toY].piece;if(pieceTo==null||pieceTo.color!=color){if(pieceTo!=null){capture=true;}else{capture=false;}if(!checking){board.makeMove(fromX,fromY,toX,toY,capture);if(!this.check(color)){result.push(toX+toY);}board.loadFEN(oldFEN);}else{result.push(toX+toY);}}if(pieceTo!=null){break;}}}for(var i=1;i<=range;i++){toXnum=fromXnum;toX=letters[toXnum-1];toY=parseInt(fromY+i);if(toXnum>0&&toXnum<=8&&toY>0&&toY<=8){var pieceTo=board.squares[toX][toY].piece;if(pieceTo==null||pieceTo.color!=color){if(pieceTo!=null){capture=true;}else{capture=false;}if(!checking){board.makeMove(fromX,fromY,toX,toY,capture);if(!this.check(color)){result.push(toX+toY);}board.loadFEN(oldFEN);}else{result.push(toX+toY);}}if(pieceTo!=null){break;}}}for(var i=-1;i>=-range;i--){toXnum=parseInt(fromXnum+i);toX=letters[toXnum-1];toY=fromY;if(toXnum>0&&toXnum<=8&&toY>0&&toY<=8){var pieceTo=board.squares[toX][toY].piece;if(pieceTo==null||pieceTo.color!=color){if(pieceTo!=null){capture=true;}else{capture=false;}if(!checking){board.makeMove(fromX,fromY,toX,toY,capture);if(!this.check(color)){result.push(toX+toY);}board.loadFEN(oldFEN);}else{result.push(toX+toY);}}if(pieceTo!=null){break;}}}for(var i=-1;i>=-range;i--){toXnum=fromXnum;toX=letters[toXnum-1];toY=parseInt(fromY+i);if(toXnum>0&&toXnum<=8&&toY>0&&toY<=8){var pieceTo=board.squares[toX][toY].piece;if(pieceTo==null||pieceTo.color!=color){if(pieceTo!=null){capture=true;}else{capture=false;}if(!checking){board.makeMove(fromX,fromY,toX,toY,capture);if(!this.check(color)){result.push(toX+toY);}board.loadFEN(oldFEN);}else{result.push(toX+toY);}}if(pieceTo!=null){break;}}}return result;};this.queen=function(fromX,fromY,color){return this.bishop(fromX,fromY,color).concat(this.rook(fromX,fromY,color));};this.king=function(fromX,fromY,color){var oldFEN=board.currentFEN();var toXnum;var toX;var toXpass;var toXpass2;var toY;var fromXnum;var result=[];fromXnum=letter[fromX];toY=fromY;if(board.castling!="-"&&fromXnum==5&&!checking&&!this.check(color)){if((color=="white"&&board.castling.match(/K/))||(color=="black"&&board.castling.match(/k/))){toXnum=fromXnum;toXpass=letters[toXnum+1-1];toX=letters[toXnum+2-1];if(board.squares[toXpass][toY].piece==null&&board.squares[toX][toY].piece==null){board.makeMove(fromX,fromY,toXpass,toY,capture);if(!this.check(color)){passOk=true;}else{passOk=false;}board.loadFEN(oldFEN);if(passOk){board.makeMove(fromX,fromY,toX,toY,capture);if(!this.check(color)){result.push(toX+toY);}board.loadFEN(oldFEN);}}}if((color=="white"&&board.castling.match(/Q/))||(color=="black"&&board.castling.match(/q/))){toXnum=fromXnum;toXpass=letters[toXnum-1-1];toXpass2=letters[toXnum-3-1];toX=letters[toXnum-2-1];if(board.squares[toXpass][toY].piece==null&&board.squares[toX][toY].piece==null&&board.squares[toXpass2][toY].piece==null){board.makeMove(fromX,fromY,toXpass,toY,capture);if(!this.check(color)){passOk=true;}else{passOk=false;}board.loadFEN(oldFEN);if(passOk){board.makeMove(fromX,fromY,toX,toY,capture);if(!this.check(color)){result.push(toX+toY);}board.loadFEN(oldFEN);}}}}return result.concat(this.bishop(fromX,fromY,color,1).concat(this.rook(fromX,fromY,color,1)));};this.check=function(color){if(checking){return false;}checking=true;try{kingX=board.pieces[board.getPiece("king",color)].square.x;kingY=board.pieces[board.getPiece("king",color)].square.y;}catch(e){return true;}for(var i=0;i<board.pieces.length;i++){pieceCheck=board.pieces[i];if(pieceCheck.color!=color&&pieceCheck.square!=null){fromX=pieceCheck.square.x;fromY=pieceCheck.square.y;conSq=eval("this."+pieceCheck.name+'("'+fromX+'", '+fromY+', "'+pieceCheck.color+'")');if(isin(kingX+kingY,conSq)){checking=false;return true;}}}checking=false;return false;};}

var curLineNumber;
function goToStartPosition(element) {
    var brdWrapper = $(element).parents(".chessBoard")[0];
    curLineNumber = "line0";
    $(getNextLine(brdWrapper)).click();
}

function goToFinishPosition(element) {
    var brdWrapper = $(element).parents(".chessBoard")[0];
    curLineNumber = "line0";
    var elem = brdWrapper;
    var lastElem;
    while (elem) {
        lastElem = elem;
        elem = getNextLine(elem);
    }
    $(lastElem).click();
}

function goToNextPosition(element) {
    var brdWrapper = $(element).parents(".chessBoard")[0];
    if (curBrdWrapper && (curBrdWrapper.id == brdWrapper.id)) {
        curLineNumber = findLineNum(curMoveElement);
        $(getNextLine(curMoveElement)).click();
    }
    else {
        if (brdWrapper.curMoveElement) {
            curLineNumber = findLineNum(brdWrapper.curMoveElement);
            $(getNextLine(brdWrapper.curMoveElement)).click();
        }
        else {
            curLineNumber = "line0";
            var nextElem = getNextLine(getNextLine(brdWrapper));
            if (nextElem)
                $(nextElem).click();
            else
                $(getNextLine(brdWrapper)).click();
        }

    }   
    
}


function goToPrevPosition(element) {
    var brdWrapper = $(element).parents(".chessBoard")[0];
    if (curBrdWrapper && (curBrdWrapper.id == brdWrapper.id)) {
        curLineNumber = findLineNum(curMoveElement);
        $(getPrevLine(curMoveElement)).click();
    }
    else {
        if (brdWrapper.curMoveElement) {
            curLineNumber = findLineNum(brdWrapper.curMoveElement);
            $(getPrevLine(brdWrapper.curMoveElement)).click();
        }
        else {
            curLineNumber = "line0";
            $(getNextLine(brdWrapper)).click();
        }
    }

}

function findLineNum(elem)
{
    var classes = elem.className.split(/\s/);
    for (var i = 0, len = classes.length; i < len; i++) 
        if (/^line/.test(classes[i])) return classes[i];
    return null;
}


function classStartsWithLine(elem) {
    var classes = elem.className.split(/\s/);
    for (var i = 0, len = classes.length; i < len; i++) {
        if (classes[i] == "line0") {
            curLineNumber = "line0";
            return true;
        }
        if (classes[i] == curLineNumber) return true;
    }
     
    return false;
}

function findFirstLine(elems) {
    for (var i = 0; i < elems.length; i++) {
        if (classStartsWithLine(elems[i]))
            return elems[i];
    }
    return null;
}

function findLastLine(elems) {
    for (var i = elems.length - 1; i >= 0; i--) {
        if (classStartsWithLine(elems[i]))
            return elems[i];
    }
    return null;
}

function getNextLineDown(elem) {    
    var next = $(elem).nextAll();
    if (next.length != 0)
    {
        for (var i = 0; i < next.length; i++) {
            if (classStartsWithLine(next[i]))
                return next[i];
            var child = $(next[i]).children();
            if (child.length > 0) {
                var firstLine = findFirstLine(child);
                if (firstLine)
                    return firstLine;
                var found = getNextLineDown(child[0]);
                if (found)
                    return found;
            }
        }
    }
    return null;
}

function getPrevLineDown(elem) {
    var prev = $(elem).prevAll();    
    if (prev.length != 0) {
        for (var i = 0; i < prev.length; i++) {
            if (classStartsWithLine(prev[i]))
                return prev[i];
            var child = $(prev[i]).children();
            if (child.length > 0) {
                var lastLine = findLastLine(child);
                if (lastLine)
                    return lastLine;
                var found = getPrevLineDown(child[i]);
                if (found)
                    return found;
            }
        }
    }
    return null;

}

function getPrevLine(elem) {    
    var result = getPrevLineDown(elem);
    var parent = $(elem).parent();
    while (!result && (parent.length > 0) && (!parent.hasClass('section'))) {
        result = getPrevLineDown(parent);
        if (!result)
            parent = parent.parent();
    }
    return result;
}

function getNextLine(elem) {
    var result = getNextLineDown(elem);
    var parent = $(elem).parent();
    while (!result && (parent.length > 0) && (!parent.hasClass('section'))) {
        result = getNextLineDown(parent);
        if (!result)
            parent = parent.parent();
    }
    return result;
}


var curMoveElement;
var curBrdWrapper;
$(document).keydown(function (ev) {
    if (ev.ctrlKey) {
        var elem;
        if (ev.keyCode == 39) {
            elem = $("#next_page");
        }
        if (ev.keyCode == 37) {
            elem = $("#prev_page");
        }
        if (!elem)
            return true;
        if (elem.length > 0)
            window.location = $(elem[0]).attr("href")
        return false;
    }
    else {
        if (!curMoveElement)
            return true;
        var elems;
        curLineNumber = findLineNum(curMoveElement);
        if (ev.keyCode == 39) {            
            elems = $(getNextLine(curMoveElement));
        }
        if (ev.keyCode == 37) {
            elems = $(getPrevLine(curMoveElement));
        }
        if (!elems)
            return true;
        if (elems.length > 0)
            $(elems[0]).click();
        return false;
    }
});

function loadMove(fen, element, move) {
    if (curMoveElement) {
        $(curMoveElement).removeClass('current_move');
    }
    curMoveElement = element;
    curMoveElement.className += ' current_move';
    $(curMoveElement).addClass('current_move');
    element = $(element).parents('.section')[0];
    if (!element)
        element = document;
    var brdWrapper = $(element).find('.chessBoard')[0];
    curBrdWrapper = brdWrapper;
    brdWrapper.curMoveElement = curMoveElement;
    brdWrapper.board.loadFEN(fen);    
    brdWrapper.gui.drawBoardPosition();
    if (move) {
        var fromX = move.charAt(0);
        var fromY = move.charAt(1);
        var toX = move.charAt(2);
        var toY = move.charAt(3);
        var piece = brdWrapper.board.squares[toX][toY].piece;
        var knight = (piece) ? (piece.name == "knight") : false;
        brdWrapper.boardMarkers.notaDrawArrow(fromX, fromY, toX, toY, knight);
    }

}

function promoteTo(pieceName, element) {
    var brdWrapper = $(element).parent().parent().parent()[0];
    var promBox = brdWrapper.promotionView;    
    $(promBox).fadeOut('slow');
    mv = $(promBox).data('move');
    var c = pieceName.charAt(0).toLowerCase();
    if (pieceName == "knight")
        c = 'n';
    mv = mv + c;

    brdWrapper.playController.MoveMade(mv, function (result) {
        if (result) {
            brdWrapper.gui.makeMove('pawn', mv.charAt(1), mv.charAt(2), mv.charAt(3),
                mv.charAt(4), pieceName);
        }
        else {
            brdWrapper.gui.drawBoardPosition();
        }
        brdWrapper.gui.BoardDisabled = false;
    });
      
}

function BoardController() {
    // Rotates the board
    this.flipBoard =
	function (boardId) {
	    var brdWrapper = $(document).find('#' + boardId)[0];
	    if (brdWrapper.gui.flipped)
	        brdWrapper.gui.flipped = false;
	    else
	        brdWrapper.gui.flipped = true;
	    $(brdWrapper.whiteIndicator).addClass('black');
	    $(brdWrapper.whiteIndicator).removeClass('white');
	    $(brdWrapper.blackIndicator).removeClass('black');
	    $(brdWrapper.blackIndicator).addClass('white');

	    var temp = brdWrapper.whiteIndicator;
	    brdWrapper.whiteIndicator = brdWrapper.blackIndicator;
	    brdWrapper.blackIndicator = temp;

	    brdWrapper.gui.drawBoardPosition();
	    brdWrapper.boardMarkers.redrawMarkers();
	}

	this.loadMove =
    function (boardId, moveId) {
        var brdWrapper = $(document).find('#' + boardId)[0];
        var game = brdWrapper.games[0];

        if (moveId == "end") {
            moveId = game.lastMove;
        }
        var fen = game.FENs[game.displayNotation[moveId]["fenlink"].variation][game.displayNotation[moveId]["fenlink"].number];
        brdWrapper.board.loadFEN(fen);
        game.currPosition = fen;
        var oldid = game.notationMove;
        game.notationMove = moveId;

        brdWrapper.gui.displayMove(game, brdWrapper.board, oldid);

        if (moveId != "start") {
            var fromX = game.displayNotation[moveId]["fromto"].fromX;
            var fromY = game.displayNotation[moveId]["fromto"].fromY;
            var toX = game.displayNotation[moveId]["fromto"].toX;
            var toY = game.displayNotation[moveId]["fromto"].toY;

            var knight = (game.displayNotation[moveId]["token"].charAt(0) == "N" ? true : false);

            brdWrapper.boardMarkers.notaDrawArrow(fromX, fromY, toX, toY, knight);            
        } else
            brdWrapper.boardMarkers.clearMarkers();                    

    }
}


function GUI(boardWrapper) {
    var board = boardWrapper.board;
    var boardTable = boardWrapper.boardTable;
    var boardMarkers = boardWrapper.boardMarkers;
    var lang = chessBoardLang;
	var numbers = [8, 7, 6, 5, 4, 3, 2, 1];
	var letters = ["a", "b", "c", "d", "e", "f", "g", "h"];
	var letter = [];
	var canvas = null;
	letter["a"] = 1;
	letter["b"] = 2;
	letter["c"] = 3;
	letter["d"] = 4;
	letter["e"] = 5;
	letter["f"] = 6;
	letter["g"] = 7;
	letter["h"] = 8;

	this.IsFinished = false;
	this.BoardDisabled = false;

	// If board is flipped
	this.flipped = false;

	this.addNotaMove = function (text, fen, move) {
	    var moveString = '<span data-fen="' + fen + '"';
	    if (move) {
	        moveString += ' data-move="' + move + '"';
	    }
	    moveString += ' class="line">' + text + '</span>';

	    this.notation.innerHTML += moveString + ' ';
	}

	this.makeMove = function (piece, fromX, fromY, toX, toY, promoteTo) {
	    var moveNumber = board.fullMoves;

	    var move = board.formMove(piece, fromX, fromY, toX, toY, promoteTo);
	    board.moveHandler(piece, fromX, fromY, toX, toY, promoteTo);
	    this.drawBoardPosition(board);

	    if (this.notation) {
	        var fen = board.currentFEN();

            var moveText = '';

            if (moveNumber == 1 && !this.notation.notEmpty) {
	            this.notation.notEmpty = true;
	            moveText += moveNumber + '.';
	            if (board.currentMove == 'white')
	                moveText += '..';
	            moveText += ' ';
	        }
	        else if (board.currentMove == 'black') {
	            moveText += moveNumber + '. ';
	        }

	        moveText += move.AsString();

	        this.addNotaMove(moveText, fen, move.LongString());
	    }
	}

    this.parseMove =
	function (token, varNum, aIsFinished) {
	    var moveArray = token.match(/([RBQKPN])?([a-h])?([1-8])?([x])?([a-h])([1-8])([=]?)([qnrbQNRB]?)([+#]?)/);	    
	    var fromX;
	    var fromY;
	    var toX;
	    var toY;
	    var piece;
	    var promotion;
	    var promoteTo;

	    fromX = moveArray[2];
	    fromY = moveArray[3];

	    piece = board.squares[fromX][fromY].piece.name;
	    this.IsFinished = aIsFinished;

	    toX = moveArray[5];
	    toY = moveArray[6];

	    if (moveArray[8]) {
	        promotion = true;
	        switch (moveArray[8].toLowerCase()) {
	            case "r":
	                promoteTo = "rook";
	                break;
	            case "b":
	                promoteTo = "bishop";
	                break;
	            case "q":
	                promoteTo = "queen";
	                break;
	            case "n":
	                promoteTo = "knight";
	                break;
	            default:
	                break;
	        }
	    } else {
	        promotion = false;
	        promoteTo = '';
	    }

	    // Make piece move + animation	   

	    var castle = board.castleMove(piece, fromX, toX);
	    if (castle.castling) {
	        this.AnimateMove(piece, fromX, fromY, toX, toY, promoteTo, 0, 600);
	        this.AnimateMove(castle.piece, castle.fromX, castle.fromY, castle.toX, castle.toY, null, -1, 600);
	    } else {
	        this.AnimateMove(piece, fromX, fromY, toX, toY, promoteTo, 0, 600);
	    }
	}

    // if varLvl = -1 => no move needed
	this.AnimateMove =
    function (piece, fromX, fromY, toX, toY, promoteTo, varLvl, AnimDuration) {
        var animateFromPiece = $(boardTable).find(".piece" + fromX + fromY)[0];
        var AnimateFromSquare = this.getGUISquare(fromX, fromY);
        var posSquare = $(AnimateFromSquare).position();
        var posAnimate = $(animateFromPiece).position();
        animateFromPiece.style.left = posAnimate.left + "px";
        animateFromPiece.style.top = posAnimate.top + "px";
        var offsetX = posAnimate.left - posSquare.left;
        var offsetY = posAnimate.top - posSquare.top;
        animateFromPiece.style.position = 'absolute';
        var AnimateToPiece = this.getGUISquare(toX, toY);
        var posToAnimate = $(AnimateToPiece).position();
        
        animateFromPiece.dataPiece = piece;
        animateFromPiece.dataFromX = fromX;
        animateFromPiece.dataFromY = fromY;
        animateFromPiece.dataToX = toX;
        animateFromPiece.dataToY = toY;
        animateFromPiece.dataPromoteTo = promoteTo;
        animateFromPiece.dataVarLvl = varLvl;
        $(animateFromPiece).animate({
            "left": posToAnimate.left + offsetX,
            "top": posToAnimate.top + offsetY
        }, AnimDuration, function () {
            if (parseInt(this.dataVarLvl) == -1)
                return;
            boardWrapper.gui.makeMove(this.dataPiece, this.dataFromX, parseInt(this.dataFromY),
                        this.dataToX, parseInt(this.dataToY), this.dataPromoteTo);
        });

    }

    this.blinkPiece =
    function (square) {
        x = square.charAt(0);
        y = square.charAt(1);        
        var animateFromPiece = $(boardTable).find(".piece" + x + y)[0];
        $(animateFromPiece).blink({
            speed: 200,
            blinks: 4
        });
    }

    this.ShowActions =
	function (Actions) {
	    boardMarkers.clearMarkers();
	    var element = $(document).find("#puzzleMessage")[0];
	    if (Actions.length == 0) {
	        if (element != null) {
	            if (this.BoardDisabled)
	                element.innerHTML = lang.yourTurn;
	        }
	        return;
	    }
	    var NeedDisable = true;
	    if (this.BoardDisabled)
	        NeedDisable = false;
	    this.BoardDisabled = true;

	    if ((Actions.length > 0) && (Actions[0].charAt(0) == 'p')) {
	        if (board.currentFEN(true) == Actions[0].substr(1))
	            Actions.splice(0, 1);
	    }

	    if (Actions.length == 0) {
	        if (NeedDisable) {
	            this.BoardDisabled = false;
	        }
	        else {
	            if (element != null)
	                element.innerHTML = lang.yourTurn;
	        }
	    }

	    else {
	        $(this).everyTime(800, 'MoveTimer', function (i) {
	            if (i == Actions.length + 1) {
	                if (NeedDisable) {
	                    this.BoardDisabled = false;
	                    if (element != null)
	                        element.innerHTML = lang.yourTurn;
	                }

	                if (this.TaskFinished) {
	                    $('.task_notation .line').addClass('active').live('click', function () {
	                        loadMove($(this).attr('data-fen'), this, $(this).attr('data-move'));
	                    });
	                }
	            }
	            else
	                if (Actions[i - 1] != undefined)
	                    switch (Actions[i - 1].charAt(0)) {
	                    case "p":
	                        {
	                            board.loadFEN(Actions[i - 1].substr(1));
	                            boardWrapper.gui.drawBoardPosition();
	                            break;
	                        }
	                    case "m":
	                        {
	                            if (element != null && !$(element).hasClass('solved')) {
	                                element.innerHTML = '<span class="ajaxload right">' + lang.animating + '</span>';
	                            }
	                            boardWrapper.gui.parseMove(Actions[i - 1].substr(1), 0);
	                            break;
	                        }
	                    case "b":
	                        {
	                            boardWrapper.gui.blinkPiece(Actions[i - 1].substr(1));
	                            break;
	                        }
	                    case "x":
	                        {
	                            boardWrapper.boardMarkers.drawMarkers(Actions[i - 1].substr(1));
	                            break;
	                        }
	                    default:
	                        {
	                            break;
	                        }
	                }
	        }, Actions.length + 1);
	    }

	}

	var firstDraw = true;

	this.drawBoardPosition =
	function () {
	    if (!firstDraw) {
	        $(boardTable).find('td').children('.piece').remove();
	    }
	    else {
	        firstDraw = false;
	    }

	    for (var i = 0; i < board.pieces.length; i++) {
	        var piece = board.pieces[i];
	        var square = piece.square;
	        if (square != undefined) {
	            var GUIsquare = this.getGUISquare(square.x, square.y);
	            var pieceImg = document.createElement("div");
	            pieceImg.className = "piece" + square.x + square.y + ' piece ' + piece.color.charAt(0) + piece.name;
	            GUIsquare.appendChild(pieceImg);
	        }
	    }

	    if (boardMarkers != null)
	        boardMarkers.clearMarkers();

	    if (board.currentMove == 'white') {
	        $(boardWrapper.blackIndicator).hide();
	        $(boardWrapper.whiteIndicator).show();
	    }
	    else {
	        $(boardWrapper.blackIndicator).show();
	        $(boardWrapper.whiteIndicator).hide();
	    }

	    if (!firstDraw || this.flipped)
	        this.drawCoordinates();
	}

	// Draws the coordinates according to this.flipped state
	this.drawCoordinates =
	function () {
	    var lttr;
	    var nmbr;
	    for (var i = 0; i < letters.length; i++) {
	        if (this.flipped) {
	            lttr = letters[7 - i];
	            nmbr = i + 1;
	        } else {
	            lttr = letters[i];
	            nmbr = 8 - i;
	        }
	        
	        var holder = boardTable.rows[0].cells[i + 1];
	        holder.innerHTML = lttr.toUpperCase();
	        holder = boardTable.rows[9].cells[i + 1];
	        holder.innerHTML = lttr.toUpperCase();
	        holder = boardTable.rows[i + 1].cells[0];
	        holder.innerHTML = nmbr;
	        holder = boardTable.rows[i + 1].cells[9];
	        holder.innerHTML = nmbr;
	    }
	}

	this.displayMove =
	function (game, board, oldid) {
	    this.drawBoardPosition(game, board);
	}

	// Returns the GUI square reference given the board coordinates;
	this.getGUISquare =
	function (x, y) {
	    if (!this.flipped) {
	        x = letter[x];
	        y = 9 - y;
	    } else {
	        x = 9 - letter[x];
	    }

        element = boardTable.rows[y].cells[x];

	    return element;
	}

	// Returns the board coordinates given the id of GUI square
	this.getSquare =
	function (className) {
	    var startIndex;
	    if (className.match(/piece/)) {
	        startIndex = className.indexOf('piece');
	        return { x: className.charAt(startIndex + 5), y: className.charAt(startIndex + 6) };
	    }
	    startIndex = className.indexOf("square");
	    if (!this.flipped) {
	        x = letters[className.charAt(startIndex + 6) - 1];
	        y = 9 - className.charAt(startIndex + 7);
	    } else {
	        x = letters[8 - className.charAt(startIndex + 6)];
	        y = className.charAt(startIndex + 7);
	    }
	    return { x: x, y: y };
	}
}

function PlayController(aType,aBoard,aGUI,aCounter,aTaskID,aUrl){var board=aBoard;var gui=aGUI;var Counter=aCounter;var TaskID=aTaskID;var TaskFinished=false;var Type=aType;var attemps=0;var curRight=0;var curWrong=0;var askedMoves=1;this.MoveMade=function(aMove){if(Type=="ChessTask"){var Result=false;var Actions=[];$.ajax({type:"Post",url:aUrl,async:false,dataType:"json",data:{Move:aMove,CurCounter:Counter,CurTaskID:TaskID,CurAttemps:attemps,CurRight:curRight,CurWrong:curWrong,AskedMoves:askedMoves},success:function(msg,status){Result=msg.Result;if(Result){curRight++;}else{curWrong++;}Actions=msg.Actions;attemps=msg.curAttemps;if(Counter!=msg.Counter){Counter=msg.Counter;askedMoves++;}gui.BoardDisabled=msg.IsFinished;TaskFinished=msg.IsFinished;gui.ShowActions(Actions);var textMessage;var element=$(document).find("#puzzleMessage")[0];if(!msg.IsFinished){if(Result){if(element!=null){element.className="correct";}textMessage="Right move!";}else{if(element!=null){element.className="incorrect";}textMessage="Incorrect move";}}else{if(msg.IsSolved){textMessage='<span class="accept_icon">Problem solved ('+msg.Score+")</span>";}else{textMessage='<span class="cancel_icon">Not solved ('+msg.Score+")</span>";}if(element!=null){element.className="solved";}$(".next_practice").show();}if(element!=null){element.innerHTML=textMessage;}},error:function(jqXHR,textStatus,errorThrown){alert(errorThrown);var element=$(document).find("#puzzleMessage")[0];element.innerHTML="Internal server error.";}});return Result;}else{return true;}};}

function getPosition(e){var p=$(e).offset();return{x:p.left,y:p.top};}function mouseCoords(ev){if(ev.pageX||ev.pageY){return{x:ev.pageX,y:ev.pageY};}var body=document.body;return{x:ev.clientX+body.scrollLeft-body.clientLeft,y:ev.clientY+body.scrollTop-body.clientTop};}function getMouseOffset(size){return{x:Math.floor(size/2),y:Math.floor(size/2)};}function MouseHandler(brdWrapper){this.dragObject=null;this.mouseOffset=null;var conSq=[];this.dropTargets=[];var promData;var promoting=false;var board=brdWrapper.board;var gui=brdWrapper.gui;var boardPosition=null;this.controlledSquares=function(fromX,fromY){var result=[];piece=brdWrapper.board.squares[fromX][fromY].piece;if(piece!=undefined&&piece.color==board.currentMove){result=eval("brdWrapper.rules."+piece.name+'("'+fromX+'", '+fromY+', "'+piece.color+'")');}return result;};this.makeMoveable=function(item){$(item).mousemove(brdWrapper,function(ev){if(!brdWrapper.mouseHandler.dragObject){return true;}var handler=brdWrapper.mouseHandler,mousePos=mouseCoords(ev),st=handler.dragObject.style,moOf=handler.mouseOffset;st.top=(mousePos.y-boardPosition.top-moOf.y)+"px";st.left=(mousePos.x-boardPosition.left-moOf.x)+"px";return true;});};this.addDropTarget=function(dropTarget){this.dropTargets.push(dropTarget);};var letters=["a","b","c","d","e","f","g","h"];var letter=[];letter.a=1;letter.b=2;letter.c=3;letter.d=4;letter.e=5;letter.f=6;letter.g=7;letter.h=8;function truncate(n){return Math.round(n-0.5);}this.mouseDown=function(ev){var gui=brdWrapper.gui;if(gui.BoardDisabled){return false;}if(brdWrapper.visibleCols!=8||brdWrapper.visibleRows!=8){return false;}var handler=brdWrapper.mouseHandler;var mousePos=mouseCoords(ev);var brd=brdWrapper.boardTable;boardPosition=$(brd.rows[0].cells[0]).offset();var sq=brd.rows[1].cells[1];var pos=$(sq).offset();var xpos=Math.abs(truncate((mousePos.x-pos.left)/brdWrapper.squareSize))+1;var ypos=truncate((mousePos.y-pos.top)/brdWrapper.squareSize)+1;if(xpos<1||xpos>8||ypos<1||ypos>8){return false;}var obj=brd.rows[ypos].cells[xpos].children[0];if(obj){var tempSq;var boardPos=gui.getSquare("square"+xpos+ypos);conSq=handler.controlledSquares(boardPos.x,boardPos.y);if(conSq&&conSq.length>0){for(var i=0;i<conSq.length;i++){tempSq=gui.getGUISquare(conSq[i].charAt(0),conSq[i].charAt(1));tempSq.className+=" controlled";handler.dropTargets.push(tempSq);}}else{return false;}handler.mouseOffset=getMouseOffset(brdWrapper.squareSize);var mousePos=mouseCoords(ev);obj.style.position="absolute";obj.style.top=(mousePos.y-boardPosition.top-handler.mouseOffset.y)+"px";obj.style.left=(mousePos.x-boardPosition.left-handler.mouseOffset.x)+"px";handler.dragObject=obj;return false;}};this.mouseUp=function(item){$(item).mouseup(brdWrapper,function(ev){if(brdWrapper.mouseHandler.dragObject==null){return true;}var handler=brdWrapper.mouseHandler;var gui=brdWrapper.gui;var board=brdWrapper.board;var PlayController=brdWrapper.playController;var mousePos=mouseCoords(ev);var promoting=false;for(var i=0;i<handler.dropTargets.length;i++){var curTarget=handler.dropTargets[i];var targPos=getPosition(curTarget);var targWidth=parseInt(curTarget.clientWidth);var targHeight=parseInt(curTarget.clientHeight);var Board=brdWrapper.boardTable;var boardPos=getPosition(Board);if((mousePos.x>targPos.x)&&(mousePos.x<(targPos.x+targWidth))&&(mousePos.y>targPos.y)&&(mousePos.y<(targPos.y+targHeight))){var coords=gui.getSquare(brdWrapper.mouseHandler.dragObject.className);var piece=board.squares[coords.x][coords.y].piece;var square=piece.square;var oldSquare=gui.getGUISquare(square.x,square.y);var curCoords=gui.getSquare(curTarget.className);var currSquare=gui.getGUISquare(curCoords.x,curCoords.y);if(piece.name=="pawn"&&(curCoords.y==1||curCoords.y==8)){var promBox=brdWrapper.promotionView;$(promBox).data("move","p"+square.x+square.y+curCoords.x+curCoords.y);var pieceNames=["queen","rook","bishop","knight"];for(var i in pieceNames){var name=pieceNames[i];$(promBox).find("."+name)[0].className=name+" piece "+brdWrapper.board.currentMove.charAt(0)+name;}brdWrapper.gui.BoardDisabled=true;promBox.style.position="absolute";$(promBox).css("left",$(Board).width()/2-$(promBox).width()/2+"px");$(promBox).css("top",$(Board).height()/2-$(promBox).height()/2+"px");$(promBox).fadeIn();promoting=true;$(oldSquare).children().remove();$(currSquare).append(brdWrapper.mouseHandler.dragObject);brdWrapper.mouseHandler.dragObject.style.position="static";}else{var c=piece.name.charAt(0).toLowerCase();if(piece.name=="knight"){c="n";}if(PlayController.MoveMade(c+square.x+square.y+curCoords.x+curCoords.y)){board.moveHandler(piece.name,square.x,square.y,curCoords.x,curCoords.y,true,null,null,0);gui.drawBoardPosition(board);brdWrapper.mouseHandler.dragObject.style.position="static";brdWrapper.mouseHandler.dragObject=null;}break;}}}if(!promoting&&brdWrapper.mouseHandler.dragObject){brdWrapper.mouseHandler.dragObject.style.position="static";}brdWrapper.mouseHandler.dropTargets=[];for(var j=0;j<conSq.length;j++){var tempSq=gui.getGUISquare(conSq[j].charAt(0),conSq[j].charAt(1));$(tempSq).removeClass("controlled");}conSq=[];brdWrapper.mouseHandler.dragObject=null;return true;});};}

var boardController = new BoardController();

var lastBoardId = 1;

var en_chessBoardLang = {
    flipBoard: 'Flip board',
    checkingMove: 'Checking move...',
    correctMove: 'Right move!',
    incorrectMove: 'Incorrect move',
    problemSolved: 'Problem solved',
    problemUnsolved: 'Not solved',
    internalServerError: 'Internal server error.',
    yourTurn: "It's your turn",
    animating: 'Animating...',
    eloChange: 'Your new ELO rating is',
    eloNotChanged: 'Your ELO rating stay unchanged.'
};

var ru_chessBoardLang = {
    flipBoard: 'Перевернуть доску',
    checkingMove: 'Проверяем ход...',
    correctMove: 'Правильно!',
    incorrectMove: 'Неверный ход',
    problemSolved: 'Задача решена',
    problemUnsolved: 'Задача не решена',
    internalServerError: 'Ошибка сервера.',
    yourTurn: "Ваш ход",
    animating: 'Разыгрывание...',
    eloChange: 'Ваш рейтинг: ',
    eloNotChanged: 'Ваш ЭЛО рейтинг не изменился: Вы уже решали данную задачу.',
    UserIsCheater: 'Ваш Эло рейтинг не изменился, т.к. Вы нечестно решали данную задачу. Порешайте другие задачи, а после вернитесь к этой.'
};

var chessBoardLang = ru_chessBoardLang;

function TransformBoards(parentElement) {
    var letters = ["a", "b", "c", "d", "e", "f", "g", "h"];
    var letter = [];
    letter["a"] = 1;
    letter["b"] = 2;
    letter["c"] = 3;
    letter["d"] = 4;
    letter["e"] = 5;
    letter["f"] = 6;
    letter["g"] = 7;
    letter["h"] = 8;
    
    var tableViewElement = null;

    $(parentElement).find(".chessBoard").each(function (index, brdWrapper) {
        if (brdWrapper.boardTransformed) {
            return;
        }

        brdWrapper.boardTransformed = true;
        var Actions = [];

        brdWrapper.id = "ChessBoard" + lastBoardId++;
        if (brdWrapper.className.indexOf('small') == -1) {
            brdWrapper.squareSize = 50;
        }
        else {
            brdWrapper.squareSize = 27;
        }

        var lang = chessBoardLang;

        $(brdWrapper).find('.data-chessActions span').each(function (index, node) {
            Actions.push(node.innerHTML);
        }).html("");

        if (tableViewElement == null) {
            tableViewElement = document.createElement('div');
            tableViewElement.className = 'tableView';

            var boardElement = document.createElement("table");
            boardElement.className = "game_board";
            boardTable_innerHTML = '';
            boardTable_innerHTML += '<tr class="row8"><td class="corner cola"></td><td class="lettertop topa cola">A</td><td class="lettertop topb colb">B</td><td class="lettertop topc colc">C</td><td class="lettertop topd cold">D</td><td class="lettertop tope cole">E</td><td class="lettertop topf colf">F</td><td class="lettertop topg colg">G</td><td class="lettertop toph colh">H</td><td class="corner colh"><div class="indicator black"></div></td></tr>';
            boardTable_innerHTML += '<tr class="row8"><td class="numberleft left8 cola">8</td><td class="white square11 cola"></td><td class="black square21 colb"></td><td class="white square31 colc"></td><td class="black square41 cold"></td><td class="white square51 cole"></td><td class="black square61 colf"></td><td class="white square71 colg"></td><td class="black square81 colh"></td><td class="numberright right8 colh">8</td></tr>';
            boardTable_innerHTML += '<tr class="row7"><td class="numberleft left7 cola">7</td><td class="black square12 cola"></td><td class="white square22 colb"></td><td class="black square32 colc"></td><td class="white square42 cold"></td><td class="black square52 cole"></td><td class="white square62 colf"></td><td class="black square72 colg"></td><td class="white square82 colh"></td><td class="numberright right7 colh">7</td></tr>';
            boardTable_innerHTML += '<tr class="row6"><td class="numberleft left6 cola">6</td><td class="white square13 cola"></td><td class="black square23 colb"></td><td class="white square33 colc"></td><td class="black square43 cold"></td><td class="white square53 cole"></td><td class="black square63 colf"></td><td class="white square73 colg"></td><td class="black square83 colh"></td><td class="numberright right6 colh">6</td></tr>';
            boardTable_innerHTML += '<tr class="row5"><td class="numberleft left5 cola">5</td><td class="black square14 cola"></td><td class="white square24 colb"></td><td class="black square34 colc"></td><td class="white square44 cold"></td><td class="black square54 cole"></td><td class="white square64 colf"></td><td class="black square74 colg"></td><td class="white square84 colh"></td><td class="numberright right5 colh">5</td></tr>';
            boardTable_innerHTML += '<tr class="row4"><td class="numberleft left4 cola">4</td><td class="white square15 cola"></td><td class="black square25 colb"></td><td class="white square35 colc"></td><td class="black square45 cold"></td><td class="white square55 cole"></td><td class="black square65 colf"></td><td class="white square75 colg"></td><td class="black square85 colh"></td><td class="numberright right4 colh">4</td></tr>';
            boardTable_innerHTML += '<tr class="row3"><td class="numberleft left3 cola">3</td><td class="black square16 cola"></td><td class="white square26 colb"></td><td class="black square36 colc"></td><td class="white square46 cold"></td><td class="black square56 cole"></td><td class="white square66 colf"></td><td class="black square76 colg"></td><td class="white square86 colh"></td><td class="numberright right3 colh">3</td></tr>';
            boardTable_innerHTML += '<tr class="row2"><td class="numberleft left2 cola">2</td><td class="white square17 cola"></td><td class="black square27 colb"></td><td class="white square37 colc"></td><td class="black square47 cold"></td><td class="white square57 cole"></td><td class="black square67 colf"></td><td class="white square77 colg"></td><td class="black square87 colh"></td><td class="numberright right2 colh">2</td></tr>';
            boardTable_innerHTML += '<tr class="row1"><td class="numberleft left1 cola">1</td><td class="black square18 cola"></td><td class="white square28 colb"></td><td class="black square38 colc"></td><td class="white square48 cold"></td><td class="black square58 cole"></td><td class="white square68 colf"></td><td class="black square78 colg"></td><td class="white square88 colh"></td><td class="numberright right1 colh">1</td></tr>';
            boardTable_innerHTML += '<tr class="row1"><td class="corner cola"><div class="flipicon" title="' + chessBoardLang.flipBoard + '"></div></td><td class="letterbottom bottoma cola">A</td><td class="letterbottom bottomb colb">B</td><td class="letterbottom bottomc colc">C</td><td class="letterbottom bottomd cold">D</td><td class="letterbottom bottome cole">E</td><td class="letterbottom bottomf colf">F</td><td class="letterbottom bottomg colg">G</td><td class="letterbottom bottomh colh">H</td>';
            boardTable_innerHTML += '<td class="corner colh"><div class="indicator white"></div></td></tr>';
            $(boardElement).html(boardTable_innerHTML);

            var markersElement = document.createElement('div');
            markersElement.className = 'markersView';

            var promotionElement = document.createElement('div');
            promotionElement.className = 'promotion';
            promotionElement.innerHTML =
                  "<div onclick=\"promoteTo('queen', this)\" class='queen piece bqueen'></div>"
                + "<div onclick=\"promoteTo('rook', this)\" class='rook piece brook'></div>"
                + "<div onclick=\"promoteTo('bishop', this)\" class='bishop piece bbishop'></div>"
                + "<div onclick=\"promoteTo('knight', this)\" class='knight piece bknight'></div>";

            var buttonsElement = document.createElement('div');
            buttonsElement.className = 'board_buttons';
            buttonsElement.innerHTML =
                  "<div onclick=\"goToStartPosition(this)\" class='button_start'></div>"
                + "<div class='button_left'></div>"
                + "<div class='button_right'></div>"
                + "<div onclick=\"goToFinishPosition(this)\" class='button_end'></div>";
            

            tableViewElement.appendChild(boardElement);
            tableViewElement.appendChild(markersElement);
            tableViewElement.appendChild(promotionElement);
            tableViewElement.appendChild(buttonsElement);
        }

        var tableView = tableViewElement.cloneNode(true);
        brdWrapper.boardTable = tableView.children[0];
        brdWrapper.markersView = tableView.children[1];
        brdWrapper.promotionView = tableView.children[2];

        brdWrapper.blackIndicator = $(brdWrapper.boardTable).find('.indicator.black')[0];
        brdWrapper.whiteIndicator = $(brdWrapper.boardTable).find('.indicator.white')[0];

        $(".flipicon", brdWrapper.boardTable).click(function () {
            boardController.flipBoard(brdWrapper.id);
        });

        boardRect = $(brdWrapper).data('rect');
        brdWrapper.isBoardrect = (boardRect != null && boardRect != '');
        brdWrapper.visibleCols = 8;
        brdWrapper.visibleRows = 8;
        if (brdWrapper.isBoardrect) {
            fromX = boardRect.charAt(0); // Левый столбец
            toX = boardRect.charAt(3);   // Правый столбец
            fromY = parseInt(boardRect.charAt(1)); // Нижняя строка
            toY = parseInt(boardRect.charAt(4));   // Верхняя строка

            brdWrapper.startX = fromX;
            brdWrapper.startY = fromY;
            brdWrapper.finishX = toX;
            brdWrapper.finishY = toY;
            brdWrapper.visibleCols = letter[toX] - letter[fromX] + 1;
            brdWrapper.visibleRows = toY - fromY + 1;

            // Скрыть столбцы слева
            for (var i = letter['a']; i < letter[fromX]; i++) {
                $(brdWrapper.boardTable).find('td.col' + letters[i - 1]).hide();
            }

            // Скрыть строки сверху
            for (var i = toY + 1; i <= 8; i++) {
                $(brdWrapper.boardTable).find('tr.row' + i).hide();
            }

            // Скрыть строки снизу
            for (var i = 1; i < fromY; i++) {
                $(brdWrapper.boardTable).find('tr.row' + i).hide();
            }

            // Скрыть столбцы справа
            for (var i = letter[toX] + 1; i <= letter['h']; i++) {
                $(brdWrapper.boardTable).find('td.col' + letters[i - 1]).hide();
            }
        }

        if ($(brdWrapper).data('start-fen') == null) {
            $(brdWrapper).data('start-fen', 'rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1');
        }

        if ($(brdWrapper).data('type') == null) {
            $(brdWrapper).data('type', 'play');
        }

        brdWrapper.board = new chessBoard();
        brdWrapper.rules = new chessRules(brdWrapper.board);
        brdWrapper.boardMarkers = new BoardMarkers(brdWrapper);
        brdWrapper.gui = new GUI(brdWrapper);

        brdWrapper.gui.BoardDisabled = ($(brdWrapper).data('enabled') != null) && ($(brdWrapper).attr('data-enabled') == 'false') && brdWrapperisBoardrect;


        brdWrapper.playController = new PlayController(brdWrapper);

        brdWrapper.board.loadFEN($(brdWrapper).data('start-fen'));
        var needInvert = $(brdWrapper).data('board-inverted');
        if (needInvert != null) {
            brdWrapper.gui.flipped = needInvert == "True";
            if (brdWrapper.gui.flipped == true) {
                $(brdWrapper.whiteIndicator).addClass('black');
                $(brdWrapper.whiteIndicator).removeClass('white');
                $(brdWrapper.blackIndicator).removeClass('black');
                $(brdWrapper.blackIndicator).addClass('white');

                var temp = brdWrapper.whiteIndicator;
                brdWrapper.whiteIndicator = brdWrapper.blackIndicator;
                brdWrapper.blackIndicator = temp;
            }
        }
        brdWrapper.gui.drawBoardPosition();

        if ($(brdWrapper).data('type') == 'ChessTask') {
            brdWrapper.gui.notation = $(document).find('.task_notation')[0];
            brdWrapper.gui.addNotaMove('[...]', brdWrapper.board.currentFEN());
        }

        var startMarkers = $(brdWrapper).data('markers');

        if (Actions.length > 0)
            brdWrapper.gui.ShowActions(Actions);
        if (startMarkers != null && startMarkers != '')
            brdWrapper.boardMarkers.drawMarkers(startMarkers);
        brdWrapper.appendChild(tableView);

        if (!brdWrapper.isBoardrect) {
            brdWrapper.mouseHandler = new MouseHandler(brdWrapper);
            $(brdWrapper).mousedown(brdWrapper, brdWrapper.mouseHandler.mouseDown);
            brdWrapper.mouseHandler.makeMoveable(brdWrapper);
            brdWrapper.mouseHandler.mouseUp(brdWrapper);
        }
    });
}

$(document).ready(function () {
    TransformBoards(document);
    $('.button_right').mousehold(function(i) {
        goToNextPosition(this);
    });
    $('.button_left').mousehold(function(i) {
        goToPrevPosition(this);
    });
});
}
