// =============================================================
// Daily Sudoku from Andrew Stuart
//
// Copyright Scanraid Ltd 2005
//
// This script is for distribution to any web site participating
// in the Andrew Stuart Daily Sudoku Subscription
//
// Version 2.01 25-Mar-2008
// =============================================================

var g 		= [[0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0]];
var sol 	= [[0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0]];
var clues	= [[0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0]];
var mask	= [[0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0]];
var fail	= [[0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0]];
var last_back_col = '';
var last_name = '';
var timerID = 0;
var tStart  = null;
var thepuzzlestring = '';
var grade='g';

function bit2int( m )
{
	switch( m ) {
	case 1   : return 0;
	case 2   : return 1;
	case 4   : return 2;
	case 8   : return 3;
	case 16  : return 4;
	case 32  : return 5;
	case 64  : return 6;
	case 128 : return 7;
	case 256 : return 8;
	}
	return 0;
}
function bit_count( b )
{
    var n = 0;
	if ( !b ) return 0;
    do { ++n; } while ( b &= (b-1) );
    return  n;
}
function vs_valid_number(item)
{
	var okay = true;
//	item.value = item.value.Trim();
	var num = "0123456789";
	for (var intLoop = 0; intLoop < item.value.length; intLoop++) {
	    if (num.indexOf(item.value.charAt(intLoop)) == -1) okay = false;
	}
	if( !okay ) item.value = '';
	return okay;
}
function set_print_square( x, y, val )
{
	var t, s, nt;
	var oRow;

	nt = ( y < 3 ) ? "A" : (( y < 6 ) ? "B" : "C");
	nt = nt + (( x < 3 ) ? "1" : (( x < 6 ) ? "2" : "3"));

	t = document.getElementById(nt);
	oRow = t.rows[y % 3];
	if( val > 0 )
		 oRow.cells[x % 3].innerHTML = val;
	else oRow.cells[x % 3].innerHTML = '&nbsp;';
	oRow.cells[x % 3].className = ( clues[y][x]==true ) ? 'InnerTClues':'InnerTDone';
}

