<?php  // $Id: play.php,v 1.23 2012/08/15 09:26:55 bdaloukas Exp $

require_once( "../../lib/questionlib.php");

function game_sudoku_continue( $id, $game, $attempt, $sudoku, $endofgame, $context)
{
	global $CFG, $DB, $USER;
	
	if( $endofgame){
		game_updateattempts( $game, $attempt, -1, true);
		$endofgame = false;
	}	

	if( $attempt != false and $sudoku != false){
		return game_sudoku_play( $id, $game, $attempt, $sudoku, false, false, $context);
	}
	
	if( $attempt == false){
		$attempt = game_addattempt( $game);
	}
	
	//new game
    srand( (double)microtime()*1000000);
    
	$recsudoku = getrandomsudoku();
	if( $recsudoku == false){
		print_error( 'Empty sudoku database');
	}

    $newrec = new stdClass();
	$newrec->id = $attempt->id;
	$newrec->guess = '';
	$newrec->data = $recsudoku->data;
	$newrec->opened  = $recsudoku->opened;

	$need = 81 - $recsudoku->opened;
	$closed = game_sudoku_getclosed( $newrec->data);
	$n = min( count($closed), $need);
	//if the teacher set the maximum number of questions
	if( $game->param2 > 0){
		if( $game->param2 < $n){
			$n = $game->param2;
		}
	}
	$recs = game_questions_selectrandom( $game, CONST_GAME_TRIES_REPETITION*$n);
	
	if( $recs === false){
	    mysql_execute( "DELETE FROM {game_sudoku} WHERE id={$game->id}");
		print_error( get_string( 'no_questions', 'game'));
	}
	
	$closed = array_rand($closed, $n);

    $selected_recs = game_select_from_repetitions( $game, $recs, $n);

	if(!game_insert_record('game_sudoku', $newrec)){
		print_error('error inserting in game_sudoku');
	}

	$i = 0;
    $field = ($game->sourcemodule == 'glossary' ? 'glossaryentryid' : 'questionid');
	foreach( $recs as $rec)
	{
	    if( $game->sourcemodule == 'glossary')
	        $key = $rec->glossaryentryid;
	    else
	        $key = $rec->questionid;
	        
        if( !array_key_exists( $key, $selected_recs))
            continue;

		$query = new stdClass();
		$query->attemptid = $newrec->id;
		$query->gamekind = $game->gamekind;
		$query->gameid = $game->id;
		$query->userid = $USER->id;
		$query->col = $closed[ $i++];
		$query->sourcemodule = $game->sourcemodule;
		$query->questionid = $rec->questionid;
		$query->glossaryentryid = $rec->glossaryentryid;
		$query->score = 0;
		if( ($query->id = $DB->insert_record( 'game_queries', $query)) == 0){
			print_error( 'error inserting in game_queries');
		}

        game_update_repetitions($game->id, $USER->id, $query->questionid, $query->glossaryentryid);
	}

	game_updateattempts( $game, $attempt, 0, 0);

	game_sudoku_play( $id, $game, $attempt, $newrec, false, false, $context);
}

function game_sudoku_play( $id, $game, $attempt, $sudoku, $onlyshow, $showsolution, $context)
{
    $offsetquestions = game_sudoku_compute_offsetquestions( $game->sourcemodule, $attempt, $numbers, $correctquestions);

	if( $game->toptext != ''){
		echo $game->toptext.'<br>';
	}
	
	game_sudoku_showsudoku( $sudoku->data, $sudoku->guess, true, $showsolution, $offsetquestions, $correctquestions, $id, $attempt, $game);
	switch( $game->sourcemodule)
	{
	case 'quiz':
	case 'question':
		game_sudoku_showquestions_quiz( $id, $game, $attempt, $sudoku, $offsetquestions, $numbers, $correctquestions, $onlyshow, $showsolution, $context);
		break;
	case 'glossary':
		game_sudoku_showquestions_glossary( $id, $game, $attempt, $sudoku, $offsetquestions, $numbers, $correctquestions, $onlyshow, $showsolution);
		break;
	}
	
	if( $game->bottomtext != ''){
		echo '<br>'.$game->bottomtext;
	}	
}

