function Quiz()
{
this.AddQuestion = Quiz_AddQuestion;
this.RandomizeQuestions = Quiz_RandomizeQuestions;
this.HasAllGuesses = Quiz_HasAllGuesses;
this.Evaluate = Quiz_EvaluateQuestions;
this.Render = Quiz_Render;
this.AddScore = Quiz_AddScore;
this.GetPossiblePoints = Quiz_GetPossiblePoints;
this.GetAwardedPoints = Quiz_GetAwardedPoints;
this.GetPercentage = Quiz_GetPercentage;
this.SetQuestionNumberStyle = Quiz_SetQuestionNumberStyle;
this.SetQuestionNumberCssClass = Quiz_SetQuestionNumberCssClass;
this.SetRequireAllGuesses = Quiz_SetRequireAllGuesses;
this.SetNeedAllGuessesHTML = Quiz_SetNeedAllGuessesHTML;
this.SetNeedAllGuessesCssClass = Quiz_SetNeedAllGuessesCssClass;
this.SetScoreByPercentage = Quiz_SetScoreByPercentage;
this.SetScoreCssClass = Quiz_SetScoreCssClass;
// internal use
this._questions = new Array();
this._scores = new Array();
this._nPossiblePoints = 0;
this._rAwardedPoints = 0;
this._nAwardedPercentage = 0;
this._sQuestionNumberStyle = "1";
this._sQuestionNumberCssClass = "";
this._bRequireAllGuesses = false;
this._sNeedAllGuessesHTML = "";
this._sNeedAllGuessesCssClass = "";
this._bByPercentage = false;
this._sScoreCssClass = "";
}
function Quiz_AddQuestion(oQuestion)
{
this._questions.push(oQuestion);
}
function Quiz_RandomizeQuestions()
{
var aRandom = Quiz_GetRandomArray(this._questions.length);
for (var n = 0; n < aRandom.length; n++)
this._questions[n]._nNumber = aRandom[n];
}
function Quiz_GetRandomArray(nLength)
{
var n;
var aUnusedNumbers = new Array();
for (n = 0; n < nLength; n++)
aUnusedNumbers[n] = n + 1;
var aSelectedNumbers = new Array();
while (aSelectedNumbers.length < nLength)
{
var bNumberUsedAlready;
do
{
n = Math.floor(Math.random() * nLength);
bNumberUsedAlready = (aUnusedNumbers[n] == 0);
}
while (bNumberUsedAlready)
aSelectedNumbers.push(aUnusedNumbers[n]);
aUnusedNumbers[n] = 0;
}
return aSelectedNumbers;
}
function Quiz_HasAllGuesses()
{
var cHasGuesses = 0;
for (var nQuestion = 0; nQuestion < this._questions.length; nQuestion++)
cHasGuesses += this._questions[nQuestion].HasGuess() ? 1 : 0;
return (cHasGuesses == this._questions.length);
}
function Quiz_EvaluateQuestions()
{
Quiz_ConcealAllEvaluations(this);
if (this._bRequireAllGuesses)
{
var elmNeedAllGuesses = document.getElementById("_quiz_divNeedAllGuesses");
if (! this.HasAllGuesses())
{
elmNeedAllGuesses.style.display = "block";
return false;
}
else
elmNeedAllGuesses.style.display = "none";
}
this.GetPossiblePoints();
this._rAwardedPoints = 0;
for (var nQuestion = 0; nQuestion < this._questions.length; nQuestion++)
{
var oQuestion = this._questions[nQuestion];
oQuestion.Evaluate();
this._rAwardedPoints += oQuestion.GetAwardedPoints();
Quiz_RevealEvaluation(oQuestion);
}
this._nAwardedPercentage = Math.floor((this._rAwardedPoints * 100) / this._nPossiblePoints);
var oAwardedScore = null;
for (var nScore = 0; nScore < this._scores.length; nScore++)
{
var oScore = this._scores[nScore];
if (this._bByPercentage)
{
if ((this._nAwardedPercentage >= oScore._rMinScore) && ((oAwardedScore == null) || (oScore._rMinScore > oAwardedScore._rMinScore)))
oAwardedScore = oScore;
}
else
{
if ((this._rAwardedPoints >= oScore._rMinScore) && ((oAwardedScore == null) || (oScore._rMinScore > oAwardedScore._rMinScore)))
oAwardedScore = oScore;
}
}
if (oAwardedScore != null)
{
var elmScore = document.getElementById("_quiz_divScorebox");
if (oAwardedScore._sScoreCssClass.length > 0)
elmScore.className = oAwardedScore._sScoreCssClass;
elmScore.innerHTML = oAwardedScore._sScoreHTML;
elmScore.style.display = "block";
}
return true;
}
function Quiz_ConcealAllEvaluations(oQuiz)
{
var elmScore = document.getElementById("_quiz_divScorebox");
elmScore.style.display = "none";
for (var nQuestion = 0; nQuestion < oQuiz._questions.length; nQuestion++)
{
var oQuestion = oQuiz._questions[nQuestion];
var sQuestionID = "_quiz_Question_" + oQuestion._nNumber.toString();
var elmQuestionEvalCorrect = document.getElementById(sQuestionID + "_Correct");
var elmQuestionEvalIncorrect = document.getElementById(sQuestionID + "_Incorrect");
if (elmQuestionEvalCorrect != null)
elmQuestionEvalCorrect.style.display = "none";
if (elmQuestionEvalIncorrect != null)
elmQuestionEvalIncorrect.style.display = "none";
}
}
function Quiz_RevealEvaluation(oQuestion)
{
var sQuestionID = "_quiz_Question_" + oQuestion._nNumber.toString();
var elmQuestionEvalCorrect = document.getElementById(sQuestionID + "_Correct");
var elmQuestionEvalIncorrect = document.getElementById(sQuestionID + "_Incorrect");
if (oQuestion.GetAwardedPoints() > 0)
{
if (oQuestion._sQuestionType == "MS" && !oQuestion._bAllOrNothing)
{
if (oQuestion._bAnsweredAll)
{
elmQuestionEvalCorrect.style.display = "block";
elmQuestionEvalIncorrect.style.display = "none";
}
else
{
elmQuestionEvalCorrect.style.display = "none";
elmQuestionEvalIncorrect.style.display = "block";
}
}
else
{
elmQuestionEvalCorrect.style.display = "block";
elmQuestionEvalIncorrect.style.display = "none";
}
}
if (oQuestion.GetAwardedPoints() == 0)
{
elmQuestionEvalCorrect.style.display = "none";
elmQuestionEvalIncorrect.style.display = "block";
}
}
function Quiz_Render()
{
Quiz_RenderQuestions(this);
Quiz_RenderNeedAllGuesses(this);
Quiz_RenderScoreBox(this);
}
function Quiz_RenderQuestions(oQuiz)
{
var aSortedQuestions = new Array();
for (var nQuestion = 0; nQuestion < oQuiz._questions.length; nQuestion++)
{
var oQuestion = oQuiz._questions[nQuestion];
if (oQuestion._nNumber == 0)
oQuestion._nNumber = nQuestion + 1;
else if(oQuestion._nNumber > oQuiz._questions.length)
throw "You must renumber your questions from 1 to the number of questions you have.";
else if(aSortedQuestions[oQuestion._nNumber - 1] != null)
throw "You have already used the number " + oQuestion._nNumber + " in a question.";
aSortedQuestions[oQuestion._nNumber - 1] = oQuestion;
}
for (var nQuestion = 0; nQuestion < aSortedQuestions.length; nQuestion++)
Quiz_RenderQuestion(oQuiz, aSortedQuestions[nQuestion]);
}
function Quiz_RenderQuestion(oQuiz, oQuestion)
{
document.write("
0)
document.write(" class=\"" + oQuestion._sQuestionCssClass + "\"");
document.write(">");
var sNumber = Quiz_GetFormattedNumber(oQuestion._nNumber, oQuiz._sQuestionNumberStyle);
document.write(" 0)
document.write(" class=\"" + oQuiz._sQuestionNumberCssClass + "\"");
document.write(">");
document.write(sNumber);
document.write(" ");
document.write("");
document.write(oQuestion._sQuestionHTML);
document.write(" ");
Quiz_RenderAnswers(oQuiz, oQuestion);
document.write("
");
Quiz_RenderEvaluation(oQuiz, oQuestion);
}
function Quiz_RenderAnswers(oQuiz, oQuestion)
{
var aSortedAnswers = new Array();
for (var nAnswer = 0; nAnswer < oQuestion._answers.length; nAnswer++)
{
var oAnswer = oQuestion._answers[nAnswer];
if (oAnswer._nNumber == 0)
oAnswer._nNumber = nAnswer + 1;
else if(oAnswer._nNumber > oQuestion._answers.length)
throw "You must renumber your answers from 1 to the number of answers you have in question '" + oQuestion._nNumber + ".";
else if(aSortedAnswers[oAnswer._nNumber - 1] != null)
{
throw "You have already used the number " + oAnswer._nNumber + " in an answer.";
}
aSortedAnswers[oAnswer._nNumber - 1] = oAnswer;
}
for (var nAnswer = 0; nAnswer < aSortedAnswers.length; nAnswer++)
Quiz_RenderAnswer(oQuiz, oQuestion, aSortedAnswers[nAnswer]);
}
function Quiz_RenderAnswer(oQuiz, oQuestion, oAnswer)
{
document.write(" 0)
document.write(" class=\"" + oAnswer._sAnswerCssClass + "\"");
document.write(">");
var sNumber = Quiz_GetFormattedNumber(oAnswer._nNumber, oQuestion._sAnswerNumberStyle);
document.write(" 0)
document.write(" class=\"" + oQuestion._sAnswerNumberCssClass + "\"");
document.write(">");
document.write(sNumber);
document.write(" ");
document.write("");
var sName = "_quiz_Question_" + oQuestion._nNumber;
var sID = sName + "_Answer_" + oAnswer._nNumber;
if (oQuestion._sQuestionType == "TF" || oQuestion._sQuestionType == "MC" || oQuestion._sQuestionType == "none")
{
document.write(" ");
document.write(" ");
document.write("");
document.write(oAnswer._sAnswerHTML);
document.write(" ");
}
else if(oQuestion._sQuestionType == "MS")
{
document.write(" ");
document.write(" ");
document.write("");
document.write(oAnswer._sAnswerHTML);
document.write(" ");
}
document.write(" ");
document.write("
");
}
function Quiz_RenderEvaluation(oQuiz, oQuestion)
{
document.write(" 0)
document.write(" class=\"" + oQuestion._sCorrectCssClass + "\"");
document.write(" style=\"display:none;\"");
document.write(">");
document.write(oQuestion._sCorrectHTML);
document.write("
");
document.write(" 0)
document.write(" class=\"" + oQuestion._sIncorrectCssClass + "\"");
document.write(" style=\"display:none;\"");
document.write(">");
document.write(oQuestion._sIncorrectHTML);
document.write("
");
}
function Quiz_RenderNeedAllGuesses(oQuiz)
{
document.write(" 0)
document.write(" class=\"" + oQuiz._sNeedAllGuessesCssClass + "\"");
document.write(" style=\"display:none;\"");
document.write(">");
document.write(oQuiz._sNeedAllGuessesHTML);
document.write("
");
}
function Quiz_RenderScoreBox(oQuiz)
{
document.write(" 0)
document.write(" class=\"" + oQuiz._sScoreCssClass + "\"");
document.write(" style=\"display:none;\"");
document.write(">");
document.write("
");
}
function Quiz_GetFormattedNumber(nNumber, sStyle)
{
if ("1" == sStyle)
return nNumber.toString() + ":";
else if("A" == sStyle)
{
var sA = "A";
var cRepeats = Math.floor((nNumber - 1) / 26) + 1;
var sChar = String.fromCharCode(sA.charCodeAt(0) + (nNumber - 1));
var sNumber = "";
while (cRepeats-- > 0)
sNumber = sNumber + sChar;
return sNumber + ":";
}
else if("a" == sStyle)
{
var sA = "a";
var cRepeats = Math.floor((nNumber - 1) / 26) + 1;
var sChar = String.fromCharCode(sA.charCodeAt(0) + (nNumber - 1));
var sNumber = "";
while (cRepeats-- > 0)
sNumber = sNumber + sChar;
return sNumber + ":";
}
else if("." == sStyle)
return "•";
else if("" == sStyle)
return "";
else
return "";
}
function Quiz_AddScore(oScore)
{
this._scores.push(oScore);
}
function Quiz_GetPossiblePoints()
{
var oQuestion = null;
var aQuestions = this._questions;
if (this._nPossiblePoints == 0)
for (var nQuestion = 0; nQuestion < this._questions.length; nQuestion++)
{
var oQuestion = this._questions[nQuestion];
this._nPossiblePoints += oQuestion.GetPossiblePoints();
}
return this._nPossiblePoints;
}
function Quiz_GetAwardedPoints()
{
return this._rAwardedPoints;
}
function Quiz_GetPercentage()
{
return this._nAwardedPercentage;
}
function Quiz_SetQuestionNumberStyle(sStyle)
{
this._sQuestionNumberStyle = sStyle;
}
function Quiz_SetQuestionNumberCssClass(sCssClass)
{
this._sQuestionNumberCssClass = sCssClass;
}
function Quiz_SetRequireAllGuesses(bRequireAll)
{
this._bRequireAllGuesses = bRequireAll;
}
function Quiz_SetNeedAllGuessesHTML(sHTML)
{
this._sNeedAllGuessesHTML = sHTML;
}
function Quiz_SetNeedAllGuessesCssClass(sCssClass)
{
this._sNeedAllGuessesCssClass = sCssClass;
}
function Quiz_SetScoreByPercentage(bByPercentage)
{
this._bByPercentage = bByPercentage;
}
function Question()
{
this.AddAnswer = Quiz_AddAnswer;
this.RandomizeAnswers = Quiz_RandomizeAnswers;
this.Evaluate = Quiz_EvaluateAnswers;
this.HasGuess = Quiz_HasGuess;
this.GetPossiblePoints = Quiz_GetQuestionPossiblePoints;
this.GetAwardedPoints = Quiz_GetQuestionAwardedPoints;
this.SetPossiblePoints = Quiz_SetQuestionPossiblePoints;
this.SetQuestionHTML = Quiz_SetQuestionHTML;
this.SetQuestionCssClass = Quiz_SetQuestionCssClass;
this.SetCorrectGuessHTML = Quiz_SetCorrectGuessHTML;
this.SetCorrectGuessCssClass = Quiz_SetCorrectGuessCssClass;
this.SetIncorrectGuessHTML = Quiz_SetIncorrectGuessHTML;
this.SetIncorrectGuessCssClass = Quiz_SetIncorrectGuessCssClass;
this.SetQuestionType = Quiz_SetQuestionType;
this.SetQuestionNumber = Quiz_SetQuestionNumber;
this.SetRequireAllOrNothing = Quiz_SetAllOrNothing;
this.SetAnswerNumberStyle = Quiz_SetAnswerNumberStyle;
this.SetAnswerNumberCssClass = Quiz_SetAnswerNumberCssClass;
//internal use
this._answers = new Array();
this._sQuestionHTML = "";
this._sQuestionCssClass = "";
this._sCorrectHTML = "";
this._sCorrectCssClass = "";
this._sIncorrectHTML = "";
this._sIncorrectCssClass = "";
this._sQuestionType = "none";
this._nNumber = 0;
this._nPossiblePoints = 0;
this._rAwardedPoints = 0;
this,_bAnsweredAll = false;
this._bAllOrNothing = false;
this._sAnswerNumberStyle = "A";
this._sAnswerNumberCssClass = "";
}
function Quiz_AddAnswer(oAnswer)
{
if (this._sQuestionType == "TF" && this._answers.length > 2)
throw "True/False questions may have only two possible answers."
this._answers.push(oAnswer);
}
function Quiz_RandomizeAnswers()
{
var aRandom = Quiz_GetRandomArray(this._answers.length);
for (var n = 0; n < aRandom.length; n++)
this._answers[n]._nNumber = aRandom[n];
}
function Quiz_EvaluateAnswers()
{
this._rAwardedPoints = 0;
var sQuestionID = "_quiz_Question_" + this._nNumber.toString();
var sAnswerIDPrefix = sQuestionID + "_Answer_";
var elmAnswer = null;
if (this._sQuestionType != "MS") // use for TF and MC questions
{
for (var nAnswer = 0; nAnswer < this._answers.length; nAnswer++)
{
var oAnswer = this._answers[nAnswer];
if (oAnswer._bCorrect == true)
{
elmAnswer = document.getElementById(sAnswerIDPrefix + oAnswer._nNumber.toString());
break;
}
}
if (elmAnswer != null)
{
if (elmAnswer.checked == true)
this._rAwardedPoints = this._nPossiblePoints;
}
else
{
throw "No answers were identified as correct for question " + sQuestionID + " when the quiz was created.";
}
}
else // MS question
{
var nCorrectAnswersChecked = 0;
var nCorrectAnswersUnchecked = 0;
var nPossibleCorrectAnswers = 0;
var nIncorrectAnswersChecked = 0;
var nPossiblePoints = 0;
var nPointsAccumulated = 0
for (var nAnswer = 0; nAnswer < this._answers.length; nAnswer++)
{
var oAnswer = this._answers[nAnswer];
elmAnswer = document.getElementById(sAnswerIDPrefix + oAnswer._nNumber.toString());
if (oAnswer._bCorrect == true)
{
nPossiblePoints += oAnswer._nPoints;
nPossibleCorrectAnswers++;
if (elmAnswer.checked == true)
{
nCorrectAnswersChecked++;
nPointsAccumulated += oAnswer._nPoints;
}
else
nCorrectAnswersUnchecked++;
}
else
{
if (elmAnswer.checked == true)
nIncorrectAnswersChecked++
}
}
if (nPossibleCorrectAnswers == 0)
throw "No answers were identified as correct for question " + sQuestionID + " when the quiz was created.";
if (nPossiblePoints == 0)
nPossiblePoints = 1;
if (this._nPossiblePoints == 0)
this._nPossiblePoints = nPossiblePoints;
if (nIncorrectAnswersChecked > 0)
this._rAwardedPoints = 0;
else
{
if (this._bAllOrNothing == true)
{
if (nCorrectAnswersChecked == nPossibleCorrectAnswers)
this._rAwardedPoints = this._nPossiblePoints;
else
this._rAwardedPoints = 0;
this._bAnsweredAll = (this._rAwardedPoints > 0);
}
else
{
this._bAnsweredAll = (nCorrectAnswersUnchecked == 0);
this._rAwardedPoints = (nPointsAccumulated / nPossiblePoints) * this._nPossiblePoints;
}
}
}
}
function Quiz_HasGuess()
{
var bHasGuess = false;
var sQuestionID = "_quiz_Question_" + this._nNumber.toString();
var sAnswerIDPrefix = sQuestionID + "_Answer_";
for (var nAnswer = 0; nAnswer < this._answers.length; nAnswer++)
{
var sAnswerID = sAnswerIDPrefix + (nAnswer + 1).toString();
var elmAnswerInput = document.getElementById(sAnswerID);
if (elmAnswerInput != null)
{
if (elmAnswerInput.checked == true)
{
bHasGuess = true;
break;
}
}
}
return bHasGuess;
}
function Quiz_SetQuestionHTML(sHTML)
{
this._sQuestionHTML = sHTML;
}
function Quiz_SetQuestionCssClass(sCssClass)
{
this._sQuestionCssClass = sCssClass;
}
function Quiz_SetCorrectGuessHTML(sHTML)
{
this._sCorrectHTML = sHTML;
}
function Quiz_SetCorrectGuessCssClass(sCssClass)
{
this._sCorrectCssClass = sCssClass;
}
function Quiz_SetIncorrectGuessHTML(sHTML)
{
this._sIncorrectHTML = sHTML;
}
function Quiz_SetIncorrectGuessCssClass(sCssClass)
{
this._sIncorrectCssClass = sCssClass;
}
function Quiz_SetQuestionType(sType)
{
var sT = sType.toUpperCase();
if (sT == "TF" || sT == "MC" || sT == "MS")
if (sT == "TF" && this._answers.length > 2)
throw "True/False questions may have only two possible answers."
else
this._sQuestionType = sType;
else
throw "Question type not supported"
}
function Quiz_SetQuestionNumber(nNumber)
{
this._nNumber = nNumber;
}
function Quiz_SetQuestionPossiblePoints(nPoints)
{
this._nPossiblePoints = nPoints;
}
function Quiz_GetQuestionPossiblePoints()
{
if (this._nPossiblePoints == 0)
{
for (var nAnswer = 0; nAnswer < this._answers.length; nAnswer++)
{
var oAnswer = this._answers[nAnswer];
if (oAnswer._bCorrect == true)
{
// for Multiple Selection questions:
// add all possible correct answers to get the possible points
// for all other question types
// get the points of the correct answer with the most points (even though there should only be one correct answer)
this._nPossiblePoints = (this._sQuestionType == "MS" ? this._nPossiblePoints + oAnswer._nPoints : Math.max(this._nPossiblePoints, oAnswer._nPoints));
}
}
}
return this._nPossiblePoints;
}
function Quiz_GetQuestionAwardedPoints()
{
return this._rAwardedPoints;
}
function Quiz_SetAllOrNothing(bAllOrNothing)
{
this._bAllOrNothing = bAllOrNothing;
}
function Quiz_SetAnswerNumberStyle(sStyle)
{
this._sAnswerNumberStyle = sStyle;
}
function Quiz_SetAnswerNumberCssClass(sCssClass)
{
this._sAnswerNumberCssClass = sCssClass;
}
function Answer()
{
this.SetAnswerHTML = Quiz_SetAnswerHTML;
this.SetAnswerCssClass = Quiz_SetAnswerCssClass;
this.SetPointsForCorrectGuess = Quiz_SetPointsForCorrectGuess;
this.SetAnswerNumber = Quiz_SetAnswerNumber;
this.SetCorrect = Quiz_SetCorrect;
//internal use
this._SAnswerHTML = "";
this._sAnswerCssClass = "";
this._nPoints = 1;
this._nNumber = 0;
this._bCorrect = false;
}
function Quiz_SetAnswerHTML(sHTML)
{
this._sAnswerHTML = sHTML;
}
function Quiz_SetAnswerCssClass(sCssClass)
{
this._sAnswerCssClass = sCssClass;
}
function Quiz_SetPointsForCorrectGuess(nPoints)
{
this._nPoints = nPoints;
}
function Quiz_SetAnswerNumber(nNumber)
{
this._nNumber = nNumber;
}
function Quiz_SetCorrect(bCorrect)
{
this._bCorrect = bCorrect;
}
function Score()
{
this.SetScoreHTML = Quiz_SetScoreHTML;
this.SetScoreCssClass = Quiz_SetScoreCssClass;
this.SetMinScore = Quiz_SetMinScore;
//internal use
this._sScoreHTML = "";
this._sScoreCssClass = "";
this._rMinScore = 0;
}
function Quiz_SetScoreHTML(sHTML)
{
this._sScoreHTML = sHTML;
}
function Quiz_SetScoreCssClass(sCssClass)
{
this._sScoreCssClass = sCssClass;
}
function Quiz_SetMinScore(rPercentageOrPoints)
{
this._rMinScore = rPercentageOrPoints;
}