﻿// quizzerjs javascript functions

// session variable

var queryParams;

var curq;
var questionSequenceStr;
var questionSequence;

var attempts;
var choiceDisplaySequence;
var choiceDisplaySequenceStr

var score = 0;
var newScore = 0;
var correctAnswerStr;


// functions

function getQueryParams() {

	var queryString = window.location.search.substring(1); 

	if (queryString == '') {
		return null;
	}
	
	// Array to store parameters
	var queryParams = new Array();
 
 	// save full query string as parameter
 	queryParams['QUERY_STRING'] = queryString;
 	
	// multi-value separator
	multivalueSeparator = ', ';
	
	if (queryString.length < 1) { return queryParams; }

	var params = queryString.split('&');
	
	for (p in params) {
		var curParam = params[p];

		var paramParts = curParam.split('=');

		// if param missing 
		if (paramParts.length == 1) {
			paramParts[1] = '';
		}
		
		// unencode value
		paramParts[1] = paramParts[1].replace('+', ' ');
		paramParts[1] = unescape(paramParts[1]);
		
		if (queryParams[paramParts[0]]) {
			// parameter already exits, append additional value
			queryParams[paramParts[0]] += multivalueSeparator + paramParts[1];
		} else {
			// create new parameter in array
			queryParams[paramParts[0]] = paramParts[1];
		}
	}
	
	return queryParams;

} // getQueryParams


function genRandomSequence(lowerBound, upperBound, sequenceCount) {

	var numRemainingValues = upperBound - lowerBound + 1;
	if (numRemainingValues < sequenceCount) {
		sequenceCount = numRemainingValues;
	}
	
	// create an array of the possible sequence index values
	var curSourceSequenceIndex = 0;
	var possibleValues = new Array;
	for (var s=0; s<numRemainingValues; s++) {
		possibleValues[s] = curSourceSequenceIndex;
		curSourceSequenceIndex++;
	}
	
	// create an array of random sequence index values	
	var randomList = new Array;
	var curDestSequenceIndex = 0;
	while (curDestSequenceIndex < sequenceCount) {
		// to not include upper bound, remove the plus one from the following
		selectedPosition = Math.floor((numRemainingValues)*Math.random());
		var selectedValue = possibleValues.splice(selectedPosition, 1);
		randomList[curDestSequenceIndex] = selectedValue;
		numRemainingValues--;
		curDestSequenceIndex++;
	}

	return randomList;

} // genRandomSequence


function genQuestionSequence(quizInfo) {

	var questionSequence = new Array;

	// if number to ask is wildcarded, set value to number of questions
	if (quizInfo["numToAsk"] == "*") {
		quizInfo["numToAsk"] = quizInfo["numQuestions"];
	}

	// create a random or straight number sequence
	if (quizInfo["randomQ"] == true) {
		questionSequence = genRandomSequence(0, quizInfo["numQuestions"]-1, quizInfo["numToAsk"]);
	} else {
		for (var q=0; q<quizInfo["numToAsk"]; q++) {
			questionSequence[q] = q;
		}
	}

	return questionSequence;
	
} // genQuestionSequence


function genChoiceSequence(numChoices, randomizeChoices) {

	var choiceSequence = new Array;

	if (randomizeChoices) {
		choiceSequence = genRandomSequence(0, numChoices-1, numChoices);
	} else {
		for (var c=0; c<numChoices; c++) {
			choiceSequence[c] = c;
		}
	}
	
	return choiceSequence;

} // genChoiceSequence


function getSessionData() {
	queryParams = getQueryParams();
	questionSequenceStr = queryParams['qseq'];
	questionSequence = questionSequenceStr.split(',');
	curq = parseInt(queryParams['curq']);
	attempts = parseInt(queryParams['at']);
	score = parseInt(queryParams['score']);
} // getSessionData