//returns a map with an offset and id of each question
function game_sudoku_compute_offsetquestions( $sourcemodule, $attempt, &$numbers, &$correctquestions)
{
    global $CFG,$DB;

    $select = "attemptid = $attempt->id";

	$fields = 'id, col, score';
	switch( $sourcemodule)
	{
	case 'quiz':
	case 'question':
		$fields .= ',questionid as id2';
		break;
	case 'glossary':
		$fields .= ',glossaryentryid as id2';
		break;
	}
    if( ($recs = $DB->get_records_select( 'game_queries', $select, null, '', $fields)) == false){
  	    $DB->execute( "DELETE FROM {$CFG->prefix}game_sudoku WHERE id={$attempt->id}");
        print_error( 'There are no questions '.$attempt->id);
    }
    $offsetquestions = array();
    $numbers = array();
	$correctquestions = array();
    foreach( $recs as $rec){
        $offsetquestions[ $rec->col] = $rec->id2;
        $numbers[ $rec->id2] = $rec->col;
        if($rec->score == 1)
            $correctquestions[ $rec->col] = 1;
    }

    ksort( $offsetquestions);

    return $offsetquestions;
}

function getrandomsudoku()
{
	global $DB;

    $count = $DB->count_records( 'game_sudoku_database');
    if( $count == 0)
    {
        require_once(dirname(__FILE__) . '/../db/importsudoku.php');

        $count = $DB->count_records( 'game_sudoku_database');
        if( $count == 0)
            return false;    
    }

	$i = mt_rand( 0, $count - 1);

	if( ($recs = $DB->get_records( 'game_sudoku_database', null, '', '*', $i, 1)) != false)
	{
		foreach( $recs as $rec){
			return $rec;
		}
	}

	return false;
}


function game_sudoku_getclosed( $data)
{
	$a = array();
  
	$n = game_strlen( $data);
	for( $i=1; $i <= $n; $i++)
	{
		$c = game_substr( $data, $i-1, 1);
		if( $c >= "1" and $c <= "9")
			$a[ $i] = $i;
	}

	return $a;
}

function game_sudoku_showsudoku( $data, $guess, $bShowLegend, $bShowSolution, $offsetquestions, $correctquestions, $id, $attempt, $game)
{
	global $CFG, $DB;
	
	$correct = $count = 0;
	
	echo "<br>\r\n";
	echo '<table border="1" style="border-collapse: separate; border-spacing: 0px;">';
    $pos=0;
    for( $i=0; $i <= 2; $i++)
    {
		echo "<tr>";
		for( $j=0; $j <= 2; $j++)
		{
			echo '<td><table border="1" width="100%">';
			for( $k1=0; $k1 <= 2; $k1++)
			{
				echo "<tr>";
				for( $k2=0; $k2 <= 2; $k2++)
				{
					$s = substr( $data, $pos, 1);
					$g = substr( $guess, $pos, 1);
					$pos++;
					if( $g != 0){
						$s = $g;
					}
					if( $s >= "1" and $s <= "9")
					{
						//closed number
						if( $bShowLegend)
						{
							//show legend
							if( $bShowSolution == false)
							{
								if( !array_key_exists( $pos, $correctquestions)){
									if( array_key_exists( $pos, $offsetquestions))
									{
										if( $s != $g){
											$s = '<input type="submit" value="A'.$pos.'" onclick="OnCheck( '.$pos.');" />';
										}
									}else if( $g == 0)
									{
										$s = '<input type="submit" value="" onclick="OnCheck( '.$pos.');" />';
									}
								}else
								{
									//correct question
									$count++;
								}
							}
							echo '<td width=33% style="text-align: center; padding: .6em; color: red; font-weight: lighter; font-size: 1em;">'.$s.'</td>';
						}else
						{
							//not show legend
							echo '<td width=33% style="text-align: center; padding: .6em; color: red; font-weight: lighter; font-size: 1em;">&nbsp;</td>';
						}
					}else
					{
						$s = strpos( "-ABCDEFGHI", $s);
						$count++;
						echo '<td width=33% style="text-align: center; padding: .6em; color: black; font-weight: lighter; font-size: 1em;">'.$s.'</td>';
					}
				}
				echo "</tr>";
			}
			echo "</table></td>\r\n";
		}
		echo "</tr>";
    }
	echo "</table>\r\n";
	
	?>
	<script language="javascript">
			function OnCheck( pos)
			{
				s = window.prompt( "<?php echo get_string ( 'sudoku_guessnumber', 'game') ?>", "");
				
				if( s < "1")
					return;
				if( s > "9")
					return;

				window.location.href = "<?php echo $CFG->wwwroot.'/mod/game/attempt.php?action=sudokucheckn&id='.$id ?>&pos=" + pos + "&num=" + s;
			}
		</script>
	<?php	

	//Here are the congratulations
	if( $attempt->timefinish){
		return $count;
	}
	
	if( count($offsetquestions) != count( $correctquestions)){
		return $count;
	}
	
	if (! $cm = $DB->get_record( 'course_modules', array( 'id' => $id))) {
		print_error( "Course Module ID was incorrect id=$id");
	}
	
	echo '<B><br>'.get_string( 'win', 'game').'</B><BR>';	
	echo '<br>';	
	echo "<a href=\"$CFG->wwwroot/mod/game/attempt.php?id=$id\">".get_string( 'nextgame', 'game').'</a> &nbsp; &nbsp; &nbsp; &nbsp; ';
	echo "<a href=\"$CFG->wwwroot/course/view.php?id=$cm->course\">".get_string( 'finish', 'game').'</a> ';
	
	game_updateattempts( $game, $attempt, 1, 1);

    return $count;
}


