<!--
		
// THE FOLLOWING VARIABLES AND FUNCTIONS CONTROL THE USERINTERFACE	

// general variables

var randomnumber = 0 ; 					// intermittent random number storage
var Qs = 0 ;							// number of available questions
var lastnorepeats = new Array () ;		// norepeats array
var counttonorepeats = 0 ; 				// counting up to norepeats
var norepeats = 0 ;						// maximal norepeats-array size
var showquestion = true ;				// question display control
var tape = '' ;							// output string

// question properties

var Knitem = new Array () ; 			// question properties array
var answers = new Array () ;			// question possible correct answers array property
var questiontext = ' ' ;				// question text property
var probability = 1 ;					// question drop value property

// performance tracking variables

var numberset = 0 ;						// number of set questions
var numberright = 0 ;					// number of right answers
var performance = 0 ;					// performance score in %
var nextone = false ;					// prevents logging correct answers more than once
var changed = false ;					// temporary evaluation rules restriction

// spell check control variables

var correctOption = '' ; 					// correct answer option
var preferredAnswer = '' ; 					// preferred answer
var excludeList = [ '-', 'h', ' ', '.', '&rsquo;' ] ;
											// characters to be excluded on condensation
var sizelimit = 4 ;							// no errors allowed below this answer length
var caseInsensitiveDefault = true ;			// case dependence of spell check
var byRulesDefault = true ;					// condensation by rules
var allowMismatchDefault = true ;			// true spelling error check
var mismatchlimit = 1 ;						// number of true spelling eroors allowed

var caseInsensitive = caseInsensitiveDefault ;
var byRules = byRulesDefault ;
var allowMismatch = allowMismatchDefault ;

// initialize questions
function Knit( questiontext, answers, filesource, probability ) {

	Qs++ ;
	if ( filesource == 'none' ) filesource = eval ( "'" + filesource + Qs + "'" ) ;
	Knitem[Qs] = [ questiontext, answers, filesource, probability ] ;
	norepeats = Math.round( Qs * norepeatfrac )
	
}	// end Knit


// reset form, counter variables and arrays
function Prepare() {

	// initialize variables
	nextone = false ;
	Qs = -1 ;
	lastnorepeats.length = 0 ;
	counttonorepeats = 0 ;
	Knit(' ', [' '], ' ', ' ', 0) ;
	numberright = 0 ;
	performance = 0 ;
	numberset = 0 ;
	
}	// end prepare