function displayFeedback() {
	var feedback;
	var correctAnswer;
	
	if ((queryParams != null) && (queryParams['fb'] != null) && (queryParams['fb'] != '')) {
		feedback = queryParams['fb'];
	}
	if ((queryParams != null) && (queryParams['ca'] != null) && (queryParams['ca'] != '')) {
		correctAnswer = decodeURIComponent(queryParams['ca']);
	}
	if (feedback == 'tr') {
		document.write('<p><strong>That\'s right!</strong></p><p><strong>Your score is ' + score + ' </strong></p>');
	} else if (feedback == 'ta') {
		document.write('<p><strong>Try again!</strong></p>');
	} else if (feedback == 'ca') {
		document.write('<p><strong>Sorry, that\'s not right. The correct answer is ' + correctAnswer + '.</strong></p><p><strong>Your score is ' + score + ' </strong></p>');
	}

} // displayFeedback


function displayChoices() {
	
	if ((queryParams == null) || (queryParams['cseq'] == null) || (queryParams['cseq'] == '')) {
		choiceDisplaySequence = genChoiceSequence(choices.length, randomizeChoices);
		choiceDisplaySequenceStr = choiceDisplaySequence.join(',');
	} else {
		choiceDisplaySequenceStr = queryParams['cseq'];
		choiceDisplaySequence = choiceDisplaySequenceStr.split(',');
	}
	
	if (questionType == 'mchoice') {
		for (var curDisplayChoice=0; curDisplayChoice<choiceDisplaySequence.length; curDisplayChoice++) {
			var curChoice = choiceDisplaySequence[curDisplayChoice];	
			document.write('<input type="radio" name="choices" id="choice' + curChoice + '" value="' + curChoice + '">' + choices[curChoice] + '<br/>\n');
		}
	} else if (questionType == 'mcorrect') {
		for (var curDisplayChoice=0; curDisplayChoice<choiceDisplaySequence.length; curDisplayChoice++) {
			var curChoice = choiceDisplaySequence[curDisplayChoice];	
			document.write('<input type="checkbox" name="choices" id="choice' + curChoice + '" value="' + curChoice + '">' + choices[curChoice] + '<br/>\n');
		}
	}
	
} // displayChoices


function checkAnswer() {

	if (questionType == 'mchoice') {
		checkMChoiceAnswer();
	} else if (questionType == 'mcorrect') {
		checkMCorrectAnswer();
	} else if (questionType == 'fill') {
		checkFillAnswer();
	} else {
		alert("ERROR: Unrecognized question type:" + questionType);
	}
	
} // checkAnswer


function checkMChoiceAnswer() {
	var choiceSelected = false;
	var correctAnswer = false;
	
	// retrieve first choice
	var curChoiceNum = 0;
	var curChoice = document.getElementById("choice" + curChoiceNum);
	while (curChoice != null) {
		if (curChoice.checked) {
			if (curChoice.value == cc.toString()) {
				correctAnswer = true;
				choiceSelected = true;
				break;
			} else {
				choiceSelected = true;
			}
		}
		
		// get next choice
		curChoiceNum++;
		curChoice = document.getElementById("choice" + curChoiceNum);
	}
	if (!choiceSelected) {
		alert('You must choose an answer.');
	} else if (correctAnswer) {
		updateScore();
		choiceDisplaySequenceStr = '';
		attempts = 0;
		displayPage('tr');
	} else {
		attempts++;
		if (attempts < attemptPoints.length) {
			displayPage('ta');
		} else {
			correctAnswerStr = choices[cc];
			choiceDisplaySequenceStr = '';
			attempts = 0;
			displayPage('ca');
		}
	}

} // checkMChoiceAnswer


