// Number Place Javascript Player 2.0
// (c) 2005 www.numberpuzzles.com Inc. All rights reserved.  
//
// Version History
//  2005-05-03 1.0 - Initial Release
//  2005-05-06 1.1 - cash out when digits are complete
//  2005-05-10 1.4 - delselect palette after cashout
//  2005-05-20 1.6 - disallow selection of completed digit
//  2005-06-01 1.7 - embedded version
//  2005-06-02 1.8 - pre-processed puzzle ID
//  2005-06-03 1.9 - keyboard driven
//  2005-06-22 2.0 - allow highlighting of solved cells
//  2005-08-04 2.0 - sound enable/disable
//

// Global variables
var NP_sounds_url; 		// URL where sound effect files are located
var NP_mistakecount;		// running total of player mistakes
var NP_unsolvedcount;		// running count of unsolved cells
var NP_unsolvedByDigit;		// how many of each digit are unsolved
var NP_soln;			// string representing solution is box-row-col order
var NP_mask;			// string representing starting state (1=revealed)
var NP_dim = 9;			// width of puzzle
var NP_coords = new Array(0,1,2,9,10,11,18,19,20,3,4,5,12,13,14,21,22,23,6,7,8,15,16,17,24,25,26,27,28,29,36,37,38,45,46,47,30,31,32,39,40,41,48,49,50,33,34,35,42,43,44,51,52,53,54,55,56,63,64,65,72,73,74,57,58,59,66,67,68,75,76,77,60,61,62,69,70,71,78,79,80);
var NP_seldigit;		// selected digit for highlighting
var NP_reward_url;		// optional URL for completion
var NP_zero_errors_text;	// optional wording for alert text
var NP_some_errors_text;	// optional wording for alert text
var NP_startTime;		// used by elapsed timer function
var NP_soundOn;			// initially true;

// Global variables "NP_customerID" and "NP_puzzleID" will be provided by the customer web site.
// Based on these variables, a prior script will set up NP_soln and NP_mask

if (window.NP_soln == null) {
	NP_soln = "000000000000000000000000000000000000000000000000000000000000000000000000000000000";
}
if (window.NP_mask == null) {
	NP_mask = "010110100100010011110100100111100000100101010000010111001011001110001001001001011";
}
// Global variable "NP_sounds_url" MAY be provided by the customer web site.  If not, default.
if (window.NP_sounds_url == null) {
	NP_sounds_url = "http://www.numberpuzzles.com/web/sounds/";
}
// The following global variables MAY be provided by the customer web site.  If not, default.

if (window.NP_zero_errors_text == null) {
	NP_zero_errors_text = "Congratulations! You solved the puzzle without any mistakes!";	// Default to English
}
if ((window.NP_some_errors_text == null) || (window.NP_some_errors_text == undefined)) {
	NP_some_errors_text = "Congratulations! You solved the puzzle!";	// Default to English
}
if (window.NP_reward_url == null) {
	NP_reward_url = "";
}

// Build the form table
function NP_buildForm(){
	var out_html = '';
	out_html = '<form name="NPpuzzle">\n<table border=1 cellpadding=0 cellspacing=0>';
	var idx = 0;

	var i;
	for (i=0;i<3;i++) {

	  out_html += '  <tr>\n';
	  var j;
	  for (j=0;j<3;j++) {
	    out_html += '    <td>\n<table border=1 cellpadding=0 cellspacing=0>\n';
	    var x;
	    for (x=0;x<3;x++) {
	      out_html += '      <tr>\n';
	      var y;
	      for (y=0; y<3; y++) {
		out_html += '        <td><input class="NPnorm" type="text" id="c'+idx+'" value="" size="1" readonly onMouseDown="NP_mDown('+idx+')" onMouseUp="NP_mUp('+idx+')"></td>\n';
		idx = idx + 1;
	      }
	      out_html += '      </tr>\n';
	    }
	    out_html += '    </table>\n</td>\n';
	  }
	  out_html += '  </tr>\n';
	}

	var copynotice = 'Powered by <a href="http://www.numberpuzzles.com/publisher/products.cfm" class="NPcopy">www.numberpuzzles.com</a>';
	if (window.NP_puzzleID != null) {
 		copynotice = NP_puzzleID + ' &copy 2005 www.numberpuzzles.com Inc.';
	}

	out_html = out_html 
	+ '  <tr>\n    '
	+ '    <td colspan=3 border=1 cellpadding=0 cellspacing=0 class="NPcopy">' + copynotice + '</td>\n'
	+ '  </tr>\n</table>\n';

	out_html += '<p class="NPstats"><input class="NPstats" type="text" value="Errors:" size="8" readonly>';
	out_html += '<input class="NPstats" type="text" id="NPerrcount" value="0" size="4" readonly>\n';
	out_html += '<input class="NPstats" type="text" value="  Solve time:" size="14" readonly>';
	out_html += '<input class="NPstats" type="text" id="NPsolvetime" value="" size="10" readonly>\n';
	out_html += '<input type="radio" name="NPsound" onClick="NP_soundOn=true;" checked>Sound';
	out_html += '<input type="radio" name="NPsound" onClick="NP_soundOn=false;">Off\n';
	out_html = out_html 
	+ '</form>\n</center>\n'
//	+ '<p><center>\n<p><form name="NPsound" class="NPstats"><input type="radio" name="on">Sound On<input type="radio" name="off">Sound Off</form></p>\n</center>\n';
	+ '<p></p>';
	return out_html;
}

