<!--

function onPageLoaded()
{
  checkBrowser();

  if (detected_browser == "Firefox") {
      sectionwidth = "6.0693em";  
      containerwidth = "18.871em";
      containerheight = "21.28em";
  } else if (detected_browser == "Safari") {
      sectionwidth = "6.20em";  
      containerwidth = "18.48em";
      containerheight = "20.98em";
  } else if ((detected_browser == "Explorer") && (version == "6")){
      sectionwidth = "8.44em";   
  } else if ((detected_browser == "Explorer") && (version == "7")){
  }
  
  document.getElementById('sudoku_container').style.width=containerwidth; 
  document.getElementById('sudoku_container').style.height=containerheight;

  for (var sectn=0; sectn<9; sectn++)
  {
    var sectionid = "sudokuSection" + sectn;
    var sectionelt = document.getElementById(sectionid);
    sectionelt.style.width=sectionwidth;
  }

  solnbtns = document.getElementById('sudoku_soln_buttons'); 
  sudokucontainerdiv = document.getElementById('sudoku_container');
  primaryParent = sudokucontainerdiv.parentNode;
  statisticsdiv = document.getElementById('tried_correct_statistics');
}

var playing = false;
var puzzleSolved = false;

var curscore = 0;
var nummoves = 0;
var nummovesdiv;
var numcorrectdiv;

var numPuzzleSquares = 0; // "non-revealed numbers"
var totalPossibleScore;

var sudokucontainerdiv;
var primaryParent;
var statisticsdiv;
var solnbtns;

var detected_browser;
var sectionwidth;
var containerwidth;
var containerheight;

function checkBrowser()
{
    BrowserDetect.init();
    detected_browser = BrowserDetect.browser;
    version = BrowserDetect.version;
    platform = BrowserDetect.OS;
}

function initialStartGame()
{
  var textdiv = document.getElementById('intro_text');
  primaryParent.insertBefore(statisticsdiv, textdiv);
  textdiv.innerHTML='';
  textdiv.parentNode.removeChild(textdiv);

  setupStartStop();
  sudokucontainerdiv.style.display='block';
  statisticsdiv.style.display='block';

  startGame();
}

function startGame()
{
  setStopStartBtns(false, true);
  playing = true;
  nummoves = 0;
  initSudokuGame();

  var leveldiv = document.getElementById('sudoku_level');
  var sels = leveldiv.getElementsByTagName('SELECT');
  var theSel = sels[0];
  theSel.disabled = true;

  curscore = countSquares[level];
  nummovesdiv = document.getElementById('numtried_div');
  nummovesdiv.innerHTML = nummoves;
  numcorrectdiv = document.getElementById('numcorrect_div');
  numcorrectdiv.innerHTML = curscore;

  start_timer();
}

function setSudokuLevel()
{
    var sels = document.getElementsByTagName('SELECT');
    var theSel = sels[0].value;
    if (theSel == "Easy"){
        level = 1;
    } else if (theSel == "Moderate") {
        level = 2;
    } else if (theSel == "Intermediate") {
        level = 3;
    } else if (theSel == "Hard") {
        level = 4;
    } else {
        level = 5;
    }
}

function stopGame()
{
  checkGameFinished();
  totalPossibleScore = numPuzzleSquares * level + 5 * level;
  stop_play();
  showFinalStatus();
  solnbtns.style.display='block';
}

function stop_play()
{
    var cur_time = new Date();
    elapsed_time = cur_time.getTime() - start_time.getTime();
    stop_timer();
    playing = false;

    if (puzzleSolved){
      document.messageform.umsg.value="Sudoku Puzzle Solved!";
    }
	var userNum = sbCookieData.usernum;
 	Record.recordNumCorrectPlusMovesWithMax(taskId, nummoves, curscore, elapsed_time, totalPossibleScore, userNum);
  
    setStopStartBtns(true, false);
    var leveldiv = document.getElementById('sudoku_level');
    var sels = leveldiv.getElementsByTagName('SELECT');
    var theSel = sels[0];
    theSel.disabled = false;
}

