1 //CORE CODE FOR CHECKING SHORT ANSWER GUESSES AGAINST ANSWER ARRAYS
3 var CaseSensitive = [boolCaseSensitive];
4 var ShowAlsoCorrect = [boolShowAlsoCorrect];
5 var PleaseEnter = '[strPleaseEnter]';
6 var HybridTries = [intHybridTries];
7 var PartlyIncorrect = '[strPartlyIncorrect]';
8 var CorrectList = '[strCorrectList]';
9 var NextCorrect = '[strNextCorrect]';
12 function TrackFocus(BoxID){
14 CurrBox = document.getElementById(BoxID);
21 function TypeChars(Chars){
23 //Following check added for 6.0.4.4 to avoid error message in IE6
24 if (CurrBox.style.display != 'none'){
25 CurrBox.value += Chars;
31 function CheckGuess(Guess, Answer, CaseSensitive, PercentCorrect, Feedback){
34 this.PercentCorrect = PercentCorrect;
35 this.Feedback = Feedback;
36 if (CaseSensitive == false){
37 this.WorkingGuess = Guess.toLowerCase();
38 this.WorkingAnswer = Answer.toLowerCase();
41 this.WorkingGuess = Guess;
42 this.WorkingAnswer = Answer;
45 this.HintPenalty = 1/Answer.length;
46 this.CorrectStart = '';
47 this.WrongMiddle = '';
49 this.PercentMatch = 0;
53 function CheckGuess_DoCheck(){
54 //Check if it's an exact match
55 if (this.WorkingAnswer == this.WorkingGuess){
56 this.PercentMatch = 100;
57 this.CorrectStart = this.Guess;
60 //Figure out how much of the beginning is correct
63 while (this.WorkingAnswer.charAt(i) == this.WorkingGuess.charAt(i)){
68 this.Hint = this.Answer.charAt(i);
70 this.CorrectStart = this.Guess.substring(0, i);
72 //If there's more to the answer, look at the rest of it
73 if (i<this.Guess.length){
75 //Figure out how much of the end is correct
76 var j = this.WorkingGuess.length-1;
77 var k = this.WorkingAnswer.length-1;
78 while ((j>=i)&&((this.WorkingAnswer.charAt(k) == this.WorkingGuess.charAt(j))&&(CorrectChars < this.Answer.length))){
83 this.CorrectEnd = this.Guess.substring(j+1, this.Guess.length);
84 this.WrongMiddle = this.Guess.substring(i, j+1);
86 if (TrimString(this.WrongMiddle).length < 1){this.WrongMiddle = '_';}
87 //Calculate match score based on how much of the guess is correct
88 if (CorrectChars < this.Answer.length){
89 this.PercentMatch = Math.floor(100*CorrectChars)/this.Answer.length;
92 this.PercentMatch = Math.floor((100 * CorrectChars)/this.Guess.length);
96 CheckGuess.prototype.DoCheck = CheckGuess_DoCheck;
98 function CheckAnswerArray(CaseSensitive){
99 this.CaseSensitive = CaseSensitive;
100 this.Answers = new Array();
104 this.HintPenalty = 0;
105 this.MatchedAnswerLength = 1;
106 this.CompleteMatch = false;
110 function CheckAnswerArray_AddAnswer(Guess, Answer, PercentCorrect, Feedback){
111 this.Answers.push(new CheckGuess(Guess, Answer, this.CaseSensitive, PercentCorrect, Feedback));
114 CheckAnswerArray.prototype.AddAnswer = CheckAnswerArray_AddAnswer;
116 function CheckAnswerArray_ClearAll(){
117 this.Answers.length = 0;
120 CheckAnswerArray.prototype.ClearAll = CheckAnswerArray_ClearAll;
122 function CheckAnswerArray_GetBestMatch(){
123 //First check for a 100% match
124 for (var i=0; i<this.Answers.length; i++){
125 if (this.Answers[i].PercentMatch == 100){
126 this.Feedback = this.Answers[i].Feedback;
127 this.Score = this.Answers[i].PercentCorrect;
128 this.CompleteMatch = true;
133 //Now check for the best alternative match
134 var PercentMatch = 0;
136 for (i=0; i<this.Answers.length; i++){
137 if ((this.Answers[i].PercentMatch > PercentMatch)&&(this.Answers[i].PercentCorrect == 100)){
139 PercentMatch = this.Answers[i].PercentMatch;
143 this.Score = this.Answers[BestMatch].PercentMatch;
144 this.Feedback = PartlyIncorrect + ' ';
145 this.Feedback += '<span class="PartialAnswer">' + this.Answers[BestMatch].CorrectStart;
146 this.Feedback += '<span class="Highlight">' + this.Answers[BestMatch].WrongMiddle + '</span>';
147 this.Feedback += this.Answers[BestMatch].CorrectEnd + '</span>';
148 this.Hint = '<span class="PartialAnswer">' + this.Answers[BestMatch].CorrectStart;
149 this.Hint += '<span class="Highlight">' + this.Answers[BestMatch].Hint + '</span></span>';
150 this.HintPenalty = this.Answers[BestMatch].HintPenalty;
158 CheckAnswerArray.prototype.GetBestMatch = CheckAnswerArray_GetBestMatch;
160 function CheckShortAnswer(QNum){
161 //bail if question doesn't exist or exercise finished
162 if ((State[QNum].length < 1)||(Finished == true)){return;}
164 //bail if question already complete
165 if (State[QNum][0] > -1){return;}
167 //Get the guess (TrimString added to fix bug for 6.0.4.3)
168 var G = TrimString(document.getElementById('Q_' + QNum + '_Guess').value);
170 //If no guess, bail with message; no penalty
172 ShowMessage(PleaseEnter);
179 //Create a check object
180 var CA = new CheckAnswerArray(CaseSensitive);
183 for (var ANum=0; ANum<I[QNum][3].length; ANum++){
184 CA.AddAnswer(G, I[QNum][3][ANum][0], I[QNum][3][ANum][3], I[QNum][3][ANum][1]);
188 //Store any match in the state tracking field
189 if (State[QNum][5].length > 0){State[QNum][5] += ' | ';}
190 if (CA.MatchNum > -1){
191 State[QNum][5] += String.fromCharCode(65+CA.MatchNum);
193 //Else store the student's answer
198 //Add the percent correct value for this answer to the Q State (works for all
199 //situations, wrong or right)
200 State[QNum][3] += CA.Score;
202 //Now branch, based on the nature of the match
203 //Is it a complete match?
204 if (CA.CompleteMatch == true){
206 //Is it with a wrong answer, or a right answer?
207 if (CA.Score == 100){
209 CalculateShortAnsQuestionScore(QNum);
210 //Get correct answer list if required, assuming there are any other correct alternatives
211 if (ShowAlsoCorrect == true){
212 var AlsoCorrectList = GetCorrectList(QNum, G, false);
213 if (AlsoCorrectList.length > 0){
214 CA.Feedback += '<br />' + CorrectList + '<br />' + AlsoCorrectList;
218 //Get the overall score and add it to the feedback
219 if (ContinuousScoring == true){
220 CalculateOverallScore();
221 CA.Feedback += '<br />' + YourScoreIs + ' ' + Score + '%.';
222 WriteToInstructions(YourScoreIs + ' ' + Score + '%.');
224 ShowMessage(CA.Feedback);
226 ReplaceGuessBox(QNum, G);
232 //Otherwise, it's a match to a predicted wrong/partially correct, or a partial
233 //match to a right answer
234 if (CA.Feedback.length < 1){CA.Feedback = DefaultWrong;}
235 //Remove any previous score unless exercise is finished (6.0.3.8+)
236 if (Finished == false){
237 WriteToInstructions(strInstructions);
239 ShowMessage(CA.Feedback);
241 //If necessary, switch a hybrid question to m/c
242 if (State[QNum][2] >= HybridTries){
243 SwitchHybridDisplay(QNum);
247 function CalculateShortAnsQuestionScore(QNum){
248 var Tries = State[QNum][2] + State[QNum][4]; //include tries and hint penalties;
249 var PercentCorrect = State[QNum][3];
250 var HintPenalties = State[QNum][4];
252 //Make sure it's not already complete
253 if (State[QNum][0] < 0){
254 if (HintPenalties >= 1){
258 State[QNum][0] = (PercentCorrect/(100*Tries));
260 if (State[QNum][0] < 0){
266 function SwitchHybridDisplay(QNum){
267 if (document.getElementById('Q_' + QNum + '_Hybrid_MC') != null){
268 document.getElementById('Q_' + QNum + '_Hybrid_MC').style.display = '';
269 if (document.getElementById('Q_' + QNum + '_SA') != null){
270 document.getElementById('Q_' + QNum + '_SA').style.display = 'none';
275 function GetCorrectArray(QNum){
276 var Result = new Array();
277 for (var ANum=0; ANum<I[QNum][3].length; ANum++){
278 if (I[QNum][3][ANum][2] == 1){ //This is an acceptable correct answer
279 Result.push(I[QNum][3][ANum][0]);
285 function GetCorrectList(QNum, Answer, IncludeAnswer){
286 var As = GetCorrectArray(QNum);
288 for (var ANum=0; ANum<As.length; ANum++){
289 if ((IncludeAnswer == true)||(As[ANum] != Answer)){
290 Result += As[ANum] + '<br />';
296 function GetFirstCorrectAnswer(QNum){
297 var As = GetCorrectArray(QNum);
306 function ReplaceGuessBox(QNum, Ans){
307 if (document.getElementById('Q_' + QNum + '_SA') != null){
308 var El = document.getElementById('Q_' + QNum + '_SA');
309 while (El.childNodes.length > 0){
310 El.removeChild(El.childNodes[0]);
312 var A = document.createElement('span');
313 A.setAttribute('class', 'Answer');
314 var T = document.createTextNode(Ans);
322 function ShowAnswers(QNum){
323 //bail if question doesn't exist or exercise finished
324 if ((State[QNum].length < 1)||(Finished == true)){return;}
326 //Get the answer list to display
327 var Ans = GetCorrectList(QNum, '', false);
328 Ans = CorrectList + '<br />' + Ans;
333 //Set the score for this question to 0 if no
334 if (State[QNum][0] < 1){
338 //Get the first correct answer
339 var FirstAns = GetFirstCorrectAnswer(QNum);
341 //Replace the textbox
342 ReplaceGuessBox(QNum, FirstAns);
344 //Remove any current score
345 WriteToInstructions(strInstructions);
347 //This may be the last, so check finished status
355 function ShowHint(QNum){
356 //bail if question doesn't exist or exercise finished
357 if ((State[QNum].length < 1)||(Finished == true)){return;}
359 //bail if question already complete
360 if (State[QNum][0] > -1){return;}
363 var G = document.getElementById('Q_' + QNum + '_Guess').value;
365 //If no guess, give the first correct bit
367 var Ans = GetFirstCorrectAnswer(QNum);
368 var Hint = Ans.charAt(0);
369 ShowMessage(NextCorrect + '<br />' + Hint);
371 State[QNum][4] += (1/Ans.length);
378 //Create a check object
379 var CA = new CheckAnswerArray(CaseSensitive);
382 for (var ANum=0; ANum<I[QNum][3].length; ANum++){
383 //Use only correct answers
384 if (I[QNum][3][ANum][2] == 1){
385 CA.AddAnswer(G, I[QNum][3][ANum][0], I[QNum][3][ANum][3], I[QNum][3][ANum][1]);
389 if (CA.CompleteMatch == true){
391 CheckShortAnswer(QNum);
395 if (CA.Hint.length > 0){
396 ShowMessage(NextCorrect + '<br />' + CA.Hint);
397 State[QNum][4] += CA.HintPenalty;
400 ShowMessage(DefaultWrong + '<br />' + NextCorrect + '<br />' + GetFirstCorrectAnswer(QNum).charAt(0));