function game_sudoku_getquestionlist( $offsetquestions)
{
    $questionlist = '';
    foreach( $offsetquestions as $q){
        if( $q != 0){
            $questionlist .= ','.$q;
        }
    }
    $questionlist = substr( $questionlist, 1);
	
    if ($questionlist == '') {
        print_error( get_string('no_questions', 'game'));
    }

	return $questionlist;
}

function game_sudoku_getglossaryentries( $game, $offsetentries, &$entrylist, $numbers)
{
	global $DB;

    $entrylist = implode( ',', $offsetentries);
	
    if ($entrylist == '') {
        print_error( get_string( 'sudoku_noentriesfound', 'game'));
    }

    // Load the questions
    if (!$entries = $DB->get_records_select( 'glossary_entries', "id IN ($entrylist)")) {
        print_error( get_string('sudoku_noentriesfound', 'game'));
    }
	
    return $entries;
}

function game_sudoku_showquestions_quiz( $id, $game, $attempt, $sudoku, $offsetquestions, $numbers, $correctquestions, $onlyshow, $showsolution, $context)
{
	global $CFG;

	$questionlist = game_sudoku_getquestionlist( $offsetquestions);
    $questions = game_sudoku_getquestions( $questionlist);
	
	//I will sort with the number of each question
	$questions2 = array();
	foreach( $questions as $q){
		$ofs = $numbers[ $q->id];
		$questions2[ $ofs] = $q;
	}
	ksort( $questions2);
	
	if( count( $questions2) == 0){
		game_sudoku_showquestion_onfinish( $id, $game, $attempt, $sudoku);
		return;
	}
	
	$number=0;
	$found = false;
    foreach ($questions2 as $question) {
        $ofs = $numbers[ $question->id];
        if( array_key_exists( $ofs, $correctquestions)){
            continue;   //I don't show the correct answers
        }
        
        if( $found == false)
        {
            $found = true;
    	    // Start the form
            echo "<form id=\"responseform\" method=\"post\" action=\"{$CFG->wwwroot}/mod/game/attempt.php\" onclick=\"this.autocomplete='off'\">\n";
	        if( ($onlyshow === false) and ($showsolution  === false)){
		        echo "<br><center><input type=\"submit\" name=\"submit\" value=\"".get_string('sudoku_submit', 'game')."\">";
		
		        echo " &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<input type=\"submit\" name=\"finishattempt\" value=\"".
		            get_string('sudoku_finishattemptbutton', 'game')."\">";
	        }

            // Add a hidden field with the quiz id
            echo '<div>';
            echo '<input type="hidden" name="id" value="' . s($id) . "\" />\n";
            echo '<input type="hidden" name="action" value="sudokucheck" />';

	        // Print all the questions

            // Add a hidden field with questionids
            echo '<input type="hidden" name="questionids" value="'.$questionlist."\" />\n";        
        }
                
		$number = "<a name=\"a$ofs\">A$ofs</a>";
		
		game_print_question( $game, $question, $context);
    }

    if( $found)
    {
        echo "</div>";

        // Finish the form
        echo '</div>';
	    if( ($onlyshow === false) and ($showsolution === false)){
	    	echo "<center><input type=\"submit\" name=\"submit\" value=\"".get_string('sudoku_submit', 'game')."\"></center>\n";
	    }

        echo "</form>\n";
    }
}