// function to set a questions in TheQuestion form of the page
function setaquestion () {
	
	showquestion = true ;
	question = 0 ;

	// check if one or more subject areas have been selected
	if ( Qs == 0 ) alert ('Select one or more subjects for the test!') ;

	// set a random question
	if ( Qs != 0 && stepper == 0 ) {
	
		document.getElementById('selectionTable').style.display = 'none' ;
		document.getElementById('changeSelection').style.display = 'block' ;
	
		nextone = true ;
		tryagain = true ;

		// select a question and test if it has been used recently
		while ( question == 0 ) {
			randomnumber = Math.random()* Qs ;
			question = Math.round(randomnumber) 
			for ( i = 0; i < lastnorepeats.length; i++ ) if ( Knitem[question][1][0] == lastnorepeats[i] ) question = 0 ;
			if ( Math.random() > Knitem[question][3] ) question = 0
		}
		
		// update lastnorepeats array
		lastnorepeats[counttonorepeats] = Knitem[question][1][0] ;
		counttonorepeats++ ;
		if ( counttonorepeats == norepeats) counttonorepeats = 0 ;

		// increment the number of questions set
		numberset++ ;

	}

	// disable question display
	if ( Qs == 0 || ( stepper != 0 && numberset == Qs ) ) {
		if ( Qs > 0 ) alert ('This was the last questions.') ;
		showquestion = false
	}
	
	// sequential stepping through all questions of the selected subjects
	if ( Qs != 0 && stepper != 0 && numberset < Qs ) {
		numberset ++ ;
		question = numberset ;
		nextone = true ;
		tryagain = true ;

		// temporary block of allowMismatch
		if ( Knitem[question][3] < 0 && allowMismatch == true ) {
			allowMismatch = false ;
			changed = true
		}
		// reset allowMismatch
		if ( Knitem[question][3] >= 0 && allowMismatch == false && changed == true ) {
			allowMismatch = true ;
			changed = false
		}
	}	
	
		
	// display the question
	if ( showquestion ) {
		tape =  '<form name="saqquiz" id="saqquiz" action="javascript: Checkanswer();">'
		tape += '<table><tr><td valign="top"><table cellpadding="4" cellspacing="2">' ;
		tape += '<tr><td colspan="2" class="tdbluelight"><p>' + Knitem[question][0] + '</p></td></tr>' ;
		tape += '<tr><td colspan="2" class="tdbluelight"><p class="textsmall"><br>Enter your answer here and hit the return button to check your answer.</p>' ;
		tape += '<input type="text" name="TheAnswer" size="40">&nbsp;&nbsp;<img id="answerImg" src="../Images/answerSAQ.gif" align="absmiddle">' ;
		tape += '</td</tr>' ;
		tape += '<tr><td><p class="textsmall">questions set: ' + numberset ;
		if ( stepper > 0 ) tape += ' of ' + (Qs) ;
		tape += ' % correct: ' ;
		if ( numberset == 1 ) tape += '0' ;
		if ( numberset > 1 ) tape += Math.round( numberright / ( numberset - 1 ) * 100 ) ;
		tape += '</p><td><p class="textsmall"><a href="javascript:setaquestion();"><img src="../Images/next.gif" border="0" align="right">' ;
		tape += '</a></td></tr>' ;
		
		// write a div for a reply to wrong answers
		tape += '<tr><td colspan="2"><div id="reply" style="display: none; border-width: 2px; border-style: solid; border-color: red;' ;
		tape += ' background-color: white; padding: 5px">'
		tape += '</div></td></tr>' ;
		
		tape += '</table></td><td>'
		
		// write the picture
		if ( Knitem[question][2].search('none') == -1 ) {
			tape += '<img src="' + Knitem[question][2] + '" style="border-width: 1px; border-style: solid; border-color: black">' ;
		}
		tape += '</td></tr></table></form>' ;
		
		document.getElementById('Qinterface').innerHTML = tape
		
	}

}	// end setaquestion

function showSelectionTable () {

	document.getElementById('changeSelection').style.display = 'none' ;
	document.getElementById('selectionTable').style.display = 'block' ;
	
}

// THE FOLLOWING FUNTIONS AND VARIABLES EVALUATE THE STUDENT RESPONSE

var condensedAnswer = ' ' ;				// condensed student answer
var condensedCorrect = ' ' ;			// condensed correct answer
var answer = ' ' ;						// student answer to question
var wordlength = 0 ;					// number of characters in the submitted word
var truncatedAnswer = ' ' ;				// courtesy words removed from answer
var tryagain = 'true' ;					// a right answer has not yet been found
var strip = true ;						// strip control
var optcount = 0 ;						// number of correct options
var reply = '' ;						// reply to wrong answers

/* The following function stripps leading and tailing spaces from the student answer.
It also replaces multiple spaces bewteen words by a single space */

function strippSpaces ( word ) {

	var y = 0 ;						// counter variable
	var stripped = new Array () ;	// word stripping array
	var strip = true ;				// space stripping control

	// replace all double spaces by single spaces
	while ( strip ) {
		if ( word.search('  ') != -1 ) word = word.replace('  ',' ') ;
		if ( word.search('  ') == -1 ) strip = false
	} ;	

	// determine the number of remaining characters in the submitted word
	wordlength = word.length ;

	// convert the word string to an array
	for ( y = 0 ; y < wordlength ; y ++ ) stripped[y] = word.charAt(y) ;

	// remove tailing space from students answer
	if ( stripped[stripped.length-1] == ' ' ) stripped.length = stripped.length - 1 ;

	// remove leading space
	stripped.reverse() ;
	if ( stripped[stripped.length-1] == ' ' ) stripped.length = stripped.length - 1 ;
	stripped.reverse() ;
  
	// return the array as a string
	return stripped.join('') ;
	
} ; // end strippSpaces


/* The following function condenses the students answer to the minimum of characters
considered to represent the correct answer */

function condense ( word ) {

	var condensed = new Array () ;					// word condensation array
	var m = 0 ;										// counter variable
	var n = 0 ;										// counter variable
	var endings = [ 'e ', 'ic ', 'es ', 's ' ] ;	// word endings to strip
	var lateSpaceDrop = false ;						// permits striping of spaces in justOneWrong if Stripping was omitted in condense
	
	word = word + ' ' ;

	for ( i = 0 ; i < endings.length ; i ++ ) {
		if ( word.lastIndexOf(endings[i]) != -1  && word.lastIndexOf(endings[i]) == word.length - endings[i].length ) {
			word = word.replace(endings[i],'')
		}
	}
		
	// determine the number of characters in the submitted word
	wordlength = word.length ;
	
	// condense answer (strip double letters, final e, final es, middle h, spaces and dashes)
	for ( i = 0; i < wordlength; i++ ) {
		if ( i == 0 ) {
			includeLetter = true ;
			for ( n = 0; n < excludeList.length; n ++ ) if ( word.charAt(i) == excludeList[n] ) includeLetter = false ;
			if ( includeLetter || word.charAt(i) == "h" ) {
				condensed[m] = word.charAt(i);
				m ++
			}
		}
			
		if ( i != 0 ) {
			includeLetter = true ; 
			for ( n = 0; n < excludeList.length; n ++ ) {
				if ( excludeList[n] == ' ' ) lateSpaceDrop = true ;
				if ( word.charAt(i) == excludeList[n] ) includeLetter = false ;
				if ( word.charAt(i) == ' ' ) includeLetter = true
			}
			if ( includeLetter ) {
				if ( m == 0 ) {
					condensed[m] = word.charAt(i) ;
					m ++
				}	
				if ( m != 0 && word.charAt(i) != condensed[m-1] ) {
					condensed[m] = word.charAt(i) ;
					m ++
				}
			}
		}
	}

	word = condensed.join('') ;

	if ( lateSpaceDrop ) {
		strip = true ;
		while ( strip ) {
			if ( word.search(' ') != -1 ) word = word.replace(' ','') ;
			if ( word.search(' ') == -1 ) strip = false
		}	
	}	

	// join the remaining characters into the condensed word and return it
	return word 

}	// end condense

/* The following function compares two strings and returns true if there is
only one mismatch or one transposition of characters between the string. */

function justOneWrong ( word, correct ) {

	var lengthDifference = 0 ;
	var stillOK = true ;
	var mismatches = 0 ;

	lengthDifference = word.length - correct.length ;
	if ( Math.abs(lengthDifference) > 1 ) stillOK = false ;
 
	if ( lengthDifference == 0 )
		for ( l = 0 ; l < word.length ; l ++ )
			if ( word.charAt(l) != correct.charAt(l) ) 
				if ( word.charAt(l) == correct.charAt(l+1) && word.charAt(l+1) == correct.charAt(l) ) l ++ 
				else mismatches ++ ;
	if ( mismatches > mismatchlimit ) stillOK = false ;	

	if ( stillOK && lengthDifference == 1 )
		for ( l = 0 ; l < correct.length ; l ++ )
			if ( word.charAt(l) != correct.charAt(l) )
				if ( word.substr( l + 1) != correct.substr(l) ) stillOK = false ;
           
	if ( stillOK && lengthDifference == -1 )
		for ( l = 0 ; l < word.length ; l ++ )
			if ( word.charAt(l) != correct.charAt(l) )
				if ( correct.substr( l + 1) != word.substr(l) ) stillOK = false ;

	return stillOK ;

}	// end justOneWrong

/* The following functions analyse the student answer against the possible correct
answers. If necessary the function will use the function called condense to account for
possible spelling errors */