/*
 The sudoku board is represented by the massive collection of div's in ~sudoku/body.jsp.
 Each div of class=sudokuSquare has an id="square_j_k", and contains two initially empty spans:
           <span></span><span></span>
 When a game board is setup, the underlying value for the square is written into the innerHTML of
 the first span.  The user's typing is inserted into the second span.
    Note that each small sudokuSquare has a larger (3x3) sudokuSection as its parent; called a group.
*/

var squareObjects = new Array();
var level = 1;	// 1 is lowest level
var countSquares = [36,36,34,32,31,30];
var gameFinished = false;
var highlightedCell;

function initSudokuGame()
{

  curscore = 0; //countSquares[level];
  nummovesdiv = document.getElementById('numtried_div');
  numcorrectdiv = document.getElementById('numcorrect_div');
  nummovesdiv.innerHTML = nummoves;
  numcorrectdiv.innerHTML = curscore;

  gameFinished = false;

    // temporary storage to hold the initial underlying numbers:
  var matrix = new Array();

    // simple initial generation of a correct array of numbers:
  for (var rowCounter=0; rowCounter<9; rowCounter++)
  {
    matrix[rowCounter] = new Array();
    for(var colCounter=0; colCounter<9; colCounter++)
    {
      var number = colCounter/1 + 1 + (rowCounter*3) + Math.floor(rowCounter/3)%3;
      if(number>9)number = number % 9;
      if(number==0)number=9;
      matrix[rowCounter][colCounter] = number;        
    }      
  }
    //Swap pairs of rows within each 3x3 group:
  for (var groupBaseRow=0; groupBaseRow<9; groupBaseRow+=3)
  {
    // swap 3 pairs of rows between groupBaseRow and groupBaseRow+2:
    for (var counter=0; counter<3; counter++)
    {
        // select two distinct random row numbers: 1<=...<=3:
      row1 = Math.floor(Math.random()*3);  
      row2 = Math.floor(Math.random()*3);  
      while(row2==row1){
        row2 = Math.floor(Math.random()*3);  
      }
        // the rows to swap:
      row1 = groupBaseRow + row1;
      row2 = groupBaseRow + row2;      
	// swap them:
      var tmpMatrix = new Array();
      tmpMatrix = matrix[row1];
      matrix[row1] = matrix[row2];
      matrix[row2] = tmpMatrix;         
    }      
  }
    //Swap pairs of columns within each 3x3 group:
  for (var groupBaseCol=0; groupBaseCol<9; groupBaseCol+=3)
  {
    // swap 3 pairs of rows between groupBaseCol and groupBaseCol+2:
    for (var counter=0; counter<3; counter++){
        // select two distinct random col numbers: 1<=...<=3:
      col1 = Math.floor(Math.random()*3);  
      col2 = Math.floor(Math.random()*3);  
      while(col2==col1){
        col2 = Math.floor(Math.random()*3);  
      }
        // the cols to swap:
      col1 = groupBaseCol + col1;
      col2 = groupBaseCol + col2;      
        // swap them:
      for (var row_num=0; row_num<matrix.length; row_num++)
      {
        var tmpMatrixValue = matrix[row_num][col1];
        matrix[row_num][col1] = matrix[row_num][col2];        
        matrix[row_num][col2] = tmpMatrixValue;        
      }
    }  
  }
  
    // Now insert the underlying numbers from matrix in the
    // left [0] span of the appropriate sudokuSquares,
    // and also the right [2] user&solution-entry span;
    // setup the onclick events for the sudokuSquares,
    // and save all the sudokuSquare entities on the array(list) squareObjects.
  for (var rowNum=0; rowNum<matrix.length; rowNum++)
  {
    for (var colNum=0; colNum<matrix[rowNum].length; colNum++)
    {
      var obj = document.getElementById('square_' + rowNum + '_' + colNum);
      var spanObjects = obj.getElementsByTagName('SPAN');
      
      var span = spanObjects[0];
     
      span.innerHTML = matrix[rowNum][colNum];    
      span.style.display='none';  
      spanObjects[2].innerHTML=matrix[rowNum][colNum];  
      spanObjects[2].style.display='none'; 
      
      spanObjects[1].innerHTML = '';
      spanObjects[1].style.display = '';
      spanObjects[1].style.color='#000';  

      obj.onclick = highlightSquare;
          
      squareObjects.push(obj);            
    }      
  }
    // setup the onkeydown event (for insertions):
  if(document.all){
    document.body.onkeydown = insertNumber;
  }else{
    document.documentElement.onkeydown = insertNumber;
  }
    // clear the record-keeping areas:
  newGame();
    // do an additional shuffle:
//  shuffleBoard();
  showColumnsInGroup();
}

