#!../../src/xotclsh # $Id: MC.xotcl,v 1.1 2004/05/23 22:50:39 neumann Exp $ # # A simple multiple choice test application # array set opts {-pkgdir .}; array set opts $argv lappend auto_path $opts(-pkgdir) package require XOTcl 1 1; namespace import -force xotcl::* #package require xotcl::package; package verbose 1 package require xotcl::actiweb::htmlPlace package require xotcl::actiweb::pageTemplate HtmlPlace ::receiver -port 8092 -allowExit exit # Define a pool of questions: Question and their alternatives # are defined as classes and all questions are stored in the pool # Class Pool Class Pool::Question -parameter {text {altcounter 1}} Class Pool::Question::Alternative -parameter {text correct} Pool::Question instproc alternatives {pairs} { my instvar altcounter foreach {alt correct} $pairs { incr altcounter [self class]::Alternative [self]::$altcounter \ -text $alt -correct $correct } } # # An Exam has a name and is a selection of questions from a pool. # "requiredCorrect" defines the minimal number of correct answers # to pass the test. Class Exam -parameter {name requiredCorrect pool questions} # # For every candidate we create an individual exam. We scramble # the questions and alternatives and use the studentID as a seed. # Class IndividualExam -superclass Agent -parameter {ID exam} IndividualExam instproc random modulo { ;### random number generator my instvar seed set seed [expr {($seed*12731+34197) % 21473}] return [expr {$seed % $modulo}] } IndividualExam instproc permute {list} { ;### permute random permutation set permuted {} for {set nr [llength $list]} {$nr>0} {incr nr -1} { set select [my random $nr] lappend permuted [lindex $list $select] set list [lreplace $list $select $select] } return $permuted } IndividualExam instproc init args { my instvar seed ID exam individualTest alternatives set questions [$exam set questions] set seed $ID ### compute order of individual tests and alternatives foreach index [my permute [$exam set questions]] { set questionObj [$exam set pool]::$index lappend individualTest $index set alts [my permute [lsort [$questionObj info children]]] lappend alternatives $alts } #puts stderr "Individual test [self] has $individualTest" } # # Define a web facade using a page template # "testObject" is the individual test that is shielded by the web facade # Class WebExam -superclass WebObject \ -instmixin PageTemplateHtml -parameter {testObject} WebExam instproc default {} { ;### This method creates the HTML Test my instvar testObject ;### import var that stores shielded test object ### import vars from the test $testObject instvar individualTest alternatives exam set action [my selfAction result] ### create Test page set htmlText "
\n" ### create simple HTML Page my simplePage [$exam name] \ "Exam [$exam name] for [string trimleft $testObject :] \ (Exam: $exam)" $htmlText } WebExam instproc result {} { ;# This method analyses the results of the test my instvar testObject ;### import var that stores shielded test set exam [$testObject exam] $testObject instvar individualTest alternatives foreach question $individualTest alts $alternatives { foreach a $alts {set ca($a) 0} } foreach a [my getFormData] {set ca([$a set content]) 1} set htmlText "You have answered: