// This script has been tested in IE5+ and NS6+ under Windows XP

// engine customization
var showRawScore = false ;					// if true: shows uncorrected % score instead of % score corrected for random right answers
var stemsize = 4 ;									// stemnumber of the mcqs
var allowNotes = true ;							// allows the recording of questions

// variable declarations
var randomnumber = 0 ; 							// intermittent random number storage
var Qs = -1 ;												// number of available knowledge items
var Knitem = new Array() ; 					// knowledge item array
var rightone = 0 ; 									// knowledge item array number of the right answer
var areacode = 0 ;									// subject areacode of the question
var wrong = new Array() ;						// distractor array
var theQuestion = 'text' ;					// the text of the question
var lesstheory = false ;						// allows deselection of true-false questions
var negpos = false ;								// negative-positive question identifier

// administration variables
var lastnorepeats = new Array() ;		// norepeats-sources array
var counttonorepeats = 0 ; 					// counting up to norepeats
var norepeats = 0 ;									// maximal norepeats-sources array size
var CtrlAdmin = new Array() ;				// central administration array

// performance tracking variables
var numberset = 0 ;									// number of set questions
var numberright = 0 ;								// number of right answers
var performance = 0 ;								// performance score, %
var nextone = false ;								// prevents logging correct answers more than once


var Recorder = null ;

function smart_ass () {

	// The smart_ass(essment tool) sends the url of any source materials, the current question and the anwsers to
	// the recorder. Newly recorded questions are appended to list of previously recorded questions.

	var source = ' ' ;
	var record = ' ' ;
	var location = ' ' ;	

	if ( Recorder == null || Recorder.closed ) {
		Recorder = window.open ("","The_Recorder","WIDTH=600,HEIGHT=200,RESIZABLE=YES,SCROLLBARS=YES") ;
		record += '<p>You can copy text from this window and paste it into your word processor.</p>' ;		
	}
	if ( Knitem[rightone][0].search('none') != 0 && Knitem[rightone][0].search('replace') != 0 && Knitem[rightone][0].search('append') != 0 ) source = Knitem[rightone][0] ;
	record += '<p>' + theQuestion ;
	location = self.location.href ;
	location = location.substring( 0, location.indexOf('addons')+7 ) ;
	if ( source != ' ' ) record += '<br>(source - ' + location + source + ')' ;
	record += '</p>' ;
	for ( i = 0 ; i < stemsize ; i ++ ) record += '<p>&nbsp;&nbsp;' + (i+1) + '.&nbsp;&nbsp;' + Knitem[wrong[i]][1][0] + '</p>' ;
	Recorder.document.write(record) ;  
	Recorder.focus()

}	// end smart_ass


function Knit(aa, bb, cc, dd, ee, ff) {

	// Initialize knowledge items
	Qs++ ;
	if ( aa == "none" ) aa = eval ( "'" + aa + Qs + "'" ) ;
	
	// double the probability of theory questions on user demand
	if ( document.forms["Selector"].moretheory.checked && Qtype[cc].length == 2 ) ee = ee * 2 ;
	
	Knitem[Qs] = [ aa, bb, cc, dd, ee, ff] ;
	
	// discard theory questions on user demand
	if ( document.forms["Selector"].lesstheory.checked && Qtype[cc].length == 2 ) Qs --

}	// end of Knit


function Prepare() {

	// reset form, counter variables and arrays
	Qs = -1 ;
	lastnorepeats.length = 0 ;
	counttonorepeats = 0 ;
	numberset = 0 ;
	numberright = 0 ;
	performance = 0 ;

}	// end prepare