function set_square(x,y,val)
{
	if( document.getElementById('A' + x + y).className == 'SQ1'
	 || document.getElementById('A' + x + y).className == 'SQ2' 	 // White background
	 || document.getElementById('A' + x + y).className == 'notes2' ) // White background
	{
		if( val == ' ' || val == '0' || val == 0 )
		{
			document.getElementById('A' + x + y).value = '';
			document.getElementById('A' + x + y).className = (clues[y][x]==true)?'SQ2':'SQ1';
		}
		else
		{
			document.getElementById('A' + x + y).value = val;
			document.getElementById('A' + x + y).className = (clues[y][x]==true)?'SQ2':'SQ1';
		}
	}
	else
	{
		if( val == ' ' || val == '0' )
		{
			document.getElementById('A' + x + y).value = '';
			document.getElementById('A' + x + y).className = (clues[y][x]==true)?'SQ4':'SQ3';
		}
		else
		{
			document.getElementById('A' + x + y).value = val;
			document.getElementById('A' + x + y).className = (clues[y][x]==true)?'SQ4':'SQ3';
		}
	}
}
function load_board(print_version)
{
	var i, j, c;
	var archive_date = location.search;
	var mySudoku;
	var today = new Date();
	var yesterday = new Date();
	var todayStr,todayTitle;

	var ayear = today.getYear();
	if( ayear < 1900 ) ayear += 1900;

	if( archive_date.length == 0 )
	{
		todayTitle = today.getDate() + '/' + (today.getMonth()+1) + '/' + ayear;
		todayStr = '&m=' + (today.getMonth()+1)  + '&d=' + today.getDate() + '&y=' + ayear;
	}
	else
		todayStr = archive_date.substring(4,archive_date.length);

	if( print_version )
		document.getElementById("ptitle").innerHTML = "<font size=5>The Daily Sudoku for " + todayTitle + "</font>";

	if(window.ActiveXObject)
	{
		var xmlDoc = new ActiveXObject("Msxml2.XMLHTTP");
		xmlDoc.open("GET","http://www.sudokuwiki.org/feed/fetchSudokuDAILY.asp?accid=9002" + todayStr, false);
		xmlDoc.send();
		mySudoku = xmlDoc.responseXML.xml;
		mySudoku = mySudoku.substring(24,mySudoku.length-2);
	}
	else if(document.implementation && document.implementation.createDocument)
	{
		xmlDoc = new XMLHttpRequest();
		xmlDoc.open("GET", "http://www.sudokuwiki.org/feed/fetchSudokuDAILYtxt.asp?accid=9002" + todayStr, false);
		xmlDoc.send(null);
		mySudoku = xmlDoc.responseText;
	}
	if( mySudoku.indexOf('rror') > 0 )
	{
		alert(mySudoku.substring(6,mySudoku.length-8));
		return;
	}

	grade = mySudoku.charAt(0);
	if( print_version ) {
		switch( grade ) {
		case 'k' : document.getElementById("pgrade").innerHTML = "<font size=5>Kid's</font>"; break;
		case 'g' : document.getElementById("pgrade").innerHTML = "<font size=5>Gentle</font>"; break;
		case 'm' : document.getElementById("pgrade").innerHTML = "<font size=5>Moderate</font>"; break;
		case 't' : document.getElementById("pgrade").innerHTML = "<font size=5>Tough</font>"; break;
		case 'd' : document.getElementById("pgrade").innerHTML = "<font size=5>Diabolical</font>"; break;
		case 'e' : document.getElementById("pgrade").innerHTML = "<font size=5>Extreme</font>"; break;
		}
	} else {
		switch( grade ) {
		case 'k' :
			for(i=2;i<=6;i++)
				document.getElementById("star" + i).src = 'starfade.gif'; break;
		case 'g' :
			for(i=3;i<=6;i++)
				document.getElementById("star" + i).src = 'starfade.gif'; break;
		case 'm' :
			for(i=4;i<=6;i++)
				document.getElementById("star" + i).src = 'starfade.gif'; break;
		case 't' :
			for(i=5;i<=6;i++)
				document.getElementById("star" + i).src = 'starfade.gif'; break;
		case 'd' :
			for(i=6;i<=6;i++)
				document.getElementById("star" + i).src = 'starfade.gif'; break;
		}
	}
	thepuzzlestring = '';

	var d = new Date()

	for(j=0;j<9;j++)
		for(i=0;i<9;i++)
		{
			var c = j*9+i+1;
			thepuzzlestring += mySudoku.charAt(c);
			if( mySudoku.charAt(c)=='.' )
				g[j][i] = 0;
			else
				g[j][i] = mySudoku.charAt(c)*1;
			sol[j][i] = mySudoku.charAt(c+81)*1;
			if( print_version )
				set_print_square(i,j,g[j][i]);
			else
			{
				if( g[j][i] > 0 )
				{
					clues[j][i] = 1;
					set_square(i,j,g[j][i]);
					document.getElementById('A' + i + j).readOnly = true;
				}
				else
					set_square(i,j,' ');
			}
		}

	if( !print_version ) SWStart();
}
function load_from_script(print_version,mySudoku)
{
	var i, j, c;

	grade = 'e';
	if( !print_version )
		switch( grade ) {
		case 'g' :
			for(i=2;i<=4;i++)
				document.getElementById("star" + i).src = 'bstarfade.gif'; break;
		case 'm' :
			for(i=3;i<=4;i++)
				document.getElementById("star" + i).src = 'bstarfade.gif'; break;
		case 't' :
			for(i=4;i<=4;i++)
				document.getElementById("star" + i).src = 'bstarfade.gif'; break;
		case 'd' :
		}

	thepuzzlestring = mySudoku.substring(1,mySudoku.length);

	for(j=0;j<9;j++)
		for(i=0;i<9;i++)
		{
			var c = j*9+i+1;
			if( mySudoku.charAt(c)=='.' )
				g[j][i] = 0;
			else
				g[j][i] = mySudoku.charAt(c)*1;
			if( print_version )
				set_print_square(i,j,g[j][i]);
			else
			{
				if( g[j][i] > 0 )
				{
					clues[j][i] = 1;
					set_square(i,j,g[j][i]);
					document.getElementById('A' + i + j).readOnly = true;
				}
				else
				{
					clues[j][i] = 0;
					set_square(i,j,' ');
				}
			}
		}

	if( !print_version ) SWStart();
	last_name = '';
}
function sanity_check()
{
	var bb,cc,n,i,j,c,x,y,zz,yy,failed=0;

	for(x=0;x<9;x++)
		for(y=0;y<9;y++) fail[y][x]=0;

	for(x=0;x<9;x++)
		for(y=0;y<9;y++)	// for every square on the board...
			if( g[x][y] )	// if it is an known square...
			{
				for( i=0;i<9;i++ ) // check values in row
				{
					if( i != y && g[x][i] == g[x][y] ) {
						fail[x][y]=fail[x][i]=1;
					}
					if( i != x && g[i][y] == g[x][y] ) {
						fail[i][y]=fail[x][y]=1;
					}
				}
			}

	for(bb=0;bb<9;bb+=3)			// for each box (9 of them 3 by 3 each)
		for(cc=0;cc<9;cc+=3)
			for(i=bb;i<bb+3;i++)		// which means looking in each 3 by 3 box
				for(j=cc;j<cc+3;j++)
					if( g[i][j] ) // if the square is known ...
						for(zz=bb;zz<bb+3;zz++)	// ..check every other cell
							for(yy=cc;yy<cc+3;yy++)
								if( !(zz==i && yy==j) && g[zz][yy] == g[i][j] )	{ // .. if the number is known
									fail[zz][yy]=fail[i][j]=1;
								}
	for(x=0;x<9;x++)
		for(y=0;y<9;y++) if( fail[y][x]==1 ) failed++;
	return failed;
}

