// (c)2008-2009 SudokuPoint all rights reserved - Any duplication or use outside SudokuPoint.com is explicitly forbidden

var fontImg=new Image();var annoFontImg=new Image();var regularFontImg=new Image();var fontLoaded=false;var pageLoaded=false;var annoFontLoaded=false;var regularFontLoaded=false;var gameFinished=false;var gameStarted=false;var currentSavedGame=null;var justSaved=false;fontImg.onload=function(){fontLoaded=true;load();annoFontImg.src='/res/annofont.png';regularFontImg.src='/res/regfont.png';}
annoFontImg.onload=function(){annoFontLoaded=true;}
regularFontImg.onload=function(){regularFontLoaded=true;}
fontImg.src='/res/font.png';var userData=[["","","","","","","","",""],["","","","","","","","",""],["","","","","","","","",""],["","","","","","","","",""],["","","","","","","","",""],["","","","","","","","",""],["","","","","","","","",""],["","","","","","","","",""],["","","","","","","","",""]];var fontData=[[5,0],[8,5],[10,13],[14,23],[18,37],[22,55],[26,77],[35,103],[43,138],[51,181]];var panelSize;var cellSize;var boardWidth;var boardHeight;var offsetX;var offsetY;var fontSize;var fontImageOffset;var fontOffset;var annotationFontSize;var annotationFontImageOffset;var annotationFontOffset;var numberPanelHeight=-1;var panelTargetRow=-1;var panelTargetColumn=-1;function load(){if(!pageLoaded||!fontLoaded)return;var targetCanvas=document.getElementById("game");if(document.all){targetCanvas.attachEvent("onmousedown",mouseDown);}else{targetCanvas.addEventListener("mousedown",mouseDown,false);}
resizeApp();setTimeout("repaint()",0);}
function confirmExit(){if((gameStarted)&&(!gameFinished)&&(!justSaved)){return"It seems that your game is in progress, and you haven't saved it. If you exit now, your game will be lost.";}}
function findPos(obj){var curleft=0;var curtop=0;if(obj.offsetParent){curleft=obj.offsetLeft;curtop=obj.offsetTop;while(obj.offsetParent){obj=obj.offsetParent;curleft+=obj.offsetLeft;curtop+=obj.offsetTop;}}
return{x:curleft,y:curtop};}
function setPanelPos(panel,topPos,leftPos){if(topPos>(getWindowHeight()-panel.offsetHeight-1)){topPos=getWindowHeight()-panel.offsetHeight-1;}
if(leftPos>(getWindowWidth()-panel.offsetWidth-1)){leftPos=getWindowWidth()-panel.offsetWidth-1;}
if(topPos<0){topPos=0;}
if(leftPos<0){leftPos=0;}
panel.style.left=""+leftPos+"px";panel.style.top=""+topPos+"px";}
function mouseDown(e){var canvas=document.getElementById("game");var canvasPos=findPos(canvas);var targetX=e.clientX-canvasPos.x;var targetY=e.clientY-canvasPos.y;var currentX=targetX-offsetX;var currentCellCol=-1;if(currentX>0){currentCellCol=0;while(currentX>cellSize){currentX-=cellSize+1;if((currentCellCol+1)%3==0)currentX--;currentCellCol++;}}
var currentY=targetY-offsetY;var currentCellRow=-1;if(currentY>0){currentCellRow=0;while(currentY>cellSize){currentY-=cellSize+1;if((currentCellRow+1)%3==0)currentY--;currentCellRow++;}}
var panel=document.getElementById("numberPanel");if((currentCellRow<0)||(currentCellCol<0)||(currentCellRow>=userData.length)||(currentCellCol>=userData[0].length)){panel.style.visibility="hidden";panel.style.top="0px";panel.style.left="0px";return;}
var selectedAnnotationNumber=false;if((userData[currentCellRow][currentCellCol].length>0)&&(userData[currentCellRow][currentCellCol].charAt(0)=='*')&&(annotationFontSize!=fontSize)){var annotationMarginX=Math.floor((cellSize/2-annotationFontSize)/2+annotationFontSize/6);var annotationMarginY=Math.floor((cellSize/2-annotationFontSize)/2);if((currentY>annotationMarginY)&&(currentY<(cellSize/2-annotationMarginY))){if((currentX>annotationMarginX)&&(currentX<(cellSize/2-annotationMarginX))){if(userData[currentCellRow][currentCellCol].length>1){userData[currentCellRow][currentCellCol]=userData[currentCellRow][currentCellCol].charAt(1);selectedAnnotationNumber=true;}}else if((currentX<(cellSize-annotationMarginX))&&(currentX>(cellSize/2+annotationMarginX))){if(userData[currentCellRow][currentCellCol].length>2){userData[currentCellRow][currentCellCol]=userData[currentCellRow][currentCellCol].charAt(2);selectedAnnotationNumber=true;}}}else if((currentY<(cellSize-annotationMarginY))&&(currentY>(cellSize/2+annotationMarginY))){if((currentX>annotationMarginX)&&(currentX<(cellSize/2-annotationMarginX))){if(userData[currentCellRow][currentCellCol].length>3){userData[currentCellRow][currentCellCol]=userData[currentCellRow][currentCellCol].charAt(3);selectedAnnotationNumber=true;}}else if((currentX<(cellSize-annotationMarginX))&&(currentX>(cellSize/2+annotationMarginX))){if(userData[currentCellRow][currentCellCol].length>4){userData[currentCellRow][currentCellCol]=userData[currentCellRow][currentCellCol].charAt(4);selectedAnnotationNumber=true;}}}}
if(!selectedAnnotationNumber){if((currentCellRow>=0)&&(currentCellCol>=0)&&(currentCellRow<sudokuData.length)&&(currentCellCol<sudokuData[0].length)&&(sudokuData[currentCellRow][currentCellCol]==0)){panelTargetRow=currentCellRow;panelTargetColumn=currentCellCol;if(numberPanelHeight<0){numberPanelHeight=panel.offsetHeight;document.getElementById("checkboxAnnotationRow").style.display="";}
if(userData[currentCellRow][currentCellCol]==0){document.getElementById("buttonClearRow").style.display="none";}else{document.getElementById("buttonClearRow").style.display="";}
for(var c=1;c<=9;c++){if(userData[currentCellRow][currentCellCol].indexOf(c)>-1){document.getElementById("button"+c).className="numberSelected";}else{document.getElementById("button"+c).className="";}}
if((userData[currentCellRow][currentCellCol].length>0)&&(userData[currentCellRow][currentCellCol].charAt(0)=='*')){document.getElementById("checkboxAnnotation").checked=true;document.getElementById("buttonCloseRow").style.display="";}else{document.getElementById("checkboxAnnotation").checked=false;document.getElementById("buttonCloseRow").style.display="none";}
var panelLeftPos=canvasPos.x+offsetX+2+(cellSize+1)*currentCellCol+Math.floor(currentCellCol/3)+Math.floor(cellSize/2)-Math.floor(panel.offsetWidth/2);var panelTopPos=canvasPos.y+offsetY+2+(cellSize+1)*currentCellRow+Math.floor(currentCellRow/3)+Math.floor(cellSize/2)-Math.floor(numberPanelHeight/2);setPanelPos(panel,panelTopPos,panelLeftPos);panel.style.visibility="visible";}else{panel.style.visibility="hidden";panel.style.top="0px";panel.style.left="0px";}}else{panel.style.visibility="hidden";panel.style.top="0px";panel.style.left="0px";var canvas=document.getElementById("game");if(canvas.getContext){var ctx=canvas.getContext("2d");drawCell(ctx,currentCellRow,currentCellCol,true);}
checkGameEnd();}}
function getWindowHeight(){if(window.self&&self.innerHeight){return self.innerHeight;}
if(document.documentElement&&document.documentElement.clientHeight){return document.documentElement.clientHeight;}
return document.body.clientHeight;}
function getWindowWidth(){if(window.self&&self.innerWidth){return self.innerWidth;}
if(document.documentElement&&document.documentElement.clientWidth){return document.documentElement.clientWidth;}
return document.body.clientWidth;}
function buttonClick(targetNumber){var isAnnotation=false;gameStarted=true;justSaved=false;checkButtons();if((userData[panelTargetRow][panelTargetColumn].length>0)&&(userData[panelTargetRow][panelTargetColumn].charAt(0)=='*')){isAnnotation=true;}
if(targetNumber==0){if(isAnnotation){for(var c=1;c<userData[panelTargetRow][panelTargetColumn].length;c++){document.getElementById("button"+userData[panelTargetRow][panelTargetColumn].charAt(c)).className="";}
userData[panelTargetRow][panelTargetColumn]="*";}else{document.getElementById("button"+userData[panelTargetRow][panelTargetColumn]).className="";userData[panelTargetRow][panelTargetColumn]="";}
document.getElementById("buttonClearRow").style.display="none";}else{if(isAnnotation){if(userData[panelTargetRow][panelTargetColumn].indexOf(targetNumber)<0){if(userData[panelTargetRow][panelTargetColumn].length<5){userData[panelTargetRow][panelTargetColumn]=userData[panelTargetRow][panelTargetColumn]+targetNumber;}else{document.getElementById("button"+userData[panelTargetRow][panelTargetColumn].charAt(1)).className="";userData[panelTargetRow][panelTargetColumn]="*"+userData[panelTargetRow][panelTargetColumn].substr(2)+targetNumber;}
document.getElementById("button"+targetNumber).className="numberSelected";document.getElementById("buttonClearRow").style.display="";var panel=document.getElementById("numberPanel");var panelPos=findPos(panel);setPanelPos(panel,panelPos.y,panelPos.x);}else{var partsArray=userData[panelTargetRow][panelTargetColumn].split(targetNumber);userData[panelTargetRow][panelTargetColumn]="";for(var c=0;c<partsArray.length;c++){userData[panelTargetRow][panelTargetColumn]+=partsArray[c];}
document.getElementById("button"+targetNumber).className="";if(userData[panelTargetRow][panelTargetColumn].length<=1){document.getElementById("buttonClearRow").style.display="none";}}}else{userData[panelTargetRow][panelTargetColumn]=""+targetNumber;}}
var canvas=document.getElementById("game");if(canvas.getContext){var ctx=canvas.getContext("2d");drawCell(ctx,panelTargetRow,panelTargetColumn,true);}
if(!isAnnotation){var panel=document.getElementById("numberPanel");panel.style.visibility="hidden";panel.style.top="0px";panel.style.left="0px";checkGameEnd();}}
function annotationCheckboxClick(){if(document.getElementById("checkboxAnnotation").checked){userData[panelTargetRow][panelTargetColumn]="*"+userData[panelTargetRow][panelTargetColumn];document.getElementById("buttonCloseRow").style.display="";var panel=document.getElementById("numberPanel");var panelPos=findPos(panel);setPanelPos(panel,panelPos.y,panelPos.x);}else{if(userData[panelTargetRow][panelTargetColumn].length>1){if(userData[panelTargetRow][panelTargetColumn].length>2){for(var c=2;c<userData[panelTargetRow][panelTargetColumn].length;c++){document.getElementById("button"+userData[panelTargetRow][panelTargetColumn].charAt(c)).className="";}}
userData[panelTargetRow][panelTargetColumn]=userData[panelTargetRow][panelTargetColumn].charAt(1);}else{userData[panelTargetRow][panelTargetColumn]="";}
document.getElementById("buttonCloseRow").style.display="none";}
var canvas=document.getElementById("game");if(canvas.getContext){var ctx=canvas.getContext("2d");drawCell(ctx,panelTargetRow,panelTargetColumn,true);}}
function closePanel(){var panel=document.getElementById("numberPanel");panel.style.visibility="hidden";panel.style.top="0px";panel.style.left="0px";}
function resizeApp(){var offsetTop=0;var offsetLeft=0;var mapElem=document.getElementById("game");for(var elem=mapElem;elem!=null;elem=elem.offsetParent){offsetTop+=elem.offsetTop;offsetLeft+=elem.offsetLeft;}
var height=getWindowHeight()-offsetTop;height-=32;if(height<50){height=50;}
mapElem.style.height=height+"px";mapElem.setAttribute("height",height);var width=getWindowWidth()-offsetLeft;if(width<50){width=50;}
mapElem.setAttribute("width",width);var panel=document.getElementById("numberPanel");panel.style.visibility="hidden";panel.style.top="0px";panel.style.left="0px";}
function drawAnnotationOnCell(numbers,fillStyle,cellX,cellY,ctx){if(!annoFontLoaded){window.setTimeout(drawAnnotationOnCell,100,numbers,fillStyle,cellX,cellY,ctx);return;}
var canvasX=offsetX+1+cellX*cellSize+cellX+Math.floor(cellX/3);var canvasY=offsetY+1+cellY*cellSize+cellY+Math.floor(cellY/3);if(fillStyle!=""){ctx.fillStyle=fillStyle;ctx.fillRect(canvasX,canvasY,cellSize,cellSize);}
if(numbers.length>0){if(annotationFontSize>0){if(annotationFontSize==fontSize){var number=parseInt(numbers.charAt(0));if(number>0){ctx.drawImage(annoFontImg,fontSize*(number-1),fontImageOffset,fontSize,fontSize,canvasX+fontOffset,canvasY+fontOffset,fontSize,fontSize);}}else{for(var c=0;c<numbers.length;c++){var number=parseInt(numbers.charAt(c));var annotationOffsetX;var annotationOffsetY;switch(c)
{case 0:annotationOffsetX=0;annotationOffsetY=0;break;case 1:annotationOffsetX=Math.round(cellSize/2);annotationOffsetY=0;break;case 2:annotationOffsetX=0;annotationOffsetY=Math.round(cellSize/2);break;case 3:annotationOffsetX=Math.round(cellSize/2);annotationOffsetY=annotationOffsetX;break;}
ctx.drawImage(annoFontImg,annotationFontSize*(number-1),annotationFontImageOffset,annotationFontSize,annotationFontSize,canvasX+annotationFontOffset+annotationOffsetX,canvasY+annotationFontOffset+annotationOffsetY,annotationFontSize,annotationFontSize);}}}}}
function drawNumberOnCell(number,targetImg,fillStyle,cellX,cellY,ctx){var canvasX=offsetX+1+cellX*cellSize+cellX+Math.floor(cellX/3);var canvasY=offsetY+1+cellY*cellSize+cellY+Math.floor(cellY/3);if(fillStyle!=""){ctx.fillStyle=fillStyle;ctx.fillRect(canvasX,canvasY,cellSize,cellSize);}
if((number>0)&&(fontSize>0)){ctx.drawImage(targetImg,fontSize*(number-1),fontImageOffset,fontSize,fontSize,canvasX+fontOffset,canvasY+fontOffset,fontSize,fontSize);}}
function drawCell(ctx,row,column,update){if(sudokuData[row][column]>0){drawNumberOnCell(sudokuData[row][column],fontImg,"rgb(230,230,230)",column,row,ctx);}else{var fillStyle="";if(update){fillStyle="rgb(255,255,255)";}
if((userData[row][column].length>0)&&(userData[row][column].charAt(0)=='*')){drawAnnotationOnCell(userData[row][column].substr(1),fillStyle,column,row,ctx);}else if(!regularFontLoaded){window.setTimeout(drawCell,100,ctx,row,column,update);}else{drawNumberOnCell(parseInt(userData[row][column]),regularFontImg,fillStyle,column,row,ctx);}}}
function getBestFontSizeFor(targetSize){var newFontSize=0;var newFontImageOffset=-1;var newFontOffset=-1;if(cellSize<(fontData[0][0])){newFontSize=0;}else{var targetFont=0;while((targetFont<fontData.length)&&(targetSize>(fontData[targetFont][0]+2*targetFont))){newFontSize=fontData[targetFont][0];newFontImageOffset=fontData[targetFont][1];targetFont++;}
newFontOffset=Math.floor((targetSize-newFontSize)/2);}
return{fontSize:newFontSize,fontImageOffset:newFontImageOffset,fontOffset:newFontOffset};}
function repaint(){var canvas=document.getElementById("game");if(canvas.getContext){var ctx=canvas.getContext("2d");boardWidth=parseInt(canvas.getAttribute("width"));boardHeight=parseInt(canvas.getAttribute("height"));ctx.fillStyle="rgb(255,255,255)";ctx.fillRect(0,0,boardWidth,boardHeight);var newPanelSize;if(boardWidth>boardHeight){newPanelSize=boardHeight;}else{newPanelSize=boardWidth;}
if(newPanelSize>screen.width/2){newPanelSize=Math.floor(screen.width/2);}
if(newPanelSize>screen.height/2){newPanelSize=Math.floor(screen.height/2);}
cellSize=Math.floor((newPanelSize-2-2*4-6)/9);var newFontSize=getBestFontSizeFor(cellSize);fontSize=newFontSize.fontSize;fontImageOffset=newFontSize.fontImageOffset;fontOffset=newFontSize.fontOffset;var newAnnotationFontSize=getBestFontSizeFor(Math.floor(cellSize/2));annotationFontSize=newAnnotationFontSize.fontSize;if(annotationFontSize==0){annotationFontSize=fontSize;annotationFontImageOffset=fontImageOffset;annotationFontOffset=fontOffset;}else{annotationFontImageOffset=newAnnotationFontSize.fontImageOffset;annotationFontOffset=newAnnotationFontSize.fontOffset;}
panelSize=cellSize*9+2*4+6;var sectionSize=cellSize*3+4;offsetX=Math.floor((boardWidth-panelSize)/2);offsetY=Math.floor((boardHeight-panelSize)/2);ctx.beginPath();ctx.lineWidth=1.0;ctx.strokeStyle="#888888";var currentX=offsetX+cellSize+2;var currentY=offsetY+cellSize+2;for(var c=1;c<=6;c++){ctx.moveTo(currentX-0.5,offsetY-0.5);ctx.lineTo(currentX-0.5,offsetY+panelSize-2-0.5);ctx.moveTo(offsetX-0.5,currentY-0.5);ctx.lineTo(offsetX+panelSize-2-0.5,currentY-0.5);currentX+=cellSize+1;currentY+=cellSize+1;if(c%2==0){currentX+=cellSize+2;currentY+=cellSize+2;}}
ctx.stroke();ctx.beginPath();ctx.lineWidth=2.0;ctx.strokeStyle="#000000";ctx.strokeRect(offsetX,offsetY,sectionSize,sectionSize);ctx.strokeRect(offsetX,offsetY+panelSize-sectionSize-2,sectionSize,sectionSize);ctx.strokeRect(offsetX+panelSize-sectionSize-2,offsetY,sectionSize,sectionSize);ctx.strokeRect(offsetX+panelSize-sectionSize-2,offsetY+panelSize-sectionSize-2,sectionSize,sectionSize);ctx.strokeRect(offsetX+sectionSize,offsetY+sectionSize,sectionSize,sectionSize);ctx.moveTo(offsetX+sectionSize,offsetY);ctx.lineTo(offsetX+panelSize-sectionSize,offsetY);ctx.moveTo(offsetX+panelSize-2,offsetY+sectionSize);ctx.lineTo(offsetX+panelSize-2,offsetY+panelSize-sectionSize);ctx.moveTo(offsetX,offsetY+sectionSize);ctx.lineTo(offsetX,offsetY+panelSize-sectionSize);ctx.moveTo(offsetX+sectionSize,offsetY+panelSize-2);ctx.lineTo(offsetX+panelSize-sectionSize,offsetY+panelSize-2);ctx.stroke();for(var c=0;c<9;c++){for(var d=0;d<9;d++){drawCell(ctx,c,d,false);}}}}
function checkGameEnd(){if(gameFinished)return;gameFinished=true;for(var c=0;(c<sudokuData.length)&&gameFinished;c++){for(var d=0;(d<sudokuData[0].length)&&gameFinished;d++){if(sudokuData[c][d]==0){gameFinished=((userData[c][d].length==1)&&(parseInt(userData[c][d])==solutionData[c][d]));}}}
if(gameFinished){checkButtons();window.alert("Congratulations! You've solved this puzzle.");}}
function showErrors(){var canvas=document.getElementById("game");var errorsDetected=false;if(!canvas.getContext)return;var ctx=canvas.getContext("2d");for(var c=0;c<sudokuData.length;c++){for(var d=0;d<sudokuData[0].length;d++){if((sudokuData[c][d]==0)&&(userData[c][d].length==1)&&(userData[c][d].charAt(0)!='*')&&(parseInt(userData[c][d])!=solutionData[c][d])){drawNumberOnCell(userData[c][d],regularFontImg,"rgb(255,200,200)",d,c,ctx);errorsDetected=true;}}}
if(!errorsDetected){window.alert("No errors have been detected.");}}
function solvePuzzle(){if(gameFinished){window.alert("The puzzle is already solved.");return;}
var canvas=document.getElementById("game");if(!canvas.getContext)return;var ctx=canvas.getContext("2d");if(confirm("Are you sure you want to solve this puzzle?")){for(var c=0;c<sudokuData.length;c++){for(var d=0;d<sudokuData[0].length;d++){var fillStyle="rgb(200,200,255)";if(sudokuData[c][d]==0){if((userData[c][d].length==1)&&(userData[c][d].charAt(0)!='*')){if(parseInt(userData[c][d])!=solutionData[c][d]){fillStyle="rgb(255,200,200)";}else{fillStyle="rgb(200,255,200)";}}
userData[c][d]=solutionData[c][d];drawNumberOnCell(userData[c][d],regularFontImg,fillStyle,d,c,ctx);}}}
gameFinished=true;checkButtons();}}
function restartPuzzle(){var canvas=document.getElementById("game");if(!canvas.getContext)return;var ctx=canvas.getContext("2d");if(gameFinished||confirm("Are you sure you want to restart this puzzle?")){gameFinished=false;for(var c=0;c<sudokuData.length;c++){for(var d=0;d<sudokuData[0].length;d++){var fillStyle="rgb(200,200,255)";if(sudokuData[c][d]==0){userData[c][d]="";drawCell(ctx,c,d,true);}}}}
gameStarted=false;checkButtons();}
document.onkeydown=sudokuKeyListener;function sudokuKeyListener(e){if(!e){if(window.event){e=window.event;}else{return;}}
var targetNumber=0;if((e.keyCode>=97)&&(e.keyCode<=105)){targetNumber=e.keyCode-96;}else if((e.keyCode>=49)&&(e.keyCode<=57)){targetNumber=e.keyCode-48;}
var panel=document.getElementById("numberPanel");if(targetNumber>0){if(panel.style.visibility=="visible"){document.getElementById("button"+targetNumber).click();}}else if(e.keyCode==27){panel.style.visibility="hidden";panel.style.top="0px";panel.style.left="0px";}}
function sudokuSaveGame(){var savedGame=jaaulde.utils.cookies.get('save');if((savedGame==null)||(confirm("The current saved game will be lost. Continue?"))){var stringToSave='';for(var c=0;c<9;c++){for(var d=0;d<9;d++){stringToSave+=userData[c][d]+'-';}}
currentSavedGame=stringToSave;jaaulde.utils.cookies.set('save',currentSavedGame);checkButtons();alert('Game saved successfully');justSaved=true;}}
function sudokuLoadGame(){var savedGame=jaaulde.utils.cookies.get('save');if(savedGame==null){savedGame=currentSavedGame;}
if(savedGame==null){alert('No saved game available.');}else if(!gameStarted||confirm("The current game will be lost. Continue?")){var savedParts=savedGame.split('-');var currentRow=0;var currentCol=0;for(var c=0;c<81;c++){userData[currentRow][currentCol]=savedParts[c];currentCol++;if(currentCol>8){currentCol=0;currentRow++;}}
gameStarted=true;checkButtons();setTimeout("repaint()",0);}}
function checkButtons(){if(gameStarted){document.getElementById("savegamebutton").removeAttribute("disabled");document.getElementById("showerrorsbutton").removeAttribute("disabled");document.getElementById("restartpuzzlebutton").removeAttribute("disabled");}else{document.getElementById("savegamebutton").setAttribute("disabled","disabled");document.getElementById("showerrorsbutton").setAttribute("disabled","disabled");document.getElementById("restartpuzzlebutton").setAttribute("disabled","disabled");}
if(gameFinished){document.getElementById("restartpuzzlebutton").removeAttribute("disabled");document.getElementById("solvepuzzlebutton").setAttribute("disabled","disabled");document.getElementById("savegamebutton").setAttribute("disabled","disabled");document.getElementById("showerrorsbutton").setAttribute("disabled","disabled");}else{document.getElementById("solvepuzzlebutton").removeAttribute("disabled");}
var savedGame=jaaulde.utils.cookies.get('save');if(savedGame==null){savedGame=currentSavedGame;}
if(savedGame==null){document.getElementById("loadgamebutton").setAttribute("disabled","disabled");}else{document.getElementById("loadgamebutton").removeAttribute("disabled");}}