function Finalize() {
	// calculates itiot engine parameters based on selected knowledge items

	var areanumber = 0 ;

	// calculate the size of the norepeats array
	norepeats = Math.round( Qs * norepeatfrac ) ;

	for ( i = 0 ; i <= Qs ; i++ ) if ( Knitem[i][3] > areanumber ) areanumber = Knitem[i][3] ;
	for ( i = 0 ; i < Qtype.length ; i++ ) CtrlAdmin[i] = new Array(areanumber+1) ;
	for ( i = 0 ; i < Qtype.length ; i++ ) for ( l = 0 ; l <= areanumber ; l++ ) CtrlAdmin[i][l] = 0 ;

	// count question type numbers in selected subject areas 
	for ( i = 0 ; i <= Qs ; i++ ) {
		m = Knitem[i][2] ;
		l = Math.abs(Knitem[i][3]) ;
		CtrlAdmin[m][l] = CtrlAdmin[m][l] + 1
	}

	// convert to relative frequencies
	for ( i = 0 ; i < Qtype.length ; i++ ) {
		sumofQs = 0 ;
		for ( l = 0 ; l <= areanumber ; l++ ) sumofQs = sumofQs + CtrlAdmin[i][l] ;
		for ( l = 0 ; l <= areanumber ; l++ ) if ( CtrlAdmin[i][l] != 0 ) CtrlAdmin[i][l] = CtrlAdmin[i][l] / sumofQs } ;
		
}	// end of Finalize	