// Called when the user mouse clicks on a square.
function highlightSquare(e,inputObj)
{
  if (!inputObj){
    inputObj = this;
  }
    // clicked on a "revealed number" square; do nothing & return:
  if (inputObj.style.backgroundColor){
    return;
  }
    // game is already done; do nothing & return:
  if (gameFinished){
    return;
  }

    // there was a previously highlighted cell, different from the clicked cell:
  if (highlightedCell && highlightedCell!=inputObj){
    highlightedCell.style.backgroundColor='';
  }

    // if we are here, the clicked square is ok for focus; 
  inputObj.style.backgroundColor='yellow';
  highlightedCell = inputObj;

  if(document.all)inputObj.focus();
}

// Erases and resets the user's record-keeping areas (the spans in the square divs)
// without changing the underlying sudoku board values.
function newGame()
{
  highlightedCell = null;
  var obj = document.getElementById('sudoku_container');
  var subObjects = obj.getElementsByTagName('DIV');
  for (var  i=0; i<subObjects.length; i++){
    if(subObjects[i].className=='sudokuSquare')
    {
      subObjects[i].style.backgroundColor='';  
      var spans = subObjects[i].getElementsByTagName('SPAN');
      spans[0].style.display='none';
      spans[1].innerHTML = '';
      spans[2].innerHTML = '';
      spans[2].style.display='none';
    }
  }	
}

function showColumnsInGroup()
{
  var object = document.getElementById('sudoku');
  var cellsRevealed = new Array();
  var numberArray = new Array();
  var groupCountArray = new Array();
  var maxInGroup=5;

     // constraints:
     // at most maxInGroup squares revealed in each (parent) group;
     // 

  if (level<=0){ level=1; }
  if (level==1){
    maxInGroup=4;
  }

    // reveal countSquares[level] randomly selected squares:
  for (var counter=0; counter<countSquares[level]; counter++)
  {
    do{
        // square to reveal:
      var row = Math.floor(Math.random()*9);
      var col = Math.floor(Math.random()*9);
      var obj = document.getElementById('square_' + row + '_' + col);
        // 3x3 group containing the selected square:
      var parentID = obj.parentNode.id;
        // get the span containing the underlying number:
      var span = obj.getElementsByTagName('SPAN')[0];  
      if (!numberArray[span.innerHTML]){
        numberArray[span.innerHTML]=0;
      }
      if (!groupCountArray[parentID]){
        groupCountArray[parentID]=0;
      }
    }
    while( cellsRevealed[row + '_' + col] || 
           numberArray[span.innerHTML] > (3+Math.ceil(level/2) ) || 
           groupCountArray[parentID]>=maxInGroup  );

    cellsRevealed[row + '_' + col] = true;
    if (!numberArray[span.innerHTML]){
      numberArray[span.innerHTML]=0;
    }
    numberArray[span.innerHTML]++;
    groupCountArray[parentID]++;
    showCell(obj);
  }
}