//show the sudoku and glossaryentries
function game_sudoku_showquestions_glossary( $id, $game, $attempt, $sudoku, $offsetentries, $numbers, $correctentries, $onlyshow, $showsolution)
{
	global $CFG;
	
    $entries = game_sudoku_getglossaryentries( $game, $offsetentries, $questionlist, $numbers);

	//I will sort with the number of each question
	$entries2 = array();
	foreach( $entries as $q){
		$ofs = $numbers[ $q->id];
		$entries2[ $ofs] = $q;
	}
	ksort( $entries2);
	
	if( count( $entries2) == 0){
		game_sudoku_showquestion_onfinish( $id, $game, $attempt, $sudoku);
		return;
	}

	/// Start the form
    echo "<br><form id=\"responseform\" method=\"post\" action=\"{$CFG->wwwroot}/mod/game/attempt.php\" onclick=\"this.autocomplete='off'\">\n";
	
	if( $onlyshow)
	    $hasquestions = false;
	else
	    $hasquestions = ( count($correctentries) < count( $entries2));

	if( $hasquestions){
	    echo "<center><input type=\"submit\" name=\"submit\" value=\"".get_string('sudoku_submit', 'game')."\"></center>\n";
	}

    // Add a hidden field with the quiz id
    echo '<div>';
    echo '<input type="hidden" name="id" value="' . s($id) . "\" />\n";
    echo '<input type="hidden" name="action" value="sudokucheckg" />';

	/// Print all the questions

    // Add a hidden field with questionids
    echo '<input type="hidden" name="questionids" value="'.$questionlist."\" />\n";

	$number=0;
    foreach ($entries2 as $entry) {
        $ofs = $numbers[ $entry->id];
        if( array_key_exists( $ofs, $correctentries)){
            continue;   //I don't show the correct answers
        }

		$s = '<b>A'.$ofs.'.</b> '.game_filtertext( $entry->definition, 0).'<br>';
		if( $showsolution){
			$s .= get_string( 'answer').': ';
			$s .= "<input type=\"text\" name=\"resp{$entry->id}\" value=\"$entry->concept\"size=30 /><br>";
		}else if( $onlyshow === false){	
			$s .= get_string( 'answer').': ';
			$s .= "<input type=\"text\" name=\"resp{$entry->id}\" size=30 /><br>";
		}
		echo $s."<hr>\r\n";
    }

    echo "</div>";

    // Finish the form
	if( $hasquestions){
		echo "<center><input type=\"submit\" name=\"submit\" value=\"".get_string('sudoku_submit', 'game')."\"></center>\n";
	}

    echo "</form>\n";
}

function game_sudoku_showquestion_onfinish( $id, $game, $attempt, $sudoku)
{
	if( !set_field( 'game_attempts', 'finish', 1, 'id', $attempt->id)){
		print_error( "game_sudoku_showquestion_onfinish: Can't update game_attempts id=$attempt->id");
	}
		
	echo '<B>'.get_string( 'win', 'game').'</B><BR>';	
	echo '<br>';	
	echo "<a href=\"{$CFG->wwwroot}/mod/game/attempt.php?id=$id\">".get_string( 'nextgame', 'game').'</a> &nbsp; &nbsp; &nbsp; &nbsp; ';
	echo "<a href=\"{$CFG->wwwroot}?id=$id\">".get_string( 'finish', 'game').'</a> ';	
}

function game_sudoku_checkanswers()
{
    $responses = data_submitted();

    $actions = question_extract_responses($questions, $responses, $event);
}

