
function SudokuBlock(blockid){this.id=blockid;this.row=parseInt(blockid/9);this.col=parseInt(blockid%9);this.family=parseInt(this.row/3)*3+parseInt(this.col/3);this.values=[1,2,3,4,5,6,7,8,9];this.locked=false;this.usrset=false;}
SudokuBlock.prototype.draw=function(){var el=document.getElementById(this.id);if(el){var txt="";el.className="";if(this.usrset&&!el.className.match("set"))el.className+=" set";else if(this.locked){el.setAttribute("readOnly","true");el.className+=" locked";}
if(this.values.length==1)el.value=this.values[0];if(el.value.length>3){el.className+=" multi3";}else if(el.value.length>1){el.className+=" multi";}
delete(el);}}
function SudokuGroup(row,col,family){this.row=row;this.col=col;this.family=family;var iRw=row*9;this.rowBlocks=[iRw,iRw+1,iRw+2,iRw+3,iRw+4,iRw+5,iRw+6,iRw+7,iRw+8];this.colBlocks=[col,col+9,col+18,col+27,col+36,col+45,col+54,col+63,col+72];var famStart=parseInt(family/3)*27+parseInt(family%3)*3;this.familyBlocks=[famStart,famStart+1,famStart+2,famStart+9,famStart+10,famStart+11,famStart+18,famStart+19,famStart+20];}
SudokuGroup.prototype.checkGroup=function(blocks,oSP){var values=[[],[],[],[],[],[],[],[],[]];for(var i=0;i<this.rowBlocks.length;i++){var block=blocks[this.rowBlocks[i]];for(var j=0;j<block.values.length;j++){var iPossible=block.values[j]-1;values[iPossible][values[iPossible].length]=block.id;}}
for(var i=0;i<values.length;i++){if(values[i].length==1&&!blocks[values[i][0]].locked){var block=blocks[values[i][0]];block.values=[i+1];block.locked=true;oSP.updateOthers(values[i][0],i+1);block.draw();}}
var values=[[],[],[],[],[],[],[],[],[]];for(var i=0;i<this.colBlocks.length;i++){var block=blocks[this.colBlocks[i]];for(var j=0;j<block.values.length;j++){var iPossible=block.values[j]-1;values[iPossible][values[iPossible].length]=block.id;}}
for(var i=0;i<values.length;i++){if(values[i].length==1&&!blocks[values[i][0]].locked){var block=blocks[values[i][0]];block.values=[i+1];block.locked=true;oSP.updateOthers(values[i][0],i+1);block.draw();}}
var values=[[],[],[],[],[],[],[],[],[]];for(var i=0;i<this.familyBlocks.length;i++){var block=blocks[this.familyBlocks[i]];for(var j=0;j<block.values.length;j++){var iPossible=block.values[j]-1;values[iPossible][values[iPossible].length]=block.id;}}
for(var i=0;i<values.length;i++){if(values[i].length==1&&!blocks[values[i][0]].locked){var block=blocks[values[i][0]];block.values=[i+1];block.locked=true;oSP.updateOthers(values[i][0],i+1);block.draw();}}}
SudokuPuzzle.prototype.init=function(id,val){if(document.getElementById&&document.getElementsByTagName){el=document.getElementById(id);if(el){this.blocks[id].draw();if(val!='_'){this.update(id,val,true);this.updateOthers(id,val);}else{YAHOO.util.Event.addListener(el,"click",NumberCrazy.edit,this);}}}}
SudokuPuzzle.prototype.getValueStr=function(multi){var str='';for(var i=0;i<this.blocks.length;i++){var el=document.getElementById(this.blocks[i].id);var tmpvalue='_';if(el.value.length==1||(multi==1&&el.value.length>0))tmpvalue=el.value;if(multi==1){if(str.length>=1){str+=","}
str+=tmpvalue;}else{str+=tmpvalue;}}
return str;}
SudokuPuzzle.prototype.validate=function(obj){var url=this.server+'validate.html?id='+this.puzzleid+"&answer="+this.getValueStr();urchinTracker('/activity/check');if(!this.message){var oPanel=new YAHOO.widget.Panel("mesgbody",{zIndex:9999,iframe:false,underlay:'shadow'});oPanel.setBody("Checking your answers... Please wait");oPanel.render(document.getElementById("mesg"));var pLeft=YAHOO.util.Dom.getXY('18');var pL2=YAHOO.util.Dom.getXY('19');var pRight=YAHOO.util.Dom.getXY('26');var width=parseInt(document.getElementById('mesgbody').style.width);pLeft[0]=pLeft[0]+(pRight[0]+pL2[0]-width-pLeft[0]*2)/2;YAHOO.util.Dom.setXY('mesg',pLeft);oPanel.show();this.message=oPanel;}else{this.message.setBody("Checking your answers... Please wait");this.message.show();}
var callback={success:function(o){var txt=o.responseText;var goodRx=/\<code>(\d+)<\/code><msg>(.*?)<\/msg>/;var errorRx=/\<error>\d+<\/error><count>(\d+)<\/count>/;if(txt.match(goodRx)){var code=goodRx.exec(txt)[1];this.message.setBody(goodRx.exec(txt)[2]+" ");if(code==200){urchinTracker('/activity/solved');}}else if(txt.match(errorRx)){this.message.setBody("You made "+errorRx.exec(txt)[1]+" errors");}else{}
obj.ele.disabled=false;var pLeft=YAHOO.util.Dom.getXY('18');var pL2=YAHOO.util.Dom.getXY('19');var pRight=YAHOO.util.Dom.getXY('26');var width=parseInt(document.getElementById('mesgbody').style.width);pLeft[0]=pLeft[0]+(pRight[0]+pL2[0]-width-pLeft[0]*2)/2;YAHOO.util.Dom.setXY('mesg',pLeft);this.message.show();},failure:function(o){alert("Could not validate with server.  Please try again.");obj.ele.disabled=false;},scope:this}
YAHOO.util.Connect.asyncRequest('GET',url,callback);}
SudokuBlock.prototype.removeValue=function(iValue){for(var i=this.values.length;i>=0;--i){if(this.values[i]==iValue){this.values.splice(i,1);if(this.values.length==1){this.locked=true;}}}}
function SudokuPuzzle(exist,id,puzEl){this.blocks=new Array();this.name='puzzle';this.preset=exist.split('');this.puzzleid=id;this.server='http://www.numbercrazy.com/';this.savedgames=0;this.createPuzzle(puzEl,id);for(var i=0;i<81;i++){this.blocks[i]=new SudokuBlock(i);this.init(i,this.preset[i]);}
this.solve=false;}
SudokuPuzzle.prototype.reset=function(){for(var i=0;i<81;i++){if(this.preset[i]&&this.preset[i]!='_'){this.blocks[i].values=[this.preset[i]];}else{this.blocks[i].values=[''];}
this.blocks[i].draw();}}
SudokuPuzzle.prototype.restore=function(tos){var newstr;if(tos.match(/,/)){newstr=tos.split(',');}else{newstr=tos.split('');}
for(var i=0;i<81;i++){if(!this.blocks[i].locked&&newstr[i]!='_'){this.blocks[i].values=[newstr[i]];}else if(this.preset[i]&&this.preset[i]!='_'){this.blocks[i].values=[this.preset[i]];}else{this.blocks[i].values=[''];}
this.blocks[i].draw();}}
SudokuPuzzle.prototype.pause=function(){this.savedgames+=1;var holder=document.createElement("LI");var img=document.createElement("IMG");var puzid='puzzle'+this.savedgames;img.src="/thumb.jpg";img.id=puzid;img.setAttribute('savedinfo',this.getValueStr(1));holder.appendChild(img);document.getElementById('saved').appendChild(holder);var xy=YAHOO.util.Dom.getXY(puzid);var oMenu=new YAHOO.widget.Menu("mymenu"+this.savedgames,{fixedcenter:false,position:'dynamic',x:xy[0]+20,y:xy[1]+10});oMenu.addItems([{text:"Unpause",onclick:{fn:this.restoreOrDelete,obj:{im:img,puz:this,menu:oMenu}}}]);oMenu.render('snapmenus');YAHOO.util.Event.addListener(puzid,"click",oMenu.show,null,oMenu);var sMsg='NUMBERCRAZY.COM';var aSmsg=sMsg.split('');for(var i=0;i<81;i++){this.blocks[i].values=[aSmsg[i%aSmsg.length]];this.blocks[i].draw();}}
SudokuPuzzle.prototype.update=function(iBlock,iValue,lock){var block=this.blocks[iBlock];if(block.locked==false&&lock){block.values=[iValue];if(lock)block.locked=true;var el=document.getElementById(iBlock);YAHOO.util.Event.removeListener(el,"click",NumberCrazy.edit);this.updateOthers(iBlock,iValue);block.draw();}else if(iValue!=0){block.values=[iValue];block.usrset=true;if(this.solve){this.updateOthers(iBlock,iValue);}
block.draw();}else{block.usrset=false;block.values=[];}}
SudokuPuzzle.prototype.createPuzzle=function(puzzleEl,puzzleId){var body=document.getElementById(puzzleEl);var puzzle=document.createElement("TABLE");puzzle.className="cont";puzzle.id=puzzleId;for(var i=0;i<9;i++){var row;if(puzzle.tBodies){row=puzzle.insertRow(-1);}else{row=document.createElement("TR");row.className="row";}
for(var j=0;j<9;j++){var mid=i*9+j;var mclass="";if(i==0){mclass='topBd';}else if(i==2||i==5||i==8){mclass='botBd';}
if(j==0){mclass+=' lftBd';}else if(j==2||j==5||j==8){mclass+=' rgtBd';}
var spn=document.createElement("TD");spn.className=mclass;var inp=document.createElement("INPUT");inp.id=mid;inp.maxLength=5;YAHOO.util.Event.addListener(inp,"keydown",function(e,obj){var pressed=(e.keyCode|e.which);if(pressed>36&&pressed<41){var mid=parseInt(obj.id);if(pressed==37){mid=mid-1;if(mid%9==8||mid==-1)mid+=9;}
else if(pressed==38){mid=mid-9;}
else if(pressed==39){mid=mid+1;if(mid%9==0)mid-=9;}
else{mid=mid+9;}
if(mid<0){mid+=81;}
else if(mid>80){mid-=81;}
document.getElementById(mid).focus();}},inp);YAHOO.util.Event.addListener(inp,"keyup",function(e,obj){if(obj.value.length>5)obj.value=obj.value.substr(0,5);obj.className=obj.className.replace(/\s?multi\d?\s?/,'');if(obj.value.length>3){obj.className+=" multi3";}else if(obj.value.length>1){obj.className+=" multi";}},inp);spn.appendChild(inp);row.appendChild(spn);}
if(puzzle.tBodies){puzzle.tBodies[0].appendChild(row);}else{puzzle.appendChild(row);}}
body.appendChild(puzzle);}
SudokuPuzzle.prototype.drawAll=function(){for(var i=0;i<this.blocks.length;i++){this.blocks[i].draw();}}
SudokuPuzzle.prototype.updateOthers=function(iBlock,iValue){if(!this.solve)return;var block=this.blocks[iBlock];for(var i=0;i<this.blocks.length;i++){if(this.blocks[i].locked==false&&i!=iBlock&&(this.blocks[i].row==block.row||this.blocks[i].col==block.col||this.blocks[i].family==block.family)){this.blocks[i].removeValue(iValue);this.blocks[i].draw();if(i!=iBlock&&this.blocks[i].locked){this.updateOthers(i,this.blocks[i].values[0]);}}
var oSBG=new SudokuGroup(this.blocks[i].row,this.blocks[i].col,this.blocks[i].family);oSBG.checkGroup(this.blocks,this);}}
NumberCrazy={edit:function(e,obj){YAHOO.util.Event.addListener(this,"blur",NumberCrazy.update,obj);},update:function(e,obj){if(this.value.length>0){var iValue=parseInt(this.value);if(iValue>0){var id=this.id;obj.update(id,iValue,false);}}else{obj.update(this.id,0,false);}},createCookie:function(name,value,days){if(days){var date=new Date();date.setTime(date.getTime()+(days*24*60*60*1000));var expires="; expires="+date.toGMTString();}
else var expires="";document.cookie=name+"="+value+expires+"; path=/";},readCookie:function(name){var nameEQ=name+"=";var ca=document.cookie.split(';');for(var i=0;i<ca.length;i++){var c=ca[i];while(c.charAt(0)==' ')c=c.substring(1,c.length);if(c.indexOf(nameEQ)==0)return c.substring(nameEQ.length,c.length);}
return null;},eraseCookie:function(name){NumberCrazy.createCookie(name,"",-1);}}
YAHOO.util.Event.addListener(this,"load",myAttachFunc);function funcverify(e,obj){obj.ele.disabled=true;obj.puz.validate(obj);}
function funcsave(e,obj){obj.puz.savedgames+=1;var holder=document.createElement("LI");var img=document.createElement("IMG");var puzid='puzzle'+obj.puz.savedgames;img.src="/thumb.jpg";img.id=puzid;img.setAttribute('savedinfo',obj.puz.getValueStr(1));NumberCrazy.createCookie('cg',obj.puz.puzzleid+":"+obj.puz.getValueStr(1));holder.appendChild(img);document.getElementById('saved').appendChild(holder);var xy=YAHOO.util.Dom.getXY(puzid);var oMenu=new YAHOO.widget.Menu("mymenu"+obj.puz.savedgames,{fixedcenter:false,position:'dynamic',x:xy[0]+20,y:xy[1]+10});oMenu.addItems([{text:"Restore",onclick:{fn:obj.puz.restoreOrDelete,obj:{im:img,puz:obj.puz}}},{text:"Delete Snapshot",onclick:{fn:obj.puz.restoreOrDelete,obj:{im:img,menu:oMenu}}}]);oMenu.render('snapmenus');YAHOO.util.Event.addListener(puzid,"click",oMenu.show,null,oMenu);}
function funcpause(e,obj){obj.puz.pause();}
SudokuPuzzle.prototype.restoreOrDelete=function(type,e,obj){if(obj.puz){var saved=obj.im.getAttribute('savedinfo');obj.puz.restore(saved);if(obj.menu){var nPar=obj.im.parentNode.parentNode;nPar.removeChild(obj.im.parentNode);for(var i=0;i<nPar.childNodes.length;i++){var sib=nPar.childNodes[i];if(sib.nodeType==1){var loc=YAHOO.util.Dom.getXY(sib);var menuid=sib.childNodes[0].id.replace(/puzzle/,'mymenu');YAHOO.util.Dom.setXY(menuid,[loc[0]+20,loc[1]+10]);}}}}else{var nPar=obj.im.parentNode.parentNode;nPar.removeChild(obj.im.parentNode);for(var i=0;i<nPar.childNodes.length;i++){var sib=nPar.childNodes[i];if(sib.nodeType==1){var loc=YAHOO.util.Dom.getXY(sib);var menuid=sib.childNodes[0].id.replace(/puzzle/,'mymenu');YAHOO.util.Dom.setXY(menuid,[loc[0]+20,loc[1]+10]);}}}}
function funcoption(e,obj){}
function funcreset(e,obj){obj.puz.reset();}
function myAttachFunc(e,obj){var nav=document.getElementById("nav");var inputs=nav.getElementsByTagName("INPUT");for(var i=0;i<inputs.length;i++){var funcname="func"+inputs.item(i).name;YAHOO.util.Event.addListener(inputs.item(i),'click',eval(funcname),{ele:inputs.item(i),puz:oPuzzle});}}
jsTimer={init:function(){this.delay=1000;this.min=0;this.sec=0;this.el=document.getElementById("jstimer");this.timer=setInterval("jsTimer.update()",jsTimer.delay);},update:function(){this.sec+=1;if(this.sec%60==0){this.sec=0;this.min+=1;}
var m;var s;if(this.sec>9)s=this.sec;else s="0"+this.sec;if(this.min>9)m=this.min;else m="0"+this.min;this.el.innerHTML="Timer "+m+":"+s;}}