function showCell(inputDiv)
{
  var span = inputDiv.getElementsByTagName('SPAN')[0];
  span.style.display='';
  inputDiv.style.backgroundColor='#DDD';
  span.style.color='#317082';
  var typingSpan = inputDiv.getElementsByTagName('SPAN')[1];
  typingSpan.style.display='none';			
}



var allOk = true;
// Called at various points to test whether the user has successfully solved the puzzle:
// Also computes the current score together with the total number of non-revealed number squares
function checkGameFinished()
{
  var obj = document.getElementById('sudoku_container');
  var subDivs = obj.getElementsByTagName('DIV');
    // tmpscore is initialized to the number of revealed numbers:
  var tmpscore = countSquares[level];
   // this will count the number of "non-revealed numbers":
  numPuzzleSquares = 0; 
  for (var i=0; i<subDivs.length; i++)
  {
      // check the small sudoku squares which are not "revealed numbers":
    if( subDivs[i].className.indexOf('sudokuSquare')>=0 && 
         (subDivs[i].style.backgroundColor == 'yellow' || !subDivs[i].style.backgroundColor) )
    {
      numPuzzleSquares++;
      var spans = subDivs[i].getElementsByTagName('SPAN');
         // underlying number [0] different from [1] (= either blank or user's input);
         // so puzzle is not solved:
      if(spans[0].innerHTML != spans[1].innerHTML){
        allOk=false;
      } else {
          tmpscore++;
      }
    }  
  }
  curscore = (tmpscore - countSquares[level]) * level;

  nummovesdiv = document.getElementById('numtried_div');
  numcorrectdiv = document.getElementById('numcorrect_div');
  nummovesdiv.innerHTML = nummoves;
  numcorrectdiv.innerHTML = curscore;
}
function isGameFinished()
{
   checkGameFinished();
   if(allOk){
     gameFinished=true;
     curscore += 5 * level;
     numcorrectdiv = document.getElementById('numcorrect_div');
     numcorrectdiv.innerHTML = curscore;
     puzzleSolved = true;
     stop_play();
  } 
}

function insertNumber(e)
{
  if(document.all)e = event;
  e.preventDefault();
  e.stopPropagation();
  if(!highlightedCell)return;
  if(gameFinished)return;
  if (e.keyCode) code = e.keyCode; else if (e.which) code = e.which;
  
  var numbers = highlightedCell.id.split('_');

  var row = numbers[1]/1;
  var col = numbers[2]/1;
  var nextObject = false;
    
//  if (e.metaKey || e.ctrlKey || e.altKey){
//        return true;
//  } else
  if(code==39 || code==9){ // Right arrow or tab
    if(col<8){
      nextObject = document.getElementById('square_' + row + '_' + (col/1+1));
      if(nextObject.style.backgroundColor){
        while(col<8 && nextObject.style.backgroundColor){
          col = col+1;
          nextObject = document.getElementById('square_' + row + '_' + col);
        }
      }        
    }
    if(nextObject != null && nextObject){
	    highlightSquare(false,nextObject);
	    nextObject.focus();
    }
    return false;
  }
  if(code==37){ // Left arrow
    if(col>0){
      nextObject = document.getElementById('square_' + row + '_' + (col/1-1));
      if(nextObject.style.backgroundColor){
        while(col>0 && nextObject.style.backgroundColor){
          col = col-1;
          nextObject = document.getElementById('square_' + row + '_' + col);
        }
      }
      if(nextObject.style.backgroundColor)nextObject = false;
    }
    if(nextObject != null && nextObject){
	    highlightSquare(false,nextObject);
	    nextObject.focus();
    }
    return false;
  }
  if(code==38){ // Up arrow
    if(row>0){
      nextObject = document.getElementById('square_' + (row-1) + '_' + col);
      if(nextObject.style.backgroundColor){
        while(row>0 && nextObject.style.backgroundColor){
          row = row-1;
          nextObject = document.getElementById('square_' + row + '_' + col);
        }
      }        
    }
    if(nextObject != null && nextObject){
	    highlightSquare(false,nextObject);
	    nextObject.focus();
    }
    return false;
  }    
  if(code==40){ // Down arrow
    if(row<8){
      nextObject = document.getElementById('square_' + (row+1) + '_' + col);
      if(nextObject.style.backgroundColor){
        while(row<8 && nextObject.style.backgroundColor){
          row = row+1;
          nextObject = document.getElementById('square_' + row + '_' + col);
        }
      }  
    }
    if(nextObject != null && nextObject){
	    highlightSquare(false,nextObject);
	    nextObject.focus();
    }
    return false;
  }
  
  if(nextObject != null && nextObject){
    highlightSquare(false,nextObject);
    nextObject.focus();
  }
  
  
  var spans = highlightedCell.getElementsByTagName('SPAN');

  if(code==46 || code==8){  // Delete
    spans[1].innerHTML = '';
    // suppress attempting to enter the backspace in the square:
    if(code==8) {
      return false;
    }
  }
  if(code>96 && code<=105)code-=48;
  if(code>48 && code<=57){        
    var theChar = String.fromCharCode(code);
    spans[1].innerHTML = theChar;
    spans[2].innerHTML = theChar; 
    spans[2].style.display='none';

    nummoves++;
    nummovesdiv = document.getElementById('numtried_div');
    nummovesdiv.innerHTML = nummoves;
  }    
  
  isGameFinished();
}