// Javascript-encoded HTML for number puzzle form

var NP_form = NP_buildForm()
+ '<embed src="' + NP_sounds_url + 'TADA.wav" autostart=false hidden=true id="NP_tada"'
+ ' enablejavascript="true">\n'
+ '<embed src="' + NP_sounds_url + 'CASHREG.wav" autostart=false hidden=true id="NP_trill"'
+ ' enablejavascript="true">\n'
+ '<embed src="' + NP_sounds_url + 'BoinkLo.wav" autostart=false hidden=true id="NP_boing"'
+ ' enablejavascript="true">\n';


// Display number puzzle form
document.write(NP_form);

// display seconds properly
function pad0(v){
	if ((0<=v) && (v<10)) return "0"+v;
	return v;
}

// Show Elapsed Time
function showTimer() {
	var present, presenttime, elapsed, melapsed , selapsed , timerID;
	present = new Date();
	presenttime = present.getTime();
	elapsed = (presenttime - NP_startTime) / 1000;
	melapsed  = Math.floor(elapsed / 60);
	selapsed  = Math.floor(elapsed -(melapsed * 60));
	document.getElementById("NPsolvetime").value=(melapsed  + ":" + pad0(selapsed));
	if (NP_unsolvedcount > 0) timerID = setTimeout("showTimer()",1000); 
}

// Once only initialization
function NP_initialize()
{
	NP_mistakecount = 0;		// Initialize vars
	NP_unsolvedcount = 0;
	NP_unsolvedByDigit = new Array(0,0,0,0,0,0,0,0,0,0);	


	// paint initial grid

	var i;

	for (i=0;i<81;i++) {
		var pelem=document.getElementById("c"+i);
		var dig=NP_soln.charAt(i)
		if (NP_mask.charAt(i) == "1") {
			pelem.value = dig;
			pelem.className = "NPnorm";
		}
		else {
			pelem.value = "";
			pelem.className = "NPnorm";
			NP_unsolvedcount++;
			NP_unsolvedByDigit[dig]++;
		}
	}

				
	// select no cell
	NP_currcell = -1;
	NP_clicked = -1;

	// trap key presses
	document.onkeydown=NP_kbdhandler;

	// Inititialize stats

	pelem=document.getElementById("NPerrcount");
	pelem.value=0;
	

	var startme = new Date();
	NP_startTime = startme.getTime();
	showTimer();
	NP_soundOn=true;

}

// enter a digit from keyboard
function NP_kbdhandler(e)
{

	if (NP_currcell < 0) {		// discard if nothing selected
		return;
	}

	var pelem=document.getElementById("c"+NP_currcell);

	if (!e) e=window.event;
	var chr = String.fromCharCode(e.keyCode);

	if (('0'<=chr)&&(chr <='9')) {
		var d=chr.charCodeAt(0)-48;
		NP_putdigit(d);
	}
	else if ((chr==' ')||(e.keyCode==46)||(e.keyCode==8)) { // Clear
		NP_putdigit(0);
	}
	else if (chr=='\x25') {			// left arrow
		NP_select(NP_moveCell(NP_currcell,-1));
	}
	else if (chr=='\x26') {			// up arrow
		NP_select(NP_moveCell(NP_currcell,-9));
	}
	else if (chr=='\x27') {			// right arrow
		NP_select(NP_moveCell(NP_currcell,1));
	}
	else if (chr=='\x28') {			// down arrow
		NP_select(NP_moveCell(NP_currcell,+9));
	}
	else if (chr=='\x09') {			// TAB
		NP_select(NP_moveCell(NP_currcell,1));
	}
	else if (chr=='\x0D') {			// CR
		NP_select(NP_moveCell(NP_currcell,+9));
	}
	pelem.focus();
}

//Move cell in indicated direction
function NP_moveCell(cc,delta){
	var idx = NP_lookup(cc);
	if (idx<0) return(0);
	idx = idx + delta;
	if (idx<0) idx+=81;
	if (idx>80) idx-=81;
	return (NP_coords[idx]);
	
}
// Lookup currcell value in coordinates table, return index
function NP_lookup(cc) {
	var idx;
	for (idx=0;idx<81;idx++) {
		if (NP_coords[idx] == cc) return (idx);
	}
	return -1;
}