function convert_str2mask( astr )
{
	var n = 0;
	for(var i=0;i<astr.length;i++)
		n |= (1 << (parseInt(astr.charAt(i))-1));
	return n;
}
function convert_mask2str( val )
{
	var s= '';
	for(i=1;i<=9;i++)
		if( val & (1 << i-1) )
			s = s + i;
	return s;
}
function Sudoku1( afield )
{
	var x,y,i,j,done,failed;
	if( vs_valid_number(afield) )
	{
		x = afield.id.charAt(1);
		y = afield.id.charAt(2);
		if( afield.value == 0 )
		{
			afield.value = '';
			g[y][x] = 0;
			mask[y][x] = 0;
			set_square( x,y, g[y][x] );
		}
		if( afield.value.length > 1 )
		{
			mask[y][x] = convert_str2mask( afield.value )
			g[y][x] = 0;
			afield.value = convert_mask2str( mask[y][x] );
			if( bit_count(mask[y][x] ) == 1 )
			{
				g[y][x] = bit2int(mask[y][x])+1;
				mask[y][x] = 0;
				set_square( x,y, g[y][x] );
			}
			else
			{
				afield.className = (afield.className == 'SQ1' || afield.className == 'SQ2') ? "notes2" : "notes1";
			}
		}
		else
		{
			mask[y][x] = 0;
			g[y][x] = afield.value;
			set_square( x,y, g[y][x] );
		}

		done = 0;
		for(i=0;i<9;i++)
			for(j=0;j<9;j++)
			{
				if( g[j][i] > 0 ) done++;
				//if( g[j][i] == sol[j][i] ) correct++;
			}
		if( done == 81 ) {
			failed = sanity_check();
			if( failed == 0 )
				alert('Congratulations! You have completed the Sudoku!');
			else
				alert('Oops! There are ' + failed + ' cells which are in conflict.' );
		}
	}
}
function focyell( afield )
{
	if( last_name.length > 0 )
		document.getElementById(last_name).style.backgroundColor = last_back_col;
	last_name = '';

	if( afield.readOnly == false )
	{
		last_name = afield.id;
		last_back_col = afield.style.backgroundColor;
		afield.style.backgroundColor = '#ffff00';
	}
}
function color_same(x,y)
{
	var t, i, j, nt;
	var inputbox;

	inputbox = '<input type="text" value="" size=2 maxlength=2 name="ibox" id="ibox" onchange="javascript:Sudoku1(';
	inputbox = inputbox + "'" + 'A' +  x + y + "'" + ',this.value);">';

	document.getElementById('A'+x+y).innerHTML = inputbox;

}
function print_todays_board()
{
	var x,y,done=0;
//	var board = 'ad="bd=';
//	for(y=0;y<9;y++)
//		for(x=0;x<9;x++)
//			board = board + g[y][x];

	SGW = window.open('SudokuPrintable.htm','_blank','resizable=yes,toolbar=1,scrollbars=yes,left=100,top=10,screenX=100,screenY=10,width=660,height=660');
	if (!SGW.opener) SGW.opener = self;
}
function print_board(archive_date)
{
	var x,y,done=0;
//	var board = 'ad="bd=';
//	for(y=0;y<9;y++)
//		for(x=0;x<9;x++)
//			board = board + g[y][x];

	SGW = window.open('SudokuPrintable.htm?ad=' + archive_date,'_blank','resizable=yes,toolbar=1,scrollbars=yes,left=100,top=10,screenX=100,screenY=10,width=660,height=660');
	if (!SGW.opener) SGW.opener = self;
}
function print_weekly_board() {

	SGW = window.open('/Print_Weekly_Sudoku.asp?unsolvable=' + unsolvable,'_blank','resizable=yes,toolbar=1,scrollbars=yes,left=100,top=10,screenX=100,screenY=10,width=660,height=660');
	if (!SGW.opener) SGW.opener = self;

}
function print_yesterdays_solution()
{
	var yesterday = new Date();
	var yesterdayStr, yesterdayDate;
	var today = new Date();

	yesterdayDate = today.getDate() -1 ;
	yesterday.setDate( yesterdayDate );

	if( yesterday.getYear() < 200 )
		yesterdayStr = yesterday.getDate()  + '/' + (1+yesterday.getMonth()) + '/' + (1900 + yesterday.getYear());
	else yesterdayStr = yesterday.getDate()  + '/' + (1+yesterday.getMonth()) + '/' + yesterday.getYear();

	SGW = window.open('/Print_Daily_Sudoku.asp?solution=please&day=' + yesterdayStr,'_blank','resizable=yes,toolbar=1,scrollbars=yes,left=100,top=10,screenX=100,screenY=10,width=660,height=660');
	if (!SGW.opener) SGW.opener = self;
}
function print_solution(archive_date)
{
	SGW = window.open('ASSolution.htm?ad=' + archive_date,'_blank','resizable=yes,toolbar=1,scrollbars=yes,left=100,top=10,screenX=100,screenY=10,width=660,height=660');
	if (!SGW.opener) SGW.opener = self;
}
function email_board()
{
	var x,y,done=0;
	var board = 'bd=';
	for(y=0;y<9;y++)
		for(x=0;x<9;x++)
		{
			if( g[y][x]>0 ) done++;
			board = board + g[y][x];
		}
	if( !done )
		alert("This board is empty!");
	else
	{
		SGW = window.open('SudokuEmail.htm?' + board,'_blank','resizable=no,scrollbars=no,left=300,top=200,screenX=300,screenY=200,width=500,height=250');
    	if (!SGW.opener) SGW.opener = self;
	}
}
function SWUpdateTimer()
{
	if(timerID) {
	  clearTimeout(timerID);
	}

	if(!tStart)
	  tStart   = new Date();

	var hours, mins, secs;
	var   tDate = new Date();
	var   tDiff = tDate.getTime() - tStart.getTime();

	tDate.setTime(tDiff);

	hours = tDate.getHours();
	if( hours >= 15 ) hours = 0;
	mins = tDate.getMinutes();
	secs = tDate.getSeconds();
	if( mins < 10 ) mins = '0' + mins
	if( secs < 10 ) secs = '0' + secs
	document.getElementById('theTimer').value = "" + hours + ":" + mins + ":" + secs;

	timerID = setTimeout("SWUpdateTimer()", 1000);
}
function pause_game()
{
	tInt1 = new Date();

	clearTimeout(timerID);

	alert("Game Paused, press button to continue.");

	tInt2 = new Date();

	tStart.setTime( tStart.getTime() + (tInt2.getTime()-tInt1.getTime()));

	timerID  = setTimeout("SWUpdateTimer()", 1000);
}
function SWStart()
{
	tStart   = new Date();

	document.getElementById('theTimer').value = "0:00:00";

	timerID  = setTimeout("SWUpdateTimer()", 1000);
}
function SWStop()
{
   if(timerID) {
      clearTimeout(timerID);
      timerID  = 0;
   }

   tStart = null;
}
function SWReset()
{
	tStart = null;

	document.getElementById('theTimer').value = "0:00:00";
}
function openAWindow( pageToLoad, winName, width, height, center)
{
	xposition=0; yposition=0;
	if ((parseInt(navigator.appVersion) >= 4 ) && (center)){
		xposition = (screen.width - width) / 2;
		yposition = (screen.height - height) / 2;
	}
	args = "width=" + width + ","
	+ "height=" + height + ","
	+ "location=0,"
	+ "menubar=0,"
	+ "resizable=1,"
	+ "scrollbars=1,"
	+ "status=0,"
	+ "titlebar=0,"
	+ "toolbar=0,"
	+ "hotkeys=0,"
	+ "screenx=" + xposition + ","  //NN Only
	+ "screeny=" + yposition + ","  //NN Only
	+ "left=" + xposition + ","     //IE Only
	+ "top=" + yposition;           //IE Only
	window.open( pageToLoad,winName,args );
}

function send_to_solver()
{
	SGW = window.open('/sudoku.htm?bd=' + thepuzzlestring,'_blank','resizable=yes,toolbar=1,scrollbars=yes');
	if (!SGW.opener) SGW.opener = self;

}