function set_question () {

	function dropIt () { checkagain = false ; i -- }
	
	var checkagain = true ;
	var dropprob = 1 ;
	var respond = true ;

	rightone = -1 ;
	answerplace = 0 ;
	
	// select a right answer
	if ( stepper == 0 ) {

		while ( rightone == -1 ) {

			rightone = Math.round( Math.random() * Qs ) ;
			areacode = Knitem[rightone][3] ;

			// determine if negpos question type
			if ( Knitem[rightone][2] == 0 ) negpos = true
			else negpos = false ;
			
			// drop the item according to set probability
			if ( Math.random() > Knitem[rightone][4] ) rightone = -1

			// check if the new right answer is an element of the lastnorepeats array 
			else
				for ( i = 0; i < lastnorepeats.length; i++ ) if ( rightone != -1 ) if ( Knitem[rightone][0] == lastnorepeats[i] ) rightone = -1 ;

		}

		// update lastnorepeats array
		if ( norepeats > 0 ) lastnorepeats[counttonorepeats] = Knitem[rightone][0] ;
		counttonorepeats++ ;
		if ( counttonorepeats >= norepeats ) counttonorepeats = 0

	} // end select a right answer
   
	// increment the number of questions set
	numberset++ ;

	// allow stepping through items for debugging and reviewing
	if ( stepper > 0 && numberset <= Qs + 1 ) {
		rightone = numberset - 1 ;
	  areacode = Knitem[rightone][3] ;

	  // check areacodes for negative-positive type questions (see also above)
		if ( Knitem[rightone][2] == 0 ) negpos = true
		else negpos = false ;
	}
		
	// alert if all questions have been stepped through
	if ( stepper > 0 && numberset > Qs + 1 ) {
		alert ('You have reviewed all questions.') ;
		rightone = 0 ;
		respond = false
	}

	// place the right answer
	answerplace = Math.round( Math.random() * 3.48 ) ;

	i = 0 ;
	l = 0 ;
	m = 0 ;

	// select the distractors
	while (i < stemsize && respond) {
		nextone = true ;
	
		// insert the correct choice into the array of distractors
		if ( i == answerplace ) {
			wrong[i] = rightone ;
			i++
		}
	
		if ( i < stemsize ) {

			wrong[i] = Math.round( Math.random()* Qs ) ;
			checkagain = true ;
			checknew = wrong[i] ;

			// check the sign fit of areacodes for negative-positive type questions
			if ( negpos && Knitem[checknew][3] == areacode ) dropIt() ;

			// check if the wrong answer fits the questiontype of the correct answer
			if ( checkagain && Knitem[checknew][2] != Knitem[rightone][2] ) dropIt() ;

			// check if the wrong answer is the identical to the right answer or a possible right answer
			if ( checkagain )
				for ( l = 0; l < Knitem[rightone][1].length && checkagain ; l++ )
					if ( Knitem[checknew][1][0] == Knitem[rightone][1][l]) dropIt() ;

			// check for duplicate wrong answers
			if ( checkagain && i != 0 )
				for ( k = 0; k < i; k++ )
					if ( Knitem[wrong[i]][1][0] == Knitem[wrong[k]][1][0]) dropIt() ;

			// check for similarity, i.e. identical areacode, of right and wrong answers
			if ( checkagain && Math.abs(Knitem[checknew][3]) != Math.abs(areacode) ) {
				m = Knitem[rightone][2] ;
				l = Math.abs(areacode) ;
				// drop the wrong answer with the probability specified in the Knitem array
				if ( Knitem[rightone][5] != 1 ) dropprob = Knitem[rightone][5] * CtrlAdmin[m][l] / (1 - CtrlAdmin[m][l]) ;
				if ( Math.random() >= dropprob ) dropIt()
			}
					
			// check for the absolute drop value specified in the Knitem array
			if ( checkagain && Math.random() > Knitem[checknew][4]) i-- ;

			//increment the number of items found
			i++

		}		// end of if i < stemsize
	}			// end of while "select the distractors"

	// write the question to the screen
	if ( respond ) {
		tape = '' ;
		tape += '<br><table><tr><td style="vertical-align: top"><table><tr>' ;
		tape += '<td class="tdbluelight">' ;
		if ( allowNotes ) tape += '<a href="javascript:smart_ass();"><img src="../Images/note.gif" border="0" align="right"></a>' ;
		tape += '</td><td class="tdbluelight" width="400px">' ;

		// construct the question
		if ( !negpos ) {
			theQuestion = Qtype[ Knitem[rightone][2] ] ;
			if ( Knitem[rightone][0].search('append') == 0 ) 	theQuestion += Knitem[rightone][0].replace('append ',' ') ;
			if ( Knitem[rightone][0].search('replace') == 0 ) theQuestion = Knitem[rightone][0].replace('replace ','')
		}
		else {
			if ( Knitem[rightone][3] > 0 ) theQuestion = Qtype[ Knitem[rightone][2] ][0]
			else theQuestion = Qtype[ Knitem[rightone][2] ][1]
		}
		if ( Knitem[rightone][0].search("htm") == -1 || Knitem[rightone][0].search("img") != -1 ) tape += '<p>' + theQuestion + '</p>'
		else tape += '<p>' + '&nbsp;' + '</p>'
				
		tape += '</td><td>&nbsp;</td><td>&nbsp;</td></tr>' ;
		for ( i = 0; i < stemsize; i++ ) {
			tape += '<tr><td class="tdbluelight" align="center"><p class="textbold">' + ( i + 1 ) + '</td>' ;
			tape += '<td class="tdbluelight"><p>' + Knitem[wrong[i]][1][0] + '</p></td>' ;
			tape += '<td><input type="radio" id="ans' + i + '" value="radiobutton" onClick="Checkanswer(' + i + ');"></td>' ;
			tape += '<td><img id="img' + i + '" id="' + i + '" src="../Images/answer.gif"></td></tr>' ;
		}
		tape += '<tr><td>&nbsp;</td>'
		tape += '<td><p class="textsmall"><a href="javascript:set_question();"><img src="../Images/next.gif" border="0" align="right"></a>' ;
		tape += 'questions set: ' + numberset ;
		if ( stepper > 0 ) tape += ' of ' + (Qs+1) ;
		tape += '<br>% correct'
		if (!showRawScore ) tape += ' (above chance)' ;
		tape += ': ' + performance + '</p></td>';
		tape += '<td>&nbsp;</td><td>&nbsp;</td></tr></table></td>' ;
		if ( Knitem[rightone][0].search('none') == -1 && Knitem[rightone][0].search('append') == -1  && Knitem[rightone][0].search('replace') == -1 && respond ) {
			tape += '<td><img src="' + Knitem[rightone][0] + '" style="border-width: 1px; border-style: solid; border-color: black"></td>'
		}
		tape += '</tr></table>' ;

		document.getElementById('Qinterface').innerHTML = tape
		
	}

}	// end of set_question


function Checkanswer (answer) {

	if ( nextone )
		if ( answer == answerplace ) {
			eval ('document.getElementById("img' + answerplace + '").src = "../Images/right.gif"' ) ;
			numberright ++
		}
		else {
			eval ('document.getElementById("img' + answer + '").src = "../Images/wrong.gif"' ) ;
			eval ('document.getElementById("img' + answerplace + '").src = "../Images/right.gif"' )
		} 
	else alert ('Please set a new question before answering.') ;

	nextone = false ;
	performance = numberright / numberset *100 ;
	if ( !showRawScore ) performance = ( stemsize * performance - 100 ) / ( stemsize - 1 ) ;
	performance = Math.round(performance) ;
	if ( performance < 0 ) performance = 0
	
} // end of Checkanswer