function analyse ( answer, correct ) {

	var i = 0 ;		// counter variable
	var x = 0 ;		// counter variable
	var k = 0 ;		// counter variable
	var tempcorrect = '' ;
		
	// check for a perfect match
	if ( answer == correct ) {
		tryagain = false ;
	}
	
	// check for a case-insensitive match
	if ( tryagain && caseInsensitive )
		if ( answer.toLowerCase() == correct.toLowerCase() && tryagain ) {
			tryagain = false ;
		}
					
	// check for a case-insensitive imperfect match but WITHOUT accepting one missing, added or incorrect character
	if ( tryagain && byRules ) {
		if ( correct.toLowerCase().length > sizelimit ) {
			condensedCorrect = condense ( correct.toLowerCase() , false ) ;
			if ( condense( answer.toLowerCase() , false ) == condensedCorrect ) {
				tryagain = false ;
				reply =  'Yeah, the correct answer is ' + correctOption ;
				reply += ', but your spelling and/or phrasing may be a bit off - improve it if necessary.' ;
			}
		}
	}
    
	// check for a case-insensitive imperfect match ACCEPTING one missing, added or
	// incorrect character and excluding a courtesy word if present
	if ( tryagain && allowMismatch ) {
		if ( answer.toLowerCase().length > sizelimit ) {
			if ( justOneWrong( condense( answer.toLowerCase() ), condense ( correct.toLowerCase() ) )  ) {
				tryagain = false ;
				reply =  'Yeah, the correct answer is ' + correctOption ;
				reply += ', but your spelling is a bit off - improve it.' ;
			}
		}
	}
	
}	// end analyse

function Checkanswer () {
	
	reply = '' ;
	correctOption = '' ;

	if ( !nextone ) alert ('Please set a new question before answering.')
	else {
		if ( nextone ) {
			
			// read answer from the exam form
			answer = document.forms['saqquiz'].TheAnswer.value ;
			answer = answer.replace("'",'&rsquo;') ;
			answer = strippSpaces(answer) ;
			for ( optcount = 0 ; optcount < Knitem[question][1].length ; optcount ++ ) {
				correctOption = Knitem[question][1][optcount] ;
				if ( optcount == 0 ) preferredAnswer = correctOption ;
				// alert (preferredAnswer) ;
				if ( correctOption.search('%I') != -1 ) {
					caseInsensitive = false ;
					correctOption = correctOption.replace('%I','') ;
					if ( optcount == 0 ) preferredAnswer = preferredAnswer.replace('%I','') 
				}
				if ( correctOption.search('%R') != -1 ) {
					byRules = false ;
					correctOption = correctOption.replace('%R','')
					if ( optcount == 0 ) preferredAnswer = preferredAnswer.replace('%R','') 
				}
				if ( correctOption.search('%M') != -1 ) {
					allowMismatch = false ;
					correctOption = correctOption.replace('%M','')
					if ( optcount == 0 ) preferredAnswer = preferredAnswer.replace('%M','') 
				}
				if ( tryagain ) analyse ( answer, correctOption )
				caseInsensitive = caseInsensitiveDefault ;
				byRules = byRulesDefault ;
				allowMismatch = allowMismatchDefault ;
			}
			if ( !tryagain ) {
				numberright ++ ;
				nextone = false
			}
		}

		// no matching right answer was found
		if ( tryagain && nextone ) {
			document.getElementById('answerImg').src = '../Images/wrong.gif'
			reply =  'Sorry, but your answer is not correct. The correct answer is<br><span class="textbold">' ;
			reply += preferredAnswer + '</span>';
			document.getElementById('reply').innerHTML = reply ;
			document.getElementById('reply').style.display = 'block' ;
			nextone = false
		}		
	}
	
	if ( !tryagain && reply != '' ) {
		document.getElementById('reply').style.display = 'block' ;
		document.getElementById('reply').innerHTML = reply ;
	}
	if ( !tryagain ) document.getElementById('answerImg').src = '../Images/right.gif' ;	
		

}	// end Checkanswer

// -->