function checkMCorrectAnswer() {
	var choiceSelected = false;
	var incorrectAnswer = false;
	
	// create correct choices array
	var correctChoices = new Array;
	for (i=0; i<=choices.length; i++) {
		correctChoices[i] = false;
	}
	for (i=0; i<=ccs.length; i++) {
		correctChoices[ccs[i]] = true;
	}
	
	// retrieve first choice
	var curChoiceNum = 0;
	var curChoice = document.getElementById("choice" + curChoiceNum);
	while (curChoice != null) {
		if (curChoice.checked) {
			// selected a choice
			if (correctChoices[curChoice.value] == true) {
				// choice is correct and was selected by user
				choiceSelected = true;
			} else {
				// choice is incorrect, shouldn't have been selected by user
				incorrectAnswer = true;
				choiceSelected = true;
			}
		} else {
			// didn't select a choice
			if (correctChoices[curChoice.value] == false) {
				// choice is incorrect and wasn't selected by user
				choiceSelected = true;
			} else {
				// choice is correct, should have been selected by user
				incorrectAnswer = true;
				choiceSelected = true;
			}
		}
		
		// get next choice
		curChoiceNum++;
		curChoice = document.getElementById("choice" + curChoiceNum);
	}
	if (!choiceSelected) {
		alert('You must choose an answer.');
	} else if (incorrectAnswer == false) {
		updateScore();
		choiceDisplaySequenceStr = '';
		attempts = 0;
		displayPage('tr');
	} else {
		attempts++;
		if (attempts < attemptPoints.length) {
			displayPage('ta');
		} else {
			correctAnswerStr = '';
			for (i=0; i<ccs.length; i++) {
				correctAnswerStr += choices[ccs[i]] + ',';
			}
			choiceDisplaySequenceStr = '';
			attempts = 0;
			displayPage('ca');
		}
	}

} // checkMCorrectAnswer

function checkFillAnswer() {
	var correctAnswer = false;
	var answer;
	
	// retrieve user's answer
	var answerElement = document.getElementById("answer");
	var answer = answerElement.value;

	// clean up spaces
	answer = answer.replace(/\s+/g, ' ');
	answer = answer.replace(/^ /, '');
	answer = answer.replace(/ $/, '');
	answer = answer.replace(/\s*,\s*/g, ',');

	// make sure an answer was entered
	if (answer == '') {
		alert('You must enter an answer.');
	}
	
	// cycle through each answer and see if user's answer is an exact match
	var correctAnswers = ca.split(';');
	for (i=0; i<correctAnswers.length; i++) {
		var curCorrectAnswer = correctAnswers[i];
		if (correctAnswerStr == '') {
			correctAnswerStr = curCorrectAnswer;
		}
		curCorrectAnswer = curCorrectAnswer.replace(/\s*,\s*/g, ',');
		if (answer.toLowerCase() == curCorrectAnswer.toLowerCase()) {
			correctAnswer = true;
			correctAnswerStr = curCorrectAnswer;
			break;
		}
	}
	
	if (correctAnswer == true) {
		updateScore();
		choiceDisplaySequenceStr = '';
		attempts = 0;
		displayPage('tr');
	} else {
		attempts++;
		if (attempts < attemptPoints.length) {
			displayPage('ta');
		} else {
			choiceDisplaySequenceStr = '';
			attempts = 0;
			displayPage('ca');
		}
	}
		
} // checkFillAnswer


function updateScore() {

	if (attempts < attemptPoints.length) {
		newScore = score + attemptPoints[attempts];
	} else {
		alert(attempts + ',' + attemptPoints.length);
	}
	
} // updateScore


function displayPage(feedback) {

	var pageLocation;
	
	var nextq = curq;
	var nextScore = score;
	if (feedback == 'tr') {
		nextq++;
		nextScore = newScore;
	} else if (feedback == 'ca') {
		nextq++;
	}
	
	if (nextq < questionSequence.length) {
		var questionStr = questionSequence[nextq].toString();
		if (questionSequence[nextq] < 9) {
			questionStr = '0' + questionStr;
		}
		if (choiceDisplaySequenceStr != '') {
			pageLocation = questionStr + '.html?qseq=' + questionSequenceStr + '&cseq=' + choiceDisplaySequenceStr + '&at=' + attempts.toString() + '&fb=' + feedback + '&score=' + nextScore.toString() + '&curq=' + nextq.toString();
		} else {
			pageLocation = questionStr + '.html?qseq=' + questionSequenceStr + '&at=' + attempts.toString() + '&fb=' + feedback + '&score=' + nextScore.toString() + '&curq=' + nextq.toString();
		}
	} else {
		pageLocation = 'game_over.html?qseq=' + questionSequenceStr + '&fb=' + feedback + '&score=' + nextScore.toString();
	}

	if (feedback == 'ca') {
		pageLocation += '&ca=' + encodeURIComponent(correctAnswerStr);
	}
	
	// redirect to 
	document.location = pageLocation;
	
} // displayPage


function endGame() {

	document.location = 'game_over.html?qseq=' + questionSequenceStr + '&score=' + score.toString();
	
} // endGame