function game_sudoku_check_questions( $id, $game, $attempt, $sudoku, $finishattempt, $course)
{
    global $QTYPES, $DB;

    $responses = data_submitted();

    $offsetquestions = game_sudoku_compute_offsetquestions( $game->sourcemodule, $attempt, $numbers, $correctquestions);

	$questionlist = game_sudoku_getquestionlist( $offsetquestions);
	
    $questions = game_sudoku_getquestions( $questionlist);

    foreach($questions as $question) {
		$query = new stdClass();

        $select = "attemptid=$attempt->id";
        $select .= " AND questionid=$question->id";
        
        if( ($query->id = $DB->get_field_select( 'game_queries', 'id', $select)) == 0){
			die( "problem game_sudoku_check_questions (select=$select)");
            continue;
        }

        $name = "resp{$question->id}_";
        if( !isset( $responses->$name))
            continue;        
        
        $grade = game_grade_responses( $question, $responses, 100, $answertext);
        if( $grade < 50){
			//wrong answer
			game_update_queries( $game, $attempt, $query, $grade/100, $answertext);
            continue;
        }

        //correct answer
		game_update_queries( $game, $attempt, $query, 1, $answertext);
    }

    game_sudoku_check_last( $id, $game, $attempt, $sudoku, $finishattempt, $course);
}

function game_sudoku_check_glossaryentries( $id, $game, $attempt, $sudoku, $finishattempt, $course)
{
    global $QTYPES, $DB;

    $responses = data_submitted();

	//this function returns offsetentries, numbers, correctquestions
    $offsetentries = game_sudoku_compute_offsetquestions( $game->sourcemodule, $attempt, $numbers, $correctquestions);

	$entrieslist = game_sudoku_getquestionlist( $offsetentries );

    // Load the glossary entries
    if (!($entries = $DB->get_records_select( 'glossary_entries', "id IN ($entrieslist)"))) {
        print_error( get_string('noglossaryentriesfound', 'game'));
    }
    foreach($entries as $entry) {
        $answerundefined = optional_param('resp'.$entry->id, 'undefined', PARAM_TEXT);
        if( $answerundefined == 'undefined'){
            continue;
        }
        $answer = optional_param('resp'.$entry->id, '', PARAM_TEXT);
		if( $answer == ''){
			continue;
		}
		if( game_upper( $entry->concept) != game_upper( $answer)){
			continue;
		}
        //correct answer
        $select = "attemptid=$attempt->id";
        $select .= " AND glossaryentryid=$entry->id";
            
		$query = new stdClass();
        if( ($query->id = $DB->get_field_select( 'game_queries', 'id', $select)) == 0){
			echo "not found $select<br>";
            continue;
        }

        game_update_queries( $game, $attempt, $query, 1, $answer);
    }

	game_sudoku_check_last( $id, $game, $attempt, $sudoku, $finishattempt, $course);

    return true;
}


//this is the last function after submiting the answers.
function game_sudoku_check_last( $id, $game, $attempt, $sudoku, $finishattempt, $course)
{
	global $CFG, $DB;
	
	$correct = $DB->get_field_select( 'game_queries', 'COUNT(*) AS c', "attemptid=$attempt->id AND score > 0.9");
	$all = $DB->get_field_select( 'game_queries', 'COUNT(*) AS c', "attemptid=$attempt->id");
	
	if( $all){
		$grade = $correct / $all;
	}else
	{
		$grade = 0;
	}
	game_updateattempts( $game, $attempt, $grade, $finishattempt);
}

function game_sudoku_check_number( $id, $game, $attempt, $sudoku, $pos, $num, $context)
{
    global $DB;

	$correct = game_substr( $sudoku->data, $pos-1, 1);

	if( $correct != $num)
	{
		game_sudoku_play( $id, $game, $attempt, $sudoku, false, false, $context);
		return;
	}
	
	$leng = game_strlen( $sudoku->guess);
	$lend = game_strlen( $sudoku->data);
	if( $leng < $lend){
		$sudoku->guess .= str_repeat( ' ', $lend - $leng);
	}
	game_setchar( $sudoku->guess, $pos-1, $correct);
	
	if( !$DB->set_field_select('game_sudoku', 'guess', $sudoku->guess, "id=$sudoku->id")){
		print_error( 'game_sudoku_check_number: Cannot update table game_sudoku');
	}
	
	game_sudoku_play( $id, $game, $attempt, $sudoku, false, false, $context);
}