function showFinalStatus()
{
  var obj = document.getElementById('sudoku_container');
  var subDivs = obj.getElementsByTagName('DIV');
  for (var i=0; i<subDivs.length; i++)
  {
      // check the small sudoku squares which are not "revealed numbers":
    if( subDivs[i].className.indexOf('sudokuSquare')>=0 && 
         (subDivs[i].style.backgroundColor == 'yellow' || 
          subDivs[i].style.backgroundColor == 'red' || 
          !subDivs[i].style.backgroundColor) )
    {
      var spans = subDivs[i].getElementsByTagName('SPAN');
         // underlying number [0] is solution; [1] (= either blank or user's input);
         // so this puzzle square is not correct:
      spans[1].innerHTML = spans[2].innerHTML;
      if(spans[0].innerHTML != spans[1].innerHTML)
      {
        var parentDiv = spans[1].parentNode;
        parentDiv.style.backgroundColor = "red";
      } 
    }  
  }
}


function showSolution()
{
  var obj = document.getElementById('sudoku_container');
  var subDivs = obj.getElementsByTagName('DIV');
  for (var i=0; i<subDivs.length; i++)
  {
      // check the small sudoku squares which are not "revealed numbers":
    if( subDivs[i].className.indexOf('sudokuSquare')>=0 && 
         (subDivs[i].style.backgroundColor == 'yellow' 
          || subDivs[i].style.backgroundColor == 'red' 
          || !subDivs[i].style.backgroundColor) )
    {
      numPuzzleSquares++;
      var spans = subDivs[i].getElementsByTagName('SPAN');
         // underlying number [0] different from [1] (= either blank or user's input);
         // so puzzle is not solved:
      if(spans[0].innerHTML != spans[1].innerHTML){
        var parentDiv = spans[1].parentNode;
        parentDiv.style.backgroundColor = "";
        spans[1].innerHTML = spans[0].innerHTML;
      } 
    }  
  }
}

	//--------Instructions code -------------

function showInstructions()
{
    var ipath= 'sudoku-puzzle-instructions'
    var entry_win=window.open(
               ipath,
               'Sudoku_Puzzle_Instructions',
               'height=670,width=650');
    return false;
}

function displayPerfData(response)
{
    genericDisplayPerfData('Sudoku', response);
    return false;
}

// -->