//Mouse Down - highlight if solved and active!
function NP_mDown(idx) {
	NP_highlightDigits(NP_seldigit,"NPnorm");		// unhighlight for insurance
	NP_seldigit = 0;
	var dig = NP_soln.charAt(idx);
	if (NP_isSolved(idx)) {
		if (NP_isActive(dig)) {
//x alert('Debug: is active');
			NP_highlightDigits(dig,"NPhigh");
			NP_seldigit = dig;
		}
	}
	else NP_select(idx);
}

function NP_isSolved(idx) {
	var pelem=document.getElementById("c"+idx);
	return (pelem.value != "");
}

function NP_isActive(dig) {
	return (NP_unsolvedByDigit[dig] > 0);
}

// Set or remove highlighting
function NP_highlightDigits(dig,newclass) {		// set or remove highlighting

	if (dig < 1) return;	// skip if nothing selected
	var tclass = "NPsolvd";
	if (NP_isActive(dig)) tclass = newclass;

	var idx;
	for (idx=0;idx<81;idx++) {
		if (NP_soln.charAt(idx)==dig) {
			if (NP_isSolved(idx)) {
				NP_setcellclass(idx,tclass)
			}
		}
	}
}
	
//Mouse Up - cancel highlighting
function NP_mUp(idx){
	NP_highlightDigits(NP_seldigit,"NPnorm");
	NP_seldigit = 0;
}



// Select a cell by clicking or arrowing
function NP_select(idx){

	var pelem=document.getElementById("c"+idx);
	NP_unselect(NP_currcell);
	NP_currcell = idx;
	pelem.focus();
	NP_setcellclass(NP_currcell,"NPcurr");
}

//Unselect current cell, restoring proper class
function NP_unselect(idx) {
	if (idx < 0) return;
	var tclass = "NPnorm";
	if (NP_isSolved(idx)) {
		if (!NP_isActive(NP_soln.charAt(idx))) tclass="NPsolvd";
	}
	NP_setcellclass(NP_currcell,tclass);
}


function NP_setcellclass(idx,newclass) {
	var pelem=document.getElementById("c"+idx);	// Locate the cell
	pelem.className=newclass;			// start the effect
	pelem.focus();
}

function NP_resetcellclass(idx) {
	var pelem=document.getElementById("c"+idx);	// Locate the cell
	var newclass = "NPnorm";
	if (idx == NP_currcell) newclass = "NPcurr";
	pelem.className=newclass;			// start the effect
//	pelem.focus();
}


// Fill current cell using the selected digit
function NP_putdigit(d){

	var idx = NP_currcell;
	if (idx < 0) return;	// exit if no cell selected

	var pelem=document.getElementById("c"+idx);
	var dig=NP_soln.charAt(idx);

	if (pelem.value=="") {
		if (dig == d) {		// Unsolved + match = Correct!
			pelem.value=d;
			pelem.className="NPcurr";
			NP_unsolvedcount--;
			NP_unsolvedByDigit[d]--;

			if (NP_unsolvedByDigit[d]==0) {
				NP_highlightDigits(d,"NPsolvd");
				NP_seldigit=0;
				NP_select(idx);
				NP_playsound("NP_trill");	// start audio effect
			}

			if (NP_unsolvedcount==0) NP_gocelebrate();
		}
		else if (d != 0) {		// Wrong move
			NP_mistakecount++;
			NP_animatecell(idx,"NPwrong","NPcurr","NP_boing");
			pelem=document.getElementById("NPerrcount");
			pelem.value++;
		}
	}
	else {						//Already filled - highlight if not solved
		return;
	}
}


// Animate a cell
function NP_animatecell(idx,tempclass,normclass,sound) {

	NP_setcellclass(idx,tempclass);			// start the effect
	var cmdstring = "NP_resetcellclass("+idx+");";
	var the_timeout = setTimeout(cmdstring,500);	// restore class in one second
	NP_playsound(sound);
}


// Celebrate Victory
function NP_gocelebrate() {
	if (NP_reward_url == "") {
		NP_playsound("NP_tada");
		var cmdstring = "NP_reward();"
		var timer2 = setTimeout(cmdstring,200);		//start soon
	}
//x	else window.location(NP_reward_url);
	else location.href = NP_reward_url;			// goto indicated page
}

function NP_reward() {
	if (NP_mistakecount>0) {
		alert(NP_some_errors_text);
		}
	else {
		alert(NP_zero_errors_text);
	}
}

// Play indicated sound effect
function NP_playsound(effect) {
	if (NP_soundOn==false) return;
	var the_sound=document.getElementById(effect);	// start audio effect
	if (typeof(the_sound.Play) == "undefined") {
		return;
	}
	the_sound.Play();
}

NP_initialize();
