########################################################### # scorer.output.num file looks like this # classname setNum numQuest flags questiondescriptor # flags come in the order of CheckPIN, AnonMode, (CheckSpaces, Gone) # (SurveyMode, Gone) (SurveyHeader, Gone) (IdFormat, Gone) # (CheckMultipleMarks, Gone) QueryAboutPID, (log gone) ########################################################### ########################################################### # scorerMessage ########################################################### ########################################################### ########################################################### proc scorerMessage { num mesg {tag normal} } { global gScorer $gScorer(status.$num) insert end "$mesg\n" $tag $gScorer(status.$num) see end # update } ########################################################### # scorerError ########################################################### ########################################################### ########################################################### proc scorerError { num errorCode args } { global gScorer switch $errorCode { LOTS_OF_ANON_MODE_MATCHES { lappend gScorer(errortype.$num) $errorCode lappend gScorer(errors.$num) [lindex $args 0] scorerMessage $num "More than 6 Student IDs generate the closest match to the capaID specified on [lindex $args 1]'s paper" error } NO_CODE_IN_ANON_MODE { lappend gScorer(errortype.$num) $errorCode lappend gScorer(errors.$num) [lindex $args 0] scorerMessage $num "There was no CapaID/CODE on [lindex $args 1]'s paper" error } NO_SUCH_STUDENT { lappend gScorer(errortype.$num) $errorCode lappend gScorer(errors.$num) [lindex $args 0] scorerMessage $num "Unable to find [lindex $args 1] in classl" error } UNABLE_TO_PARSE { lappend gScorer(errortype.$num) $errorCode lappend gScorer(errors.$num) [lindex $args 0] scorerMessage $num "An error occured while trying to parse the set for [lindex $args 1]'s paper" error } PINWRONG - UNKNOWN_GRADING_METHOD - CANT_OPEN_SB - CANT_UPDATE_SB - default { displayError "$errorCode $args" } } incr gScorer(numerrors.$num) update } ########################################################### # runScorer ########################################################### ########################################################### ########################################################### proc runScorer { setFile } { global gUniqueNumber gWindowMenu gFile gScorer set num [incr gUniqueNumber] set classDir [file dirname $setFile] set gFile($num) $classDir # puts "set gFile($num) to $gFile($num)" set scorerWin [toplevel .beginScorer$num] $gWindowMenu add command -label "ScorerConfig $classDir" \ -command "capaRaise \"$scorerWin\"" wm title $scorerWin $classDir set infoFrame [frame $scorerWin.infoFrame ] set buttonFrame [frame $scorerWin.buttonFrame ] set configFrame [frame $scorerWin.configFrame ] pack $infoFrame $buttonFrame $configFrame -side top set classNameFrame [frame $infoFrame.classNameFrame] set setNumFrame [frame $infoFrame.setNumFrame] set scoreFileFrame [frame $infoFrame.scoreFileFrame] pack $classNameFrame $setNumFrame $scoreFileFrame -side top -anchor w #classname label $classNameFrame.label -text "Class Name:" entry $classNameFrame.entry -textvariable gScorer(class.$num)\ -width 8 # button $classNameFrame.button -text "What Goes Here" \ -command "helpScorer className" pack $classNameFrame.label $classNameFrame.entry -side left set gScorer(class.$num) [file tail $classDir] #set number set gScorer(set.$num) [string range [file rootname [file tail $setFile]] 3 end] label $setNumFrame.label -text "Set Number:" entry $setNumFrame.set -width 2 -textvariable gScorer(set.$num) pack $setNumFrame.label $setNumFrame.set -side left #scoring file label $scoreFileFrame.label -text "Scoring Office File:" set entryFrame [frame $scoreFileFrame.entryFrame] button $scoreFileFrame.select -text "Select File" \ -command "selectScoringFile $num" pack $scoreFileFrame.label $entryFrame $scoreFileFrame.select -side left entry $entryFrame.entry -textvariable gScorer(scoreFile.$num) \ -xscrollcommand "$entryFrame.scroll set" scrollbar $entryFrame.scroll -orient h -command \ "$entryFrame.entry xview" pack $entryFrame.entry $entryFrame.scroll pack configure $entryFrame.scroll -fill x #buttons button $buttonFrame.cancel -text Cancel -command "destroy $scorerWin\ removeWindowEntry \"ScorerConfig $classDir\"" button $buttonFrame.continue -text "Continue" \ -command "getScorerQuest $num" button $buttonFrame.load -text "Load Previous Settings" \ -command "loadScorerConfig $num" pack $buttonFrame.cancel $buttonFrame.continue $buttonFrame.load \ -side left #config options #flag list is from scorer.h foreach flaglist $gScorer(flags) { set flag [lindex $flaglist 0] set question [lindex $flaglist 1] set oneVal [lindex $flaglist 2] set zeroVal [lindex $flaglist 3] set defaultVal [lindex $flaglist 4] set frame($flag) [frame $configFrame.[string tolower $flag] \ -relief groove -borderwidth 2] set gScorer($flag.frame.$num) $frame($flag) pack $frame($flag) -side top -anchor w set frame($flag.top) [frame $frame($flag).top] set frame($flag.bot) [frame $frame($flag).bot] pack $frame($flag.top) $frame($flag.bot) -side top -anchor w label $frame($flag.top).label -text "$question" -anchor w -width 70 # button $frame($flag.top).help -text "Huh?" -command "helpScorerFlags $flag" pack $frame($flag.top).label -side left radiobutton $frame($flag.bot).one -variable gScorer($flag.$num) \ -value 1 -text $oneVal -command "configureOptions $num" radiobutton $frame($flag.bot).zero -variable gScorer($flag.$num) \ -value 0 -text $zeroVal -command "configureOptions $num" set gScorer($flag.$num) $defaultVal pack $frame($flag.bot).one $frame($flag.bot).zero -side left } parseCapaConfig $num $gFile($num) configureOptions $num loadScorerConfig $num Centre_Dialog $scorerWin default # trace variable gScorer(quit.$num) w "scorerClose $num 0" } ########################################################### # loadScorerConfig ########################################################### ########################################################### ########################################################### proc loadScorerConfig { num } { global gScorer gFile set filename [file join $gFile($num) records scorer.output.$gScorer(set.$num)] if { [ catch { set fileId [ open $filename "r" ] } ] } { displayMessage "Creating a new scorer.output file for set $gScorer(set.$num)." return } set line [gets $fileId ] close $fileId set flags [lindex $line 3] #When uncommenting or commenting the following lines make sure to update the actual #index values set gScorer(CheckPIN.$num) [string index $flags 0] set gScorer(AnonMode.$num) [string index $flags 1] # set gScorer(CheckSpaces.$num) [string index $flags 2] # set gScorer(SurveyMode.$num) [string index $flags 3] # set gScorer(SurveyHeader.$num) [string index $flags 4] # set gScorer(IdFormat.$num) [string index $flags 5] # set gScorer(CheckMultipleMarks.$num) [string index $flags 6] set gScorer(QueryAboutPID.$num) [string index $flags 2] # set gScorer(Form.$num) [string index $flags 8] # set gScorer(log.$num) [string index $flags 9] configureOptions $num } ########################################################### ########################################################### ########################################################### ########################################################### proc configureOptions { num } { global gScorer foreach frame [array names gScorer "*.frame.$num"] { pack forget $gScorer($frame) } # pack $gScorer(SurveyMode.frame.$num) -side top # if { $gScorer(SurveyMode.$num) } {} # pack $gScorer(SurveyHeader.frame.$num) # {} pack $gScorer(CheckPIN.frame.$num) if { $gScorer(CheckPIN.$num) } { pack $gScorer(AnonMode.frame.$num) if { $gScorer(AnonMode.$num) } { pack $gScorer(QueryAboutPID.frame.$num) } else { set gScorer(QueryAboutPID.$num) 0 } } else { set gScorer(AnonMode.$num) 0 } # pack $gScorer(CheckSpaces.frame.$num) # pack $gScorer(CheckMultipleMarks.frame.$num) # pack $gScorer(IdFormat.frame.$num) # {} # pack $gScorer(Form.frame.$num) # pack $gScorer(log.frame.$num) } ########################################################### # selectScoringFile ########################################################### ########################################################### ########################################################### proc selectScoringFile { num } { global gScorer if { "" != [ set temp [tk_getOpenFile] ] } {set gScorer(scoreFile.$num) $temp} } ########################################################### ########################################################### ########################################################### ########################################################### proc helpScorerFlags { flag } { global gUniqueNumber gWindowMenu set num [incr gUniqueNumber] set helpWin [toplevel .beginScorer$num] $gWindowMenu add command -label "HelpFlag $flag" \ -command "capaRaise \" $helpWin\"" wm title $helpWin $flag button $helpWin.dismiss -text Dismiss -command "destroy $helpWin" message $helpWin.help -aspect 2000 set help "" switch $flag { # SurveyMode { set help "An examination will include the student number on the answer sheet of the student who answered the questions, whereas a survey will have no student number at all." } # SurveyHeader { set help "If the Survey given include a header portion this will let ."} CheckPIN { set help "bluh" } AnonMode { set help "bluh" } QueryAboutPID { set help "bluh" } # CheckSpaces { set help "bluh" } # CheckMultipleMarks { set help "bluh" } # IdFormat { set help "bluh" } # Form { set help "bluh" } # log { set help "bluh" } } $helpWin.help configure -text "$help" pack $helpWin.dismiss $helpWin.help Centre_Dialog $helpWin default } ########################################################### # getScorerQuest ########################################################### ########################################################### ########################################################### proc getScorerQuest { num } { global gUniqueNumber gWindowMenu gFile gScorer if { ![file readable $gScorer(scoreFile.$num)] } { displayMessage "Please Select a readable scoring office report file before continuing." return } set classDir $gFile($num) set scorerWin ".beginScorer$num" set infoFrame $scorerWin.infoFrame set buttonFrame $scorerWin.buttonFrame set configFrame $scorerWin.configFrame set classNameFrame $infoFrame.classNameFrame set setNumFrame $infoFrame.setNumFrame set scoreFileFrame $infoFrame.scoreFileFrame set entryFrame $scoreFileFrame.entryFrame destroy $configFrame pack [frame $configFrame] destroy $scoreFileFrame.select $entryFrame.entry configure -state disabled $classNameFrame.entry configure -state disabled $setNumFrame.set configure -state disabled #disabeling the config options set classNameFrame $infoFrame.classNameFrame set setNumFrame $infoFrame.setNumFrame $classNameFrame.entry configure -state disabled $setNumFrame.set configure -state disabled $buttonFrame.continue configure -command "startScorer $num" $buttonFrame.load configure -command "loadScorerQuest $num" #question set questButFrame [ frame $configFrame.butFrame ] set questLabelFrame [frame $configFrame.label ] set questListFrame [ frame $configFrame.listFrame ] pack $questButFrame $questLabelFrame $questListFrame pack configure $questLabelFrame -anchor w button $questButFrame.add -text "Add" -command "addScorerQuest $num" button $questButFrame.clone -text "Clone" -command "cloneScorerQuest $num" button $questButFrame.rm -text "Remove" -command "rmScorerQuest $num" button $questButFrame.change -text "Change" -command "changeScorerQuest $num" pack $questButFrame.add $questButFrame.clone $questButFrame.rm \ $questButFrame.change -side left label $questLabelFrame.label -text "Num Type Points Leafs" pack $questLabelFrame.label #listbox set gScorer(questNum.$num) [ listbox $questListFrame.questNum \ -width 3 -height 20 \ -yscrollcommand "$questListFrame.scroll set" ] set gScorer(quest.$num) [ listbox $questListFrame.quest -width 50 -height 20 \ -yscrollcommand "$questListFrame.scroll set"] scrollbar $questListFrame.scroll -orient v -command \ "scrolltwo \"$questListFrame.quest yview\" \"$questListFrame.questNum yview\"" pack $questListFrame.scroll $questListFrame.quest \ $questListFrame.questNum -side right pack configure $questListFrame.scroll -fill y loadScorerQuest $num update idletasks Centre_Dialog $scorerWin default } ########################################################### # configQuestWin ########################################################### ########################################################### ########################################################### proc configQuestWin { num action {message ""} {max 1} } { global gScorer if { ![winfo exists .scorerQuestWin$num] } { return } set frame .scorerQuestWin$num.add.leaf switch $action { hide { pack forget $frame } show { pack $frame $frame.leafs configure -label $message $frame.leafs configure -to $max } } } ########################################################### # renumberScorerQuest ########################################################### ########################################################### ########################################################### proc renumberScorerQuest { num } { global gScorer $gScorer(questNum.$num) delete 0 end set max [$gScorer(quest.$num) index end ] for { set i 1 } { $i <= $max } { incr i } { lappend numList $i } eval "$gScorer(questNum.$num) insert 0 $numList" $gScorer(questNum.$num) yview [ $gScorer(quest.$num) nearest 5 ] } ########################################################### # insertQuest ########################################################### ########################################################### ########################################################### proc insertQuest { num where } { global gScorer if { $where != "end" } { $gScorer(quest.$num) delete $where } switch $gScorer(questType.$num) { ONE_OUT_OF_10 - ASSIGNED - SINGLE_DIGIT - STRING_MATCH { $gScorer(quest.$num) insert $where [format "%-13s %7s" \ $gScorer(questType.$num) $gScorer(questPoint.$num)] } GLE - TF - N_OUT_OF_M { $gScorer(quest.$num) insert $where [format "%-13s %7s %6s" \ $gScorer(questType.$num) $gScorer(questPoint.$num) \ $gScorer(questLeaf.$num)] } } renumberScorerQuest $num update $gScorer(quest.$num) see $where } ########################################################### # addScorerQuest ########################################################### ########################################################### ########################################################### proc addScorerQuest { num {position end} } { global gUniqueNumber gWindowMenu gFile gScorer if { [winfo exists .scorerQuestWin$num] } { return } set questWin [ toplevel .scorerQuestWin$num ] if { ! [ info exists gScorer(questType.$num) ] } { set gScorer(questType.$num) ONE_OUT_OF_10 } set buttonFrame [ frame $questWin.button ] set optionFrame [ frame $questWin.add ] pack $buttonFrame $optionFrame -side top set text Change if { $position == "end" } { set text Add } button $buttonFrame.done -text $text -command "insertQuest $num $position destroy $questWin" button $buttonFrame.cancel -text "Cancel" -command "destroy $questWin" pack $buttonFrame.done $buttonFrame.cancel -side left set typeFrame [ frame $optionFrame.type ] set pointFrame [ frame $optionFrame.point ] set leafFrame [ frame $optionFrame.leaf ] pack $typeFrame $pointFrame $leafFrame -side top radiobutton $typeFrame.oneoutof8 -text "One out of no more than 10" -value "ONE_OUT_OF_10" \ -variable gScorer(questType.$num) -command "configQuestWin $num hide" radiobutton $typeFrame.gletype -text "GLE type" -value "GLE" \ -variable gScorer(questType.$num) \ -command "configQuestWin $num show \"Number of Leafs\" 3 " radiobutton $typeFrame.tftype -text "TF type" -value "TF" \ -variable gScorer(questType.$num) \ -command "configQuestWin $num show \"Number of Leafs\" 5 " radiobutton $typeFrame.assigned -text "Assigned score" -value "ASSIGNED" \ -variable gScorer(questType.$num) -command "configQuestWin $num hide " radiobutton $typeFrame.noutofm -text "N out of M" -value "N_OUT_OF_M" \ -variable gScorer(questType.$num) \ -command "configQuestWin $num show \"What is the value of M\" 10 " radiobutton $typeFrame.singledigit -text "Single digit" -value "SINGLE_DIGIT" \ -variable gScorer(questType.$num) -command "configQuestWin $num hide" radiobutton $typeFrame.exactstring -text "Exact string matching" \ -value "STRING_MATCH" -variable gScorer(questType.$num) \ -command "configQuestWin $num hide" pack $typeFrame.oneoutof8 $typeFrame.gletype $typeFrame.tftype \ $typeFrame.assigned $typeFrame.noutofm $typeFrame.singledigit \ $typeFrame.exactstring -side top -anchor w scale $pointFrame.points -from 0 -to 9 -variable gScorer(questPoint.$num) \ -label "Point Value" -orient h -length 300 pack $pointFrame.points scale $leafFrame.leafs -from 1 -to 10 -variable gScorer(questLeaf.$num) \ -label "Number of Leafs" -orient h -length 300 pack $leafFrame.leafs switch $gScorer(questType.$num) { ONE_OUT_OF_10 - ASSIGNED - SINGLE_DIGIT - STRING_MATCH { configQuestWin $num hide } GLE { configQuestWin $num show "Number of Leafs" 3 } TF { configQuestWin $num show "Number of Leafs" 5 } N_OUT_OF_M { configQuestWin $num show "What is the value of M" 10 } } Centre_Dialog $questWin default } ########################################################### # cloneScorerQuest ########################################################### ########################################################### ########################################################### proc cloneScorerQuest { num } { global gUniqueNumber gWindowMenu gFile gScorer if { [ $gScorer(quest.$num) curselection ] == "" } { displayError "Please select an exisiting question to clone." return } set temp [ $gScorer(quest.$num) get [ $gScorer(quest.$num) curselection ] ] $gScorer(quest.$num) insert end $temp $gScorer(quest.$num) see end renumberScorerQuest $num } ########################################################### # rmScorerQuest ########################################################### ########################################################### ########################################################### proc rmScorerQuest { num } { global gUniqueNumber gWindowMenu gFile gScorer if { [winfo exists .scorerQuestWin$num] } { return } if { [ $gScorer(quest.$num) curselection ] == "" } { displayError "Please select an exisiting question to delete." return } $gScorer(quest.$num) delete [$gScorer(quest.$num) curselection] renumberScorerQuest $num } ########################################################### # changeScorerQuest ########################################################### ########################################################### ########################################################### proc changeScorerQuest { num } { global gUniqueNumber gWindowMenu gFile gScorer if { [winfo exists .scorerQuestWin$num] } { return } if { [ $gScorer(quest.$num) curselection ] == "" } { displayError "Please select an exisiting question to change." return } set position [ $gScorer(quest.$num) curselection ] set gScorer(questType.$num) [lindex [$gScorer(quest.$num) get $position ] 0 ] set gScorer(questPoint.$num) [lindex [$gScorer(quest.$num) get $position ] 1 ] set gScorer(questLeaf.$num) [lindex [$gScorer(quest.$num) get $position ] 2 ] addScorerQuest $num $position } ########################################################### # startScorer ########################################################### ########################################################### ########################################################### proc startScorer { num } { global gScorer gFile set scorerWin .beginScorer$num set filename [file join $gFile($num) records scorer.output.$gScorer(set.$num)] if { [ catch { set fileId [ open $filename "w+" ] } ] } { displayError "Unable to write to the scorer.output file. " return } #When deleting or adding anything to the flags var make sure to update loadScorerConfig # set flags $gScorer(CheckPIN.$num)$gScorer(AnonMode.$num)$gScorer(CheckSpaces.$num)$gScorer(SurveyMode.$num)$gScorer(SurveyHeader.$num)$gScorer(IdFormat.$num)$gScorer(CheckMultipleMarks.$num)$gScorer(QueryAboutPID.$num)$gScorer(Form.$num)$gScorer(log.$num) set flags $gScorer(CheckPIN.$num)$gScorer(AnonMode.$num)$gScorer(QueryAboutPID.$num) set numQuestion [ $gScorer(quest.$num) index end ] set questString "" for { set i 0 } { $i < $numQuestion } { incr i } { set line [ $gScorer(quest.$num) get $i ] set gScorer(quest.$i.type.$num) [lindex $line 0] switch [lindex $line 0 ] { ONE_OUT_OF_10 { append questString a } GLE { append questString b } TF { append questString c } ASSIGNED { append questString d } N_OUT_OF_M { append questString e } SINGLE_DIGIT { append questString f } STRING_MATCH { append questString g } } append questString [lindex $line 1] set gScorer(quest.$i.points.$num) [lindex $line 1] if { [ lindex $line 2 ] == "" } { set gScorer(quest.$i.leafs.$num) 1 append questString 1 } else { set gScorer(quest.$i.leafs.$num) [lindex $line 2] append questString [lindex $line 2] } } set outputLine "$gScorer(class.$num) $gScorer(set.$num) $numQuestion $flags $questString" puts $fileId [format "%-500s" $outputLine] close $fileId destroy $scorerWin.buttonFrame destroy $scorerWin.configFrame set gScorer(student.$num) 0 set gScorer(numerrors.$num) 0 set buttonFrame [frame $scorerWin.buttonFrame] set statusFrame [frame $scorerWin.statusFrame] pack $buttonFrame $statusFrame button $buttonFrame.pause -text Pause -command "pauseScorer $num" button $buttonFrame.cont -text Continue -command "unpauseScorer $num" button $buttonFrame.restart -text Restart -command "restartScorer $num" button $buttonFrame.final -text "Update .sb" -command "scorerToSet $num" button $buttonFrame.exit -text "Quit" -command "scorerQuit $num" pack $buttonFrame.pause $buttonFrame.cont $buttonFrame.restart \ $buttonFrame.final $buttonFrame.exit -side left message $statusFrame.mesg -text "Messages:" -aspect 2000 set statusText [frame $statusFrame.statusText] set student [frame $statusFrame.student] set errors [frame $statusFrame.errors] set statusButtons [frame $statusFrame.button] pack $statusFrame.mesg $statusFrame.statusText $statusFrame.student \ $statusFrame.errors $statusFrame.button pack configure $statusFrame.mesg $statusFrame.student $statusFrame.errors \ -anchor w pack configure $statusText -expand 1 -fill both set gScorer(status.$num) [text $statusText.text -wrap char \ -yscrollcommand "$statusText.scroll set"] $gScorer(status.$num) tag configure error -foreground red $gScorer(status.$num) tag configure info -foreground #006c00 scrollbar $statusText.scroll -orient v -command "$statusText.text yview" pack $statusText.text $statusText.scroll -side left pack configure $statusText.scroll -fill y pack configure $gScorer(status.$num) -expand 1 -fill both label $student.mesg -text "Students completed:" label $student.num -textvariable gScorer(student.$num) pack $student.mesg $student.num -side left label $errors.mesg -text "Errors To Be Handled:" label $errors.num -textvariable gScorer(numerrors.$num) pack $errors.mesg $errors.num -side left button $statusButtons.handleErrors -text "Save Errors" \ -command "handleErrorsScorer $num" button $statusButtons.printMsg -text "Print Messages" \ -command "printScorerMsg $num" button $statusButtons.saveMsg -text "Save Messages" \ -command "saveScorerMsg $num" button $statusButtons.clearMsg -text "Clear Messages" \ -command "clearScorerMsg $num" pack $statusButtons.handleErrors $statusButtons.printMsg \ $statusButtons.saveMsg -side left wm protocol $scorerWin WM_DELETE_WINDOW "usequit $num" update idletasks Centre_Dialog $scorerWin default # set gScorer(quit.$num) 0 restartScorer $num } ########################################################### # usequit ########################################################### ########################################################### ########################################################### proc usequit { num } { scorerMessage $num "Please use the Quit Button." info } ########################################################### # saveScorerMsg ########################################################### ########################################################### ########################################################### proc saveScorerMsg { num } { global gScorer set file [tk_getSaveFile -title "Enter the name to save messages to."] if { $file == "" } { return } if { [catch {set fileId [open $file "w"] } ] } { displayError "Unable to open $file" return } set tag [getWhichTags "All {Errors Only} {NonErrors Only}" "{} error normal" "saved"] puts -nonewline $fileId [getTextTagged $gScorer(status.$num) $tag ] close $fileId } ########################################################### # printScorerMsg ########################################################### ########################################################### ########################################################### proc printScorerMsg { num } { global gScorer gFile set file [file join $gFile($num) managertemp.txt] set lprCommand [getLprCommand $file $num] if { $lprCommand == "Cancel" } { return } if { [catch {set fileId [open $file "w"] } ] } { displayError "Unable to open $file" return } set tag [getWhichTags "All {Errors Only} {NonErrors Only}" "{} error normal" printed] puts -nonewline $fileId [getTextTagged $gScorer(status.$num) $tag ] close $fileId set errorMsg "" set error [catch {set output [ eval "exec $lprCommand" ] } errorMsg ] exec rm -f $file if { $error == 1 } { displayError "An error occurred while printing: $errorMsg" } else { displayMessage "Print job sent to the printer.\n $output" } } ########################################################### # initScorer ########################################################### ########################################################### ########################################################### proc initScorer { num } { global gScorer gFile scorerMessage $num "Initializing. . ." if { ![info exists gScorer(in.$num)] || ( $gScorer(in.$num) == "" ) } { if { [catch {set gScorer(in.$num) \ [ open $gScorer(scoreFile.$num) "r" ] } ] } { displayError "Unable to open input file $gScorer(scoreFile.$num)" exit } } set filename [file join $gFile($num) records scorer.output.$gScorer(set.$num)] if { ![info exists gScorer(out.$num)] || ( $gScorer(out.$num) == "" ) } { if { [catch {set gScorer(out.$num) [ open $filename "a+" ] } ] } { displayError "Unable to open input file $filename" exit } } scorerMessage $num "Building List of Students. . ." update set oldDir [pwd] cd $gFile($num) #4 is the length of the CapaID set a $gScorer(HalfSheet.CapaID) set capaidplus [expr {[lindex $a 1] - [lindex $a 0] - 3}] # puts "$capaidplus, $a" set gScorer(studentList.$num) [buildStudentList $num $gScorer(class.$num) \ $gScorer(set.$num) $capaidplus] cd $oldDir } ########################################################### # getLine ########################################################### ########################################################### ########################################################### proc getLine { num } { global gScorer scorerMessage $num "\nGetting Responses" set done 0 while { ! $done } { gets $gScorer(in.$num) aline if { [eof $gScorer(in.$num) ] } { error EOF } if { ![string match "#*" $aline] } { set done 1 } } return $aline } ########################################################### # oneResponse ########################################################### ########################################################### ########################################################### proc oneResponse { response max which } { upvar $which whichVar set whichVar "" set howmany 0 for { set i 0 } { $i < $max } { incr i } { if { [string index "$response" $i] == "1" } { lappend whichVar $i incr howmany } } return $howmany } ########################################################### # parseLine ########################################################### ########################################################### ########################################################### proc parseLine { num answerLine answerStruct } { global gScorer upvar $answerStruct parsedIn set result "" scorerMessage $num "Understanding Responses" # Only support HalfSheets # if { $gScorer(Form.$num) } { # set sheet FullSheet # } else { # set sheet HalfSheet # } set sheet HalfSheet set parsedIn(orignalLine) "$answerLine" foreach type { SerialNumber LastName FirstName MiddleInitial StudentNumber Section CapaID } { if { [ catch {set parsedIn($type) [string range "$answerLine" \ [lindex $gScorer($sheet.$type) 0] \ [lindex $gScorer($sheet.$type) 1] ] } ] } { set parsedIn($type) "" } } set letter "ABCDEFGHIJ" set number "1234567890" set offset [lindex $gScorer($sheet.Question) 0] set maxQuest [lindex $gScorer($sheet.Question) 1] set perQuest [lindex $gScorer($sheet.Question) 2] set parsedIn(multiplemarks) 0 set parsedIn(spaces) 0 set parsedIn(maxQuest) $maxQuest for { set i 0 } { $i < $maxQuest } { incr i } { if { [ catch { set gScorer(quest.$i.type.$num) } ] } { set parsedIn(maxQuest) $i set gScorer(numQuest.$num) $i break } set array $letter set start [expr $i * $perQuest + $offset ] set stop [expr $start + $perQuest - 1 ] set response [string range "$answerLine" $start $stop] switch $gScorer(quest.$i.type.$num) { ASSIGNED - SINGLE_DIGIT - ONE_OUT_OF_10 { if { $gScorer(quest.$i.type.$num) != "ONE_OUT_OF_10" } { set array $number } set howmany [oneResponse "$response" $perQuest which] if { $howmany == 1 } { set parsedIn(answer.$i) [string index $array $which] } else { if { $howmany > 1 } { set parsedIn(answer.$i) " " incr parsedIn(multiplemarks) } else { if { $howmany < 1 } { set parsedIn(answer.$i) " " incr parsedIn(spaces) } } } } GLE - TF { if { $gScorer(quest.$i.type.$num) != "GLE" } { set stepsize 2 } else { set stepsize 3 } set leafs $gScorer(quest.$i.leafs.$num) for { set j 0 } { $j < $leafs } { incr j } { set start [expr $j*$stepsize] set stop [expr $start + $stepsize - 1] set howmany [oneResponse [string range \ $response $start $stop] $perQuest which] if { $howmany == 1 } { append parsedIn(answer.$i) [string index $array \ [expr {$start + $which}]] } else { if { $howmany > 1 } { append parsedIn(answer.$i) " " incr parsedIn(multiplemarks) } else { if { $howmany < 1 } { append parsedIn(answer.$i) " " incr parsedIn(spaces) } } } } } N_OUT_OF_M - STRING_MATCH { set found 0 for { set j 0 } { $j < $perQuest } { incr j } { set char [string index "$response" $j] if { "$char" == 1 } { append parsedIn(answer.$i) [string index $array $j] incr found } } if { ! $found } { incr parsedIn(spaces) set parsedIn(answer.$i) "" } } } } #if there isn't a capaId already, treat the first four questions as # capaID # if { $parsedIn(CapaID) == "" && $gScorer(CheckPIN.$num) } { # set pinWrong 0 # for {set j 0} {$j < 4} {incr j} { # switch -regexp "$parsedIn(answer.$j)" { # ^[A-J]$ { # append parsedIn(CapaID) \ [string first $parsedIn(answer.$j) "ABCDEFGHIJ" ] # } # default { # set pinWrong 1 # } # } # } # if { $pinWrong } { # scorerError $num PINWRONG parsedIn # lappend result PINWRONG # } # } # parray parsedIn if { $result != "" } { error "$result" } } proc getAnswers2 { PID set maxQuest num } { global gFile set pwd [pwd] cd $gFile($num) set result [getAnswersFromSet $PID $set $maxQuest] cd $pwd return $result } proc getAnswers { PID set maxQuest num } { global gFile gCapaConfig set pwd [pwd] cd $gFile($num) set temp [exec $gCapaConfig($num.answers_command) $PID {} 0 $set] cd $pwd set result "" foreach line [split $temp "\n"] { switch [lindex [split $line :] 0] { ANS { lappend result [string range $line 4 end] } } } return $result } ########################################################### # checkStudentNumber ########################################################### ########################################################### ########################################################### proc checkStudentNumber { num answerStructVar } { global gScorer gFile upvar $answerStructVar answerStruct # puts "Stunum1:$answerStruct(StudentNumber):" if { ![inClasslist $num $answerStruct(StudentNumber)] } { # puts "Stunum2:$answerStruct(StudentNumber):" set matched [findByStudentName [string trim $answerStruct(LastName)] $gFile($num)] if { [llength $matched] != 1 } { getOneStudent "" $gFile($num) id name "Unable to find student id: $answerStruct(StudentNumber), entered name is $answerStruct(LastName), $answerStruct(FirstName)." "Name on paper:$answerStruct(LastName), $answerStruct(FirstName), Number on Paper: $answerStruct(StudentNumber)" } else { set id [lindex [lindex $matched 0] 0] if { [makeSure "Unable to find bubbled id: $answerStruct(StudentNumber), name: $answerStruct(LastName) in classl, however I did find $matched. Use this one?"] != "Yes" } { getOneStudent "" $gFile($num) id name "Unable to find student id: $answerStruct(StudentNumber), entered name is $answerStruct(LastName), $answerStruct(FirstName)." "Name on paper:$answerStruct(LastName), $answerStruct(FirstName), Number on Paper: $answerStruct(StudentNumber)" } else { } } if { $id == "" } { scorerError $num NO_SUCH_STUDENT "$answerStruct(orignalLine)" \ $answerStruct(StudentNumber) return 0 } else { scorerMessage $num "Student Number $answerStruct(StudentNumber) not found in classl using $id instead." info set answerStruct(StudentNumber) $id } } # puts "Stunum3:$answerStruct(StudentNumber):" return 1 } ########################################################### # handleStudent ########################################################### ########################################################### ########################################################### proc handleStudent { num answerStructVar} { global gScorer gFile upvar $answerStructVar answerStruct if { ![checkStudentNumber $num answerStruct] } { return 0 } scorerMessage $num "Finding Possible Students. . ." if { ! $gScorer(AnonMode.$num) } { set answerStruct(questionPID) $answerStruct(StudentNumber) } else { # puts "$answerStruct(StudentNumber):$answerStruct(CapaID):" if { [string trim $answerStruct(CapaID)] == "" } { scorerError $num NO_CODE_IN_ANON_MODE "$answerStruct(orignalLine)" \ $answerStruct(StudentNumber) return 0 } set answerStruct(questionPID) [getAnonModeID $num answerStruct] if { [llength $answerStruct(questionPID)] > 6 } { scorerError $num LOTS_OF_ANON_MODE_MATCHES "$answerStruct(orignalLine)" \ $answerStruct(StudentNumber) return 0 } } set answerStruct(Name) "$answerStruct(LastName) $answerStruct(FirstName) $answerStruct(MiddleInitial)" scorerMessage $num "Getting Possible Answers for $answerStruct(StudentNumber), paper# $answerStruct(SerialNumber). . ." foreach questionPID $answerStruct(questionPID) { scorerMessage $num "Getting Answers for $questionPID. . ." if { [catch { set answerStruct(correct.$questionPID) \ [getAnswers $questionPID $gScorer(set.$num) \ $answerStruct(maxQuest) $num] } errorMsg ] } { catch {puts $errorMsg} scorerError $num UNABLE_TO_PARSE "$answerStruct(orignalLine)" \ $answerStruct(StudentNumber) error UNABLE_TO_PARSE } # puts "$answerStruct(correct.$questionPID)" } scorerMessage $num "Grading Answers. . ." foreach questionPID $answerStruct(questionPID) { set answerStruct($questionPID.grade) [gradeSet $num answerStruct $questionPID] scorerMessage $num "Correct: $answerStruct($questionPID.correct) #correct: $answerStruct($questionPID.grade) PID: $questionPID" } scorerMessage $num "Given: $answerStruct($questionPID.given)" if { [llength $answerStruct(questionPID)] > 1 } { scorerMessage $num "Selecting Student. . ." if { $gScorer(QueryAboutPID.$num) } { set answerStruct(questionPID) \ [getWhichAnon $num answerStruct $answerStruct(indices)] } else { set answerStruct(questionPID) \ [pickAnonHighest $num answerStruct $answerStruct(indices)] } scorerMessage $num "Student $answerStruct(StudentNumber) selected $answerStruct(questionPID)'s paper." info } return 1 } ########################################################### # gradeQuestion ########################################################### ########################################################### ########################################################### proc gradeQuestion { num questNum correct given answerStructVar } { global gScorer upvar $answerStructVar answerStruct set numRight 0 switch $gScorer(quest.$questNum.type.$num) { ONE_OUT_OF_10 - GLE - TF - SINGLE_DIGIT { # scorerMessage $num "The correct answer: $correct, The student's answer: $given" set fmt "%-$gScorer(quest.$questNum.leafs.$num)s," append answerStruct(correct) [format $fmt $correct] append answerStruct(given) [format $fmt $given] for { set leafs 0 } { $leafs < $gScorer(quest.$questNum.leafs.$num) } { incr leafs } { if { [string index $correct $leafs] == [string index $given $leafs] } { incr numRight } } } ASSIGNED { # scorerMessage $num "The student got a $given out of $gScorer(quest.$questNum.points.$num) " append answerStruct(correct) "$gScorer(quest.$questNum.points.$num)," append answerStruct(given) "$given," if { [catch {incr given 0}] } { set numRight 0 } else { set numRight $given } } N_OUT_OF_M { # scorerMessage $num "The correct answer: $correct, The student's answer: $given" set fmt "%-$gScorer(quest.$questNum.leafs.$num)s," append answerStruct(correct) [format $fmt $correct] append answerStruct(given) [format $fmt $given] set letters "ABCDEFGHIJ" set maxLeaf $gScorer(quest.$questNum.leafs.$num) for { set leaf 0 } { $leaf < $maxLeaf } { incr leaf } { if { [string first [string index $letters $leaf] $correct] != -1 } { set ansOn($leaf) 1 } else { set ansOn($leaf) 0 } } for { set leaf 0 } { $leaf < $maxLeaf } { incr leaf } { if { [string first [string index $letters $leaf] $given] != -1 } { set stuOn($leaf) 1 } else { set stuOn($leaf) 0 } } for { set leaf 0 } { $leaf < $maxLeaf } { incr leaf } { if { $ansOn($leaf) == $stuOn($leaf) } { incr numRight } } } STRING_MATCH { # scorerMessage $num "The correct answer: $correct, The student's answer: $given" set fmt "%-$gScorer(quest.$questNum.leafs.$num)s," append answerStruct(correct) [format $fmt $correct] append answerStruct(given) [format $fmt $given] set letters "ABCDEFGHIJ" set maxLeaf 10 for { set leaf 0 } { $leaf < $maxLeaf } { incr leaf } { if { [string first [string index $letters $leaf] $correct] != -1 } { set ansOn($leaf) 1 } else { set ansOn($leaf) 0 } } for { set leaf 0 } { $leaf < $maxLeaf } { incr leaf } { if { [string first [string index $letters $leaf] $given] != -1 } { set stuOn($leaf) 1 } else { set stuOn($leaf) 0 } } for { set leaf 0 } { $leaf < $maxLeaf } { incr leaf } { if { $ansOn($leaf) == $stuOn($leaf) } { incr numRight } } if { $numRight != $maxLeaf } { set numRight 0 } } default { scorerMessage $num "Unknown question type while grading," } } return $numRight } ########################################################### # gradeSet ########################################################### ########################################################### ########################################################### proc gradeSet { num answerStructVar questionPID } { global gScorer upvar $answerStructVar answerStruct set numRight 0 for { set i 0 } { $i < $answerStruct(maxQuest) } { incr i } { set correct [lindex $answerStruct(correct.$questionPID) $i] set given $answerStruct(answer.$i) set probRight [gradeQuestion $num $i $correct $given answerStruct] incr numRight $probRight append answerStruct($questionPID.numRight) $probRight } set answerStruct($questionPID.correct) $answerStruct(correct) set answerStruct(correct) "" set answerStruct($questionPID.given) $answerStruct(given) set answerStruct(given) "" return $numRight } ########################################################### # getScorerEntry ########################################################### ########################################################### ########################################################### proc getScorerEntry { num PID } { global gScorer set fileId $gScorer(out.$num) seek $fileId 0 start set done 0 set found 0 set aline "" set offset 0 while { ! $done } { set readamt [gets $fileId aline] if { [eof $fileId] } { set done 0 ; break} if { 0 == [ string compare [string toupper [lindex $aline 0]] \ [string toupper $PID] ] } { set done 1 set found 1 } else { #plus one because gets swallows the newline it reads set offset [expr $offset + $readamt + 1] } } if { ! $found } { set offset -$offset } return $offset } ########################################################### # setScorerEntry ########################################################### ########################################################### ########################################################### proc setScorerEntry { num aline offset } { global gScorer set fileId $gScorer(out.$num) seek $fileId [expr abs($offset)] start puts $fileId $aline } ########################################################### # setOutput ########################################################### ########################################################### ########################################################### proc setOutput { num answerStructVar} { global gScorer upvar $answerStructVar answerStruct #FIXME what if questions PID is empty set questionPID $answerStruct(questionPID) set out [format "%9s %-30s %s %4s %3s %s %s %s" $answerStruct(StudentNumber) \ $answerStruct(Name) $answerStruct($questionPID.numRight) \ $answerStruct($questionPID.grade) $answerStruct(Section) \ $answerStruct($questionPID.given) $questionPID \ $answerStruct(SerialNumber)] set offset [getScorerEntry $num $answerStruct(StudentNumber)] setScorerEntry $num "$out" $offset } ########################################################### # finishScoring ########################################################### ########################################################### ########################################################### proc finishScoring { num answerStructVar} { global gScorer scorerMessage $num "Finishing . . ." # puts "errors:" # puts "$gScorer(errors.$num)" scorerMessage $num "Finished, Feel free to Update .sb" if { [makeSure "Would you like to update the .sb file?"] == "Yes" } { scorerToSet $num } trace variable gScorer(quit.$num) w "scorerClose $num 0" } proc scorerStudentTime { num } { puts [ time "scorerStudent $num" ] } ########################################################### # scorerStudent ########################################################### ########################################################### ########################################################### proc scorerStudent { num } { global gScorer if { $gScorer(pause.$num) } { if { [array names gScorer quit.$num] != "" } { if { ![scorerClose $num] } { unset gScorer(quit.$num) set gScorer(pause.$num) 0 } else { return } } if { $gScorer(pause.$num) == 1 } { scorerMessage $num "Pausing. . . " info set gScorer(pause.$num) 2 } after 100 "scorerStudent $num" return } #getanswerline if { [ catch { set answer [ getLine $num ] } ] } { finishScoring $num answerStruct return } set gScorer(needToUpdateDB) 1 #parseanswerline if { [catch {parseLine $num $answer answerStruct} errorMsg ] } { displayError "Error parsing line: $errorMsg" } else { #parse the set and grades it for any possiblely matching student if { ! [ catch { set result [handleStudent $num answerStruct]} errorMsg ] } { #write entry to outputfile if student was succesfully handled if { $result } { setOutput $num answerStruct } } else { #error handling Student global errorCode errorInfo displayError "An error occured when attempting to grade a student. The error is: $errorMsg" } } incr gScorer(student.$num) update after idle "scorerStudent $num" } ########################################################### # restartScorer ########################################################### ########################################################### ########################################################### proc restartScorer { num } { global gScorer if { ! [info exists gScorer(pause.$num) ] } { initScorer $num set gScorer(pause.$num) 0 } else { } after idle "scorerStudent $num" } ########################################################### # pauseScorer ########################################################### ########################################################### ########################################################### proc pauseScorer { num } { global gScorer set gScorer(pause.$num) 1 } ########################################################### # stopScorer ########################################################### ########################################################### ########################################################### proc stopScorer { num } { } ########################################################### # unpauseScorer ########################################################### ########################################################### ########################################################### proc unpauseScorer { num } { global gScorer set gScorer(pause.$num) 0 } ########################################################### ########################################################### ########################################################### ########################################################### proc finalScorer { num method studentNumber numRight } { global gScorer set answers "" for { set i 0 } { $i < $gScorer(numQuest.$num) } { incr i } { switch $gScorer(quest.$i.type.$num) { ONE_OUT_OF_10 - SINGLE_DIGIT { append answers [ expr [string index $numRight $i] * \ $gScorer(quest.$i.points.$num) ] } GLE - TF - N_OUT_OF_M { set right [string index $numRight $i] set leafs $gScorer(quest.$i.leafs.$num) set points $gScorer(quest.$i.points.$num) set unit [expr double($points)/double($leafs)] if { $unit == 0 } { set unit $points } switch $method { CAPA { set score [expr int($points-(2*$unit*($leafs-$right)))] if { $score < 0 } { set score 0 } } Lenient { set score [expr int($points-($unit*($leafs-$right)))] } Strict { if { $right == $leafs } { set score $points } else { set score 0 } } default { scorerError $num UNKNOWN_GRADING_METHOD $method } } append answers $score } STRING_MATCH - ASSIGNED { append answers [string index $numRight $i] } default { } } } return $answers } ########################################################### # scorerToSet2 ########################################################### ########################################################### ########################################################### proc scorerToSet2 { num method } { global gScorer gFile destroy .getGradingMethod$num set processed 0 set done 0 set fileId $gScorer(out.$num) set setId $gScorer(set.$num) seek $fileId 0 start #remove the header line gets $fileId aline scorerMessage $num "Processing. . ." while { ! $done } { gets $fileId aline if { [eof $fileId] } { set done 1 break } set studentNumber [lindex $aline 0] incr processed if { [ expr $processed % 100 ] == 0 } { scorerMessage $num $processed } update idletasks set cwd [pwd] cd $gFile($num) if { ![file exists [file join records set$setId.sb] ] } { if { ![file exists [file join records set$setId.db] ] } { cd $cwd scorerMessage $num "set$setId.db does not exist" error return } else { scorerMessage $num "Copying set$setId.db to set$setId.sb" if { [catch {file copy [file join records set$setId.db] \ [file join records set$setId.sb] }] } { cd $cwd scorerMessage $num "Unable to create set$setId.sb from set$setId.db, please create it by hand" error return } } } if { [catch { set offset [ scorer_get_entry $studentNumber $setId ] } errors] } { cd $cwd scorerMessage $num "Error trying to read set$setId.sb" error return } cd $cwd set name [string range $aline 10 39] set numRight [lindex [string range $aline 40 end] 0] set entry(answers) [ finalScorer $num $method $studentNumber $numRight ] set entry(tries) "" for { set i 0 } { $i < $gScorer(numQuest.$num) } { incr i } { append entry(tries) ", 1" } set entry(tries) [string range $entry(tries) 1 end] set cwd [pwd] cd $gFile($num) if { [ catch { scorer_set_entry $studentNumber $setId $offset \ $entry(answers) $entry(tries) } errors ] } { cd $cwd scorerMessage $num "Error trying to update set$setId.sb" error return } cd $cwd } scorerMessage $num "Finished updating. . ." update idletasks set gScorer(needToUpdateDB) 0 if { [makeSure "Should I copy the updated set$setId.sb to set$setId.db"] == "Yes" } { if { [file exists [file join $gFile($num) records set$setId.db] ] } { if { [catch {file delete [file join $gFile($num) records set$setId.db]}]} { scorerMessage $num "An error occured while trying to copy. Please do this by hand." error } } if { [catch {file copy [file join $gFile($num) records set$setId.sb] \ [file join $gFile($num) records set$setId.db] }] } { scorerMessage $num "An error occured while trying to copy. Please do this by hand." error } } scorerMessage $num "Done" } ########################################################### # scorerToSet ########################################################### ########################################################### ########################################################### proc scorerToSet { num } { global gScorer #getGradingMethod set gradeWindow [toplevel .getGradingMethod$num] set messageFrame [frame $gradeWindow.mesg] set capaFrame [frame $gradeWindow.capa] set lenientFrame [frame $gradeWindow.lenient] set strictFrame [frame $gradeWindow.strict] set cancelFrame [frame $gradeWindow.cancel] pack $messageFrame $capaFrame $lenientFrame $strictFrame $cancelFrame \ -side top label $messageFrame.mesg -text "Please Select a Grading Method:" pack $messageFrame.mesg button $capaFrame.capa -text "CAPA Standard" -command "scorerToSet2 $num CAPA" # button $capaFrame.huh -text "Huh?" pack $capaFrame.capa -side left button $lenientFrame.lenient -text "Lenient Method" \ -command "scorerToSet2 $num Lenient" # button $lenientFrame.huh -text "Huh?" pack $lenientFrame.lenient -side left button $strictFrame.strict -text "Strict Method" \ -command "scorerToSet2 $num Strict" # button $strictFrame.huh -text "Huh?" pack $strictFrame.strict -side left button $cancelFrame.cancel -text "Cancel" -command "destroy $gradeWindow" pack $cancelFrame.cancel Centre_Dialog $gradeWindow default } ########################################################### # scorerQuit ########################################################### ########################################################### ########################################################### proc scorerQuit { num } { global gScorer set gScorer(pause.$num) 1 set gScorer(quit.$num) 1 #puts [trace vinfo gScorer(quit.$num)] catch {scorerMessage $num "Quitting. . . " info} } ########################################################### # scorerClose ########################################################### ########################################################### ########################################################### proc scorerClose { num {mustClose 0} {dummy ""} {dummy2 ""} {dummy3 ""}} { global gScorer set message "Are you sure you wish to close?" catch { if { $gScorer(needToUpdateDB) } { set message \ "Are you sure you wish to close, you haven't yet updated the .sb file." } } if { (! $mustClose ) && [makeSure $message ] == "Cancel" } { return 0 } stopScorer $num destroy .beginScorer$num # freeStudentList $num return 1 } ########################################################### # loadScorerQuest ########################################################### ########################################################### ########################################################### proc loadScorerQuest { num } { global gScorer gFile set filename [file join $gFile($num) records scorer.output.$gScorer(set.$num)] if { [ catch { set fileId [ open $filename "r" ] } ] } { displayError "The set $gScorer(set.$num) does not yet have an scorer.output file. " return } set line [gets $fileId ] close $fileId set numQuestions [lindex $line 2] set flags [lindex $line 4] $gScorer(quest.$num) delete 0 end for { set i 0 } { $i < $numQuestions } { incr i } { switch [string index $flags [expr $i * 3] ] { a { set gScorer(questType.$num) ONE_OUT_OF_10 } b { set gScorer(questType.$num) GLE } c { set gScorer(questType.$num) TF } d { set gScorer(questType.$num) ASSIGNED } e { set gScorer(questType.$num) N_OUT_OF_M } f { set gScorer(questType.$num) SINGLE_DIGIT } g { set gScorer(questType.$num) STRING_MATCH } } set gScorer(questPoint.$num) [string index $flags [expr $i * 3 + 1] ] set gScorer(questLeaf.$num) [string index $flags [expr $i * 3 + 2] ] insertQuest $num end } } ########################################################### # reScore ########################################################### ########################################################### ########################################################### proc reScore { file } { global gUniqueNumber gScorer gFile set num [incr gUniqueNumber] if { [catch {set gScorer(out.$num) [open $file "r"]}]} { displayError "Unable to open $file" return } set gScorer(set.$num) [lindex [split $file .] end] set gFile($num) [file dirname [file dirname $file]] set line [gets $gScorer(out.$num) ] set gScorer(numQuest.$num) [lindex $line 2] set flags [lindex $line 4] for { set i 0 } { $i < $gScorer(numQuest.$num) } { incr i } { switch [string index $flags [expr $i * 3] ] { a { set gScorer(quest.$i.type.$num) ONE_OUT_OF_10 } b { set gScorer(quest.$i.type.$num) GLE } c { set gScorer(quest.$i.type.$num) TF } d { set gScorer(quest.$i.type.$num) ASSIGNED } e { set gScorer(quest.$i.type.$num) N_OUT_OF_M } f { set gScorer(quest.$i.type.$num) SINGLE_DIGIT } g { set gScorer(quest.$i.type.$num) STRING_MATCH } } set gScorer(quest.$i.points.$num) [string index $flags [expr $i * 3 + 1] ] set gScorer(quest.$i.leafs.$num) [string index $flags [expr $i * 3 + 2] ] } set reScore [toplevel .reScore$num] wm title $reScore "ReScoring $file" set windowFrame [frame $reScore.windowFrame] set buttonFrame [frame $reScore.buttonFrame] pack $windowFrame $buttonFrame -side bottom pack configure $windowFrame -expand true -fill both pack configure $buttonFrame -anchor e scrollbar $windowFrame.scroll -orient vertical -command \ "$windowFrame.text yview" set gScorer(status.$num) [text $windowFrame.text -yscrollcommand \ "$windowFrame.scroll set" -wrap char -height 40] pack $windowFrame.scroll $gScorer(status.$num) -side left -expand 0 pack configure $windowFrame.scroll -expand 0 -fill y pack configure $gScorer(status.$num) -expand true -fill both button $buttonFrame.ok -text Dismiss -command \ "destroy $reScore catch {close $gScorer(out.$num)}" bind $reScore "catch {close $gScorer(out.$num)}" button $buttonFrame.save -text "Save Messages" -command "saveScorerMsg $num" button $buttonFrame.print -text "Print Messages" -command "printScorerMsg $num" pack $buttonFrame.print $buttonFrame.save $buttonFrame.ok -side left Centre_Dialog $reScore default update scorerToSet $num } #The flags struct is # name # question to ask # yes (1) response # no (0) response set gScorer(flags) \ { { CheckPIN {Is there a capaID/CODE on the paper?} Yes No 1 } { AnonMode {Is this an anonymous Exam?} Yes No 0 } { QueryAboutPID {When finding multiple PIDs matching a capaID:} {Ask which to use} {Pick one with highest score} 0 } } # { # SurveyMode # {What is being scanned?} # Survey # Exam/Quiz # 0 # } # { # SurveyHeader # {Does the Survey have a header?} # Yes # No # 0 # } # { # CheckSpaces # {Should scorer worry about blank questions?} # Yes # No # 0 # } # { # CheckMultipleMarks # {Should scorer worry about multiple marks on single mark questions?} # Yes # No # 0 # } # { # IdFormat # {What format is the student number in?} # A # {Social Security} # 1 # } # { # Form # {Which form size is being used? Select Half Sheet} # {Full sheet} # {Half Sheet} # 0 # } # { # log # {When encountering errors: Select Query the User} # {Log them} # {Query the user} # 1 # } #Counting from zero, first number is column of start of the field, #second number is end of the field. The Question field is an #exception first comes start of question responses then # of #responses, and then the number of bubbles per response #Full Sheet Specs set gScorer(FullSheet.SerialNumber) { 5 8 } set gScorer(FullSheet.LastName) { 40 49 } set gScorer(FullSheet.FirstName) { 50 54 } set gScorer(FullSheet.MiddleInitial) { 55 55 } set gScorer(FullSheet.StudentNumber) { 56 64 } set gScorer(FullSheet.Section) { 65 67 } set gScorer(FullSheet.CapaID) { } #No CapaID spot on full sheet set gScorer(FullSheet.Question) { 76 50 10 } #Half Sheet Specs set gScorer(HalfSheet.SerialNumber) { 5 8 } set gScorer(HalfSheet.LastName) { 40 49 } set gScorer(HalfSheet.FirstName) { 50 50 } set gScorer(HalfSheet.MiddleInitial) { } #No Middle Initial set gScorer(HalfSheet.StudentNumber) { 56 64 } set gScorer(HalfSheet.Section) { 65 67 } set gScorer(HalfSheet.CapaID) { 68 73 } set gScorer(HalfSheet.Question) { 76 50 10 }