File:  [LON-CAPA] / capa / capa51 / GUITools / scorer.tcl
Revision 1.14: download - view: text, annotated - select for diffs
Fri Jul 7 18:25:12 2000 UTC (23 years, 11 months ago) by albertel
Branches: MAIN
CVS tags: version5-1-2-first_release, HEAD
- GPL notices

    1: # automated scoring of bubble sheets
    2: #  Copyright (C) 1992-2000 Michigan State University
    3: #
    4: #  The CAPA system is free software; you can redistribute it and/or
    5: #  modify it under the terms of the GNU Library General Public License as
    6: #  published by the Free Software Foundation; either version 2 of the
    7: #  License, or (at your option) any later version.
    8: #
    9: #  The CAPA system is distributed in the hope that it will be useful,
   10: #  but WITHOUT ANY WARRANTY; without even the implied warranty of
   11: #  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   12: #  Library General Public License for more details.
   13: #
   14: #  You should have received a copy of the GNU Library General Public
   15: #  License along with the CAPA system; see the file COPYING.  If not,
   16: #  write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
   17: #  Boston, MA 02111-1307, USA.
   18: #
   19: #  As a special exception, you have permission to link this program
   20: #  with the TtH/TtM library and distribute executables, as long as you
   21: #  follow the requirements of the GNU GPL in regard to all of the
   22: #  software in the executable aside from TtH/TtM.
   23: 
   24: ###########################################################
   25: # scorer.output.num file looks like this
   26: # classname setNum numQuest flags questiondescriptor
   27: # flags come in the order of CheckPIN, AnonMode, (CheckSpaces, Gone)
   28: #       (SurveyMode, Gone) (SurveyHeader, Gone) (IdFormat, Gone) 
   29: #       (CheckMultipleMarks, Gone) QueryAboutPID, (log gone)
   30: ###########################################################
   31: 
   32: ###########################################################
   33: # scorerMessage
   34: ###########################################################
   35: ###########################################################
   36: ###########################################################
   37: proc scorerMessage { num mesg {tag normal} } {
   38:     global gScorer
   39:     $gScorer(status.$num) insert end "$mesg\n" $tag
   40:     $gScorer(status.$num) see end
   41: #    update
   42: }
   43: 
   44: ###########################################################
   45: # scorerError
   46: ###########################################################
   47: ###########################################################
   48: ###########################################################
   49: proc scorerError { num errorCode args } {
   50:     global gScorer
   51:     switch $errorCode {
   52: 	INVALID_CAPAID {
   53: 	    lappend gScorer(errortype.$num) $errorCode
   54: 	    lappend gScorer(errors.$num) [lindex $args 0]
   55: 	    scorerMessage $num "Student [lindex $args 1]'s paper had an unknown CapaID" error
   56: 	}
   57: 	LOTS_OF_ANON_MODE_MATCHES {
   58: 	    lappend gScorer(errortype.$num) $errorCode
   59: 	    lappend gScorer(errors.$num) [lindex $args 0]
   60: 	    scorerMessage $num "More than 6 Student IDs generate the closest match to the capaID specified on [lindex $args 1]'s paper" error
   61: 	}
   62: 	NO_CODE_IN_ANON_MODE {
   63: 	    lappend gScorer(errortype.$num) $errorCode
   64: 	    lappend gScorer(errors.$num) [lindex $args 0]
   65: 	    scorerMessage $num "There was no CapaID/CODE on [lindex $args 1]'s paper" error
   66: 	}
   67: 	NO_SUCH_STUDENT {
   68: 	    lappend gScorer(errortype.$num) $errorCode
   69: 	    lappend gScorer(errors.$num) [lindex $args 0]
   70: 	    scorerMessage $num "Unable to find [lindex $args 1] in classl" error
   71: 	}
   72: 	UNABLE_TO_PARSE {
   73: 	    lappend gScorer(errortype.$num) $errorCode
   74: 	    lappend gScorer(errors.$num) [lindex $args 0]
   75: 	    scorerMessage $num "An error occured while trying to parse the set for [lindex $args 1]'s paper" error
   76: 	}
   77: 	PINWRONG -
   78: 	UNKNOWN_GRADING_METHOD -
   79: 	CANT_OPEN_SB -
   80: 	CANT_UPDATE_SB -
   81: 	default {
   82: 	    displayError "$errorCode $args"
   83: 	}
   84:     }
   85:     incr gScorer(numerrors.$num)
   86:     update
   87: }
   88: 
   89: ###########################################################
   90: # runScorer
   91: ###########################################################
   92: ###########################################################
   93: ###########################################################
   94: proc runScorer { setFile } {
   95:     global gUniqueNumber gWindowMenu gFile gScorer
   96: 
   97:     set num [incr gUniqueNumber]
   98:     
   99:     set classDir [file dirname $setFile]
  100:     set gFile($num) $classDir
  101: #    puts "set gFile($num) to $gFile($num)"
  102:     set scorerWin [toplevel .beginScorer$num]
  103:     $gWindowMenu add command -label "ScorerConfig $classDir" \
  104: 	    -command "capaRaise \"$scorerWin\""
  105:     wm title $scorerWin $classDir
  106: 
  107:     set infoFrame [frame $scorerWin.infoFrame ]
  108:     set buttonFrame [frame $scorerWin.buttonFrame ]
  109:     set configFrame [frame $scorerWin.configFrame ]
  110:     pack $infoFrame $buttonFrame $configFrame -side top
  111: 
  112:     set classNameFrame [frame $infoFrame.classNameFrame]
  113:     set setNumFrame [frame $infoFrame.setNumFrame]
  114:     set scoreFileFrame [frame $infoFrame.scoreFileFrame]
  115:     pack $classNameFrame $setNumFrame $scoreFileFrame -side top -anchor w
  116: 
  117:     #classname
  118:     label $classNameFrame.label -text "Class Name:"
  119:     entry $classNameFrame.entry -textvariable gScorer(class.$num)\
  120: 	    -width 8
  121: #    button $classNameFrame.button -text "What Goes Here" \
  122: 	-command "helpScorer className"
  123:     pack $classNameFrame.label $classNameFrame.entry -side left
  124:     set gScorer(class.$num) [file tail $classDir]
  125: 
  126:     #set number
  127:     set gScorer(set.$num) [string range [file rootname [file tail $setFile]] 3 end]
  128:     label $setNumFrame.label -text "Set Number:"
  129:     entry $setNumFrame.set -width 2 -textvariable gScorer(set.$num)
  130:     pack $setNumFrame.label $setNumFrame.set -side left
  131: 
  132:     #scoring file
  133:     label $scoreFileFrame.label -text "Scoring Office File:"
  134:     set entryFrame [frame $scoreFileFrame.entryFrame]
  135:     button $scoreFileFrame.select -text "Select File" \
  136: 	    -command "selectScoringFile $num"
  137:     pack $scoreFileFrame.label $entryFrame $scoreFileFrame.select -side left
  138:     entry $entryFrame.entry -textvariable gScorer(scoreFile.$num) \
  139: 	    -xscrollcommand "$entryFrame.scroll set"
  140:     scrollbar $entryFrame.scroll -orient h -command \
  141: 	    "$entryFrame.entry xview"
  142:     pack $entryFrame.entry $entryFrame.scroll
  143:     pack configure $entryFrame.scroll -fill x
  144: 
  145:     #buttons
  146:     button $buttonFrame.cancel -text Cancel -command "destroy $scorerWin\
  147:                                 removeWindowEntry \"ScorerConfig $classDir\"" 
  148:     button $buttonFrame.continue -text "Continue" \
  149: 	    -command "getScorerQuest $num" 
  150:     button $buttonFrame.load -text "Load Previous Settings" \
  151: 	    -command "loadScorerConfig $num"
  152:     pack $buttonFrame.cancel $buttonFrame.continue $buttonFrame.load \
  153: 	    -side left
  154: 
  155:     #config options
  156:     #flag list is from scorer.h
  157:     foreach flaglist $gScorer(flags) {
  158: 	set flag [lindex $flaglist 0]
  159: 	set question [lindex $flaglist 1]
  160: 	set oneVal [lindex $flaglist 2]
  161: 	set zeroVal [lindex $flaglist 3]
  162: 	set defaultVal [lindex $flaglist 4]
  163: 	set frame($flag) [frame $configFrame.[string tolower $flag] \
  164: 		-relief groove -borderwidth 2]
  165: 	set gScorer($flag.frame.$num) $frame($flag)
  166: 	pack $frame($flag) -side top -anchor w
  167: 	set frame($flag.top) [frame $frame($flag).top]
  168: 	set frame($flag.bot) [frame $frame($flag).bot]
  169: 	pack $frame($flag.top) $frame($flag.bot) -side top -anchor w
  170: 	label $frame($flag.top).label -text "$question" -anchor w -width 70
  171: #	button $frame($flag.top).help -text "Huh?" -command "helpScorerFlags $flag"
  172:         pack $frame($flag.top).label  -side left
  173: 	radiobutton $frame($flag.bot).one -variable gScorer($flag.$num) \
  174: 		-value 1 -text $oneVal -command "configureOptions $num"
  175: 	radiobutton $frame($flag.bot).zero -variable gScorer($flag.$num) \
  176: 		-value 0 -text $zeroVal -command "configureOptions $num"
  177: 	set gScorer($flag.$num) $defaultVal
  178: 	pack $frame($flag.bot).one $frame($flag.bot).zero -side left
  179:     }
  180:     parseCapaConfig $num $gFile($num)
  181:     configureOptions $num
  182:     loadScorerConfig $num
  183:     Centre_Dialog $scorerWin default
  184: #    trace variable gScorer(quit.$num) w "scorerClose $num 0"
  185: }
  186: 
  187: ###########################################################
  188: # loadScorerConfig
  189: ###########################################################
  190: ###########################################################
  191: ###########################################################
  192: proc loadScorerConfig { num } {
  193:     global gScorer gFile
  194:     
  195:     set filename [file join $gFile($num) records scorer.output.$gScorer(set.$num)]
  196:     if { [ catch { set fileId [ open $filename "r" ] } ] } {
  197: 	displayMessage "Creating a new scorer.output file for set $gScorer(set.$num)."
  198: 	return
  199:     }
  200:     set line [gets $fileId ]
  201:     close $fileId
  202:     set flags [lindex $line 3]
  203: #When uncommenting or commenting the following lines make sure to update the actual 
  204: #index values
  205:     set gScorer(CheckPIN.$num) [string index $flags 0]
  206:     set gScorer(AnonMode.$num) [string index $flags 1]
  207: #    set gScorer(CheckSpaces.$num) [string index $flags 2]
  208: #    set gScorer(SurveyMode.$num) [string index $flags 3]
  209: #    set gScorer(SurveyHeader.$num) [string index $flags 4]
  210: #    set gScorer(IdFormat.$num) [string index $flags 5]
  211: #    set gScorer(CheckMultipleMarks.$num) [string index $flags 6]
  212:     set gScorer(QueryAboutPID.$num) [string index $flags 2]
  213: #    set gScorer(Form.$num) [string index $flags 8]
  214: #    set gScorer(log.$num) [string index $flags 9]
  215:     configureOptions $num
  216: }
  217: 
  218: ###########################################################
  219: ###########################################################
  220: ###########################################################
  221: ###########################################################
  222: proc configureOptions { num } {
  223:     global gScorer
  224:     
  225:     foreach frame [array names gScorer "*.frame.$num"] {
  226: 	pack forget $gScorer($frame)
  227:     }
  228:     
  229:     #    pack $gScorer(SurveyMode.frame.$num) -side top
  230:     #    if { $gScorer(SurveyMode.$num) } {}
  231:     #       pack $gScorer(SurveyHeader.frame.$num)
  232:     #    {} 
  233:     pack $gScorer(CheckPIN.frame.$num)
  234:     if { $gScorer(CheckPIN.$num) } {
  235: 	pack $gScorer(AnonMode.frame.$num)
  236: 	if { $gScorer(AnonMode.$num) } {
  237: 	    pack $gScorer(QueryAboutPID.frame.$num)
  238: 	} else {
  239: 	    set gScorer(QueryAboutPID.$num) 0
  240: 	}
  241:     } else {
  242: 	set gScorer(AnonMode.$num) 0
  243:     }
  244:     #	pack $gScorer(CheckSpaces.frame.$num)
  245:     #	pack $gScorer(CheckMultipleMarks.frame.$num)
  246:     #	pack $gScorer(IdFormat.frame.$num)	
  247:     #    {}
  248:     #    pack $gScorer(Form.frame.$num)
  249:     #    pack $gScorer(log.frame.$num)	
  250: }
  251: 
  252: ###########################################################
  253: # selectScoringFile
  254: ###########################################################
  255: ###########################################################
  256: ###########################################################
  257: proc selectScoringFile { num } {
  258:     global gScorer
  259:     if { "" != [ set temp [tk_getOpenFile] ] } {set gScorer(scoreFile.$num) $temp}
  260: }    
  261: 
  262: ###########################################################
  263: ###########################################################
  264: ###########################################################
  265: ###########################################################
  266: proc helpScorerFlags { flag } {
  267:     global gUniqueNumber gWindowMenu
  268: 
  269:     set num [incr gUniqueNumber]
  270:     set helpWin [toplevel .beginScorer$num]
  271:     $gWindowMenu add command -label "HelpFlag $flag" \
  272: 	    -command "capaRaise \" $helpWin\""
  273:     wm title $helpWin $flag
  274:     
  275:     button $helpWin.dismiss -text Dismiss -command "destroy $helpWin"
  276:     message $helpWin.help -aspect 2000
  277:     set help ""
  278:     switch $flag {
  279: #	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." } 
  280: #	SurveyHeader       { set help "If the Survey given include a header portion this will let ."}
  281: 	CheckPIN           { set help "bluh" }
  282: 	AnonMode           { set help "bluh" }
  283: 	QueryAboutPID      { set help "bluh" }
  284: #	CheckSpaces        { set help "bluh" }
  285: #	CheckMultipleMarks { set help "bluh" }
  286: #	IdFormat           { set help "bluh" }
  287: #       Form               { set help "bluh" }
  288: #	log                { set help "bluh" }
  289:     }
  290:     $helpWin.help configure -text "$help"
  291:     pack $helpWin.dismiss $helpWin.help
  292:     Centre_Dialog $helpWin default
  293: }
  294: 
  295: ###########################################################
  296: # getScorerQuest
  297: ###########################################################
  298: ###########################################################
  299: ###########################################################
  300: proc getScorerQuest { num } {
  301:     global gUniqueNumber gWindowMenu gFile gScorer
  302: 
  303:     if { ![file readable $gScorer(scoreFile.$num)] } {
  304: 	displayMessage "Please Select a readable scoring office report file before continuing."
  305: 	return
  306:     }
  307: 
  308:     set classDir $gFile($num) 
  309: 
  310:     set scorerWin ".beginScorer$num"
  311: 
  312:     set infoFrame  $scorerWin.infoFrame 
  313:     set buttonFrame $scorerWin.buttonFrame
  314:     set configFrame $scorerWin.configFrame
  315:     set classNameFrame $infoFrame.classNameFrame
  316:     set setNumFrame $infoFrame.setNumFrame
  317:     set scoreFileFrame $infoFrame.scoreFileFrame
  318:     set entryFrame $scoreFileFrame.entryFrame
  319: 
  320:     destroy $configFrame 
  321:     pack [frame $configFrame] 
  322: 
  323:     destroy $scoreFileFrame.select
  324:     $entryFrame.entry configure -state disabled
  325:     $classNameFrame.entry configure -state disabled
  326:     $setNumFrame.set configure -state disabled
  327: 
  328:     #disabeling the config options
  329:     set classNameFrame $infoFrame.classNameFrame
  330:     set setNumFrame $infoFrame.setNumFrame
  331:     $classNameFrame.entry configure -state disabled
  332:     $setNumFrame.set configure -state disabled
  333: 
  334:     $buttonFrame.continue configure -command "startScorer $num" 
  335:     $buttonFrame.load configure -command "loadScorerQuest $num"
  336:     
  337:     #question
  338:     set questButFrame [ frame $configFrame.butFrame ]
  339:     set questLabelFrame [frame $configFrame.label ]
  340:     set questListFrame [ frame $configFrame.listFrame ]
  341:     pack $questButFrame $questLabelFrame $questListFrame 
  342:     pack configure $questLabelFrame -anchor w 
  343:   
  344:     button $questButFrame.add -text "Add"  -command "addScorerQuest $num"
  345:     button $questButFrame.clone -text "Clone" -command "cloneScorerQuest $num"
  346:     button $questButFrame.rm -text "Remove" -command "rmScorerQuest $num"
  347:     button $questButFrame.change -text "Change" -command "changeScorerQuest $num"
  348:     pack $questButFrame.add $questButFrame.clone $questButFrame.rm \
  349: 	    $questButFrame.change -side left
  350: 
  351:     label $questLabelFrame.label -text "Num  Type             Points  Leafs"
  352:     pack $questLabelFrame.label
  353: 
  354:     #listbox
  355:     set gScorer(questNum.$num) [ listbox $questListFrame.questNum \
  356: 				     -width 3 -height 20 \
  357: 				     -yscrollcommand "$questListFrame.scroll set" ]
  358:     set gScorer(quest.$num) [ listbox $questListFrame.quest -width 50 -height 20 \
  359: 	    -yscrollcommand "$questListFrame.scroll set"]
  360:     scrollbar $questListFrame.scroll -orient v -command \
  361: 	"scrolltwo \"$questListFrame.quest yview\" \"$questListFrame.questNum yview\""
  362:     pack  $questListFrame.scroll $questListFrame.quest  \
  363: 	$questListFrame.questNum  -side right
  364:     pack configure $questListFrame.scroll -fill y
  365:     loadScorerQuest $num
  366:     update idletasks
  367:     Centre_Dialog $scorerWin default
  368: }
  369: 
  370: ###########################################################
  371: # configQuestWin
  372: ###########################################################
  373: ###########################################################
  374: ###########################################################
  375: proc configQuestWin { num action {message ""} {max 1} } {
  376:     global gScorer
  377: 
  378:     if { ![winfo exists .scorerQuestWin$num] } { return }    
  379:     set frame .scorerQuestWin$num.add.leaf
  380:     
  381:     switch $action {
  382: 	hide 
  383: 	{ pack forget $frame }
  384: 	show
  385: 	{
  386: 	    pack $frame
  387: 	    $frame.leafs configure -label $message
  388: 	    $frame.leafs configure -to $max
  389: 	}
  390:     }
  391: }
  392: 
  393: 
  394: ###########################################################
  395: # renumberScorerQuest
  396: ###########################################################
  397: ###########################################################
  398: ###########################################################
  399: proc renumberScorerQuest { num } {
  400:     global gScorer
  401:     $gScorer(questNum.$num) delete 0 end
  402:     set max [$gScorer(quest.$num) index end ]
  403:     for { set i 1 } { $i <= $max } { incr i } {
  404: 	lappend numList $i
  405:     }
  406:     eval "$gScorer(questNum.$num) insert 0 $numList"
  407:     $gScorer(questNum.$num) yview [ $gScorer(quest.$num) nearest 5 ]
  408: }
  409: 
  410: ###########################################################
  411: # insertQuest
  412: ###########################################################
  413: ###########################################################
  414: ###########################################################
  415: proc insertQuest { num where } {
  416:     global gScorer
  417: 
  418:     if { $where != "end" } { $gScorer(quest.$num) delete $where }
  419:     switch $gScorer(questType.$num) {
  420: 	ONE_OUT_OF_10
  421: 	-
  422: 	ASSIGNED
  423: 	-
  424: 	SINGLE_DIGIT
  425: 	-
  426: 	STRING_MATCH
  427: 	{
  428: 	    $gScorer(quest.$num) insert $where [format "%-13s %7s" \
  429: 		    $gScorer(questType.$num) $gScorer(questPoint.$num)]
  430: 	}
  431: 	GLE
  432: 	-
  433: 	TF
  434: 	-
  435: 	N_OUT_OF_M
  436: 	{
  437: 	    $gScorer(quest.$num) insert $where [format "%-13s %7s %6s" \
  438: 		    $gScorer(questType.$num) $gScorer(questPoint.$num) \
  439: 		    $gScorer(questLeaf.$num)]
  440: 	}
  441:     }
  442:     renumberScorerQuest $num
  443:     update
  444:     $gScorer(quest.$num) see $where
  445: }
  446: 
  447: ###########################################################
  448: # addScorerQuest
  449: ###########################################################
  450: ###########################################################
  451: ###########################################################
  452: proc addScorerQuest { num {position end} } {
  453:     global gUniqueNumber gWindowMenu gFile gScorer
  454: 
  455:     if { [winfo exists .scorerQuestWin$num] } { return }    
  456:     set questWin [ toplevel .scorerQuestWin$num ]
  457: 
  458:     if { ! [ info exists gScorer(questType.$num) ] } {
  459: 	set gScorer(questType.$num) ONE_OUT_OF_10
  460:     }
  461: 
  462:     set buttonFrame [ frame $questWin.button ]
  463:     set optionFrame [ frame $questWin.add ]
  464:     pack $buttonFrame $optionFrame -side top
  465: 
  466:     set text Change
  467:     if { $position == "end" } { 
  468: 	set text Add
  469:     } 
  470:     button $buttonFrame.done -text $text -command "insertQuest $num $position
  471:                                                    destroy $questWin"
  472:     button $buttonFrame.cancel -text "Cancel" -command "destroy $questWin"
  473:     pack $buttonFrame.done $buttonFrame.cancel -side left
  474: 
  475:     set typeFrame [ frame $optionFrame.type ]
  476:     set pointFrame [ frame $optionFrame.point ]
  477:     set leafFrame [ frame $optionFrame.leaf ]
  478:     pack $typeFrame $pointFrame $leafFrame -side top
  479: 
  480:     radiobutton $typeFrame.oneoutof8 -text "One out of no more than 10" -value "ONE_OUT_OF_10" \
  481: 	-variable gScorer(questType.$num) -command "configQuestWin $num hide" 
  482:     radiobutton $typeFrame.gletype -text "GLE type" -value "GLE" \
  483: 	-variable gScorer(questType.$num) \
  484: 	-command "configQuestWin $num show \"Number of Leafs\" 3 " 
  485:     radiobutton $typeFrame.tftype -text "TF type" -value "TF" \
  486: 	-variable gScorer(questType.$num) \
  487: 	-command "configQuestWin $num show \"Number of Leafs\" 5 "
  488:     radiobutton $typeFrame.assigned -text "Assigned score" -value "ASSIGNED" \
  489: 	-variable gScorer(questType.$num) -command "configQuestWin $num hide " 
  490:     radiobutton $typeFrame.noutofm -text "N out of M" -value "N_OUT_OF_M" \
  491: 	-variable gScorer(questType.$num) \
  492: 	-command "configQuestWin $num show \"What is the value of M\" 10 " 
  493:     radiobutton $typeFrame.singledigit -text "Single digit" -value "SINGLE_DIGIT" \
  494: 	-variable gScorer(questType.$num) -command "configQuestWin $num hide" 
  495:     radiobutton $typeFrame.exactstring -text "Exact string matching" \
  496: 	-value "STRING_MATCH" -variable gScorer(questType.$num) \
  497: 	-command "configQuestWin $num hide"
  498:     pack $typeFrame.oneoutof8 $typeFrame.gletype $typeFrame.tftype \
  499: 	$typeFrame.assigned $typeFrame.noutofm $typeFrame.singledigit  \
  500: 	$typeFrame.exactstring -side top -anchor w
  501: 
  502:     scale $pointFrame.points -from 0 -to 9 -variable gScorer(questPoint.$num) \
  503: 	-label "Point Value" -orient h -length 300
  504:     pack $pointFrame.points
  505: 
  506:     scale $leafFrame.leafs -from 1 -to 10 -variable gScorer(questLeaf.$num) \
  507: 	-label "Number of Leafs" -orient h -length 300
  508:     pack $leafFrame.leafs
  509:     
  510:     switch $gScorer(questType.$num) {
  511: 	ONE_OUT_OF_10
  512: 	-
  513: 	ASSIGNED
  514: 	-
  515: 	SINGLE_DIGIT
  516: 	-
  517: 	STRING_MATCH { configQuestWin $num hide }
  518: 	GLE { configQuestWin $num show "Number of Leafs" 3 }
  519: 	TF { configQuestWin $num show "Number of Leafs" 5 }
  520: 	N_OUT_OF_M { configQuestWin $num show "What is the value of M" 10 }
  521:     }
  522:     Centre_Dialog $questWin default
  523: }
  524: 
  525: ###########################################################
  526: # cloneScorerQuest
  527: ###########################################################
  528: ###########################################################
  529: ###########################################################
  530: proc cloneScorerQuest { num } {
  531:     global gUniqueNumber gWindowMenu gFile gScorer
  532: 
  533:     if { [ $gScorer(quest.$num) curselection ] == "" } { 
  534: 	displayError "Please select an exisiting question to clone."
  535: 	return
  536:     }
  537:     
  538:     set temp [ $gScorer(quest.$num) get [ $gScorer(quest.$num) curselection ] ]
  539:     $gScorer(quest.$num) insert end $temp
  540:     $gScorer(quest.$num) see end
  541:     renumberScorerQuest $num
  542: }
  543: 
  544: ###########################################################
  545: # rmScorerQuest
  546: ###########################################################
  547: ###########################################################
  548: ###########################################################
  549: proc rmScorerQuest { num } {
  550:     global gUniqueNumber gWindowMenu gFile gScorer
  551: 
  552:     if { [winfo exists .scorerQuestWin$num] } { return }    
  553:     if { [ $gScorer(quest.$num) curselection ] == "" } { 
  554: 	displayError "Please select an exisiting question to delete."
  555: 	return
  556:     }
  557:     $gScorer(quest.$num) delete [$gScorer(quest.$num) curselection]
  558:     renumberScorerQuest $num
  559: }
  560: 
  561: ###########################################################
  562: # changeScorerQuest
  563: ###########################################################
  564: ###########################################################
  565: ###########################################################
  566: proc changeScorerQuest { num } {
  567:     global gUniqueNumber gWindowMenu gFile gScorer
  568: 
  569:     if { [winfo exists .scorerQuestWin$num] } { return }    
  570:     if { [ $gScorer(quest.$num) curselection ] == "" } { 
  571: 	displayError "Please select an exisiting question to change."
  572: 	return
  573:     }
  574:     
  575:     set position [ $gScorer(quest.$num) curselection ]
  576:     set gScorer(questType.$num) [lindex [$gScorer(quest.$num) get $position ] 0 ]
  577:     set gScorer(questPoint.$num) [lindex [$gScorer(quest.$num) get $position ] 1 ]
  578:     set gScorer(questLeaf.$num) [lindex [$gScorer(quest.$num) get $position ] 2 ]
  579:     addScorerQuest $num $position
  580: }
  581: 
  582: ###########################################################
  583: # startScorer
  584: ###########################################################
  585: ###########################################################
  586: ###########################################################
  587: proc startScorer { num } {
  588:     global gScorer gFile
  589:     
  590:     set scorerWin .beginScorer$num
  591: 
  592:     set filename [file join $gFile($num) records scorer.output.$gScorer(set.$num)]
  593:     if { [ catch { set fileId [ open $filename "w+" ] } ] } {
  594: 	displayError "Unable to write to the scorer.output file. "
  595: 	return
  596:     }
  597: #When deleting or adding anything to the flags var make sure to update loadScorerConfig
  598: #    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)
  599:     set flags $gScorer(CheckPIN.$num)$gScorer(AnonMode.$num)$gScorer(QueryAboutPID.$num)
  600:     set numQuestion [ $gScorer(quest.$num) index end ]
  601:     set questString ""
  602:     for { set i 0 } { $i < $numQuestion } { incr i } {
  603: 	set line [ $gScorer(quest.$num) get $i ]
  604: 	set gScorer(quest.$i.type.$num) [lindex $line 0]
  605: 	switch [lindex $line 0 ] {
  606: 	    ONE_OUT_OF_10 { append questString a }
  607: 	    GLE { append questString b }
  608: 	    TF { append questString c }
  609: 	    ASSIGNED { append questString d }
  610: 	    N_OUT_OF_M { append questString e }
  611: 	    SINGLE_DIGIT { append questString f }
  612: 	    STRING_MATCH { append questString g }
  613: 	}
  614: 	append questString [lindex $line 1]
  615: 	set gScorer(quest.$i.points.$num) [lindex $line 1]
  616: 	if { [ lindex $line 2 ] == "" } {
  617: 	    set gScorer(quest.$i.leafs.$num) 1
  618: 	    append questString 1
  619: 	} else {
  620: 	    set gScorer(quest.$i.leafs.$num) [lindex $line 2]
  621: 	    append questString [lindex $line 2] 
  622: 	}
  623:     }
  624:     set outputLine "$gScorer(class.$num) $gScorer(set.$num) $numQuestion $flags $questString"
  625:     puts $fileId [format "%-500s" $outputLine]
  626:     close $fileId
  627:     destroy $scorerWin.buttonFrame
  628:     destroy $scorerWin.configFrame
  629: 
  630:     set gScorer(student.$num) 0
  631:     set gScorer(numerrors.$num) 0
  632: 
  633:     set buttonFrame [frame $scorerWin.buttonFrame]
  634:     set statusFrame [frame $scorerWin.statusFrame]
  635:     pack $buttonFrame $statusFrame
  636: 
  637:     button $buttonFrame.pause -text Pause -command "pauseScorer $num"
  638:     button $buttonFrame.cont -text Continue -command "unpauseScorer $num"
  639:     button $buttonFrame.restart -text Restart -command "restartScorer $num"
  640:     button $buttonFrame.final -text "Update .sb" -command "scorerToSet $num"
  641:     button $buttonFrame.exit -text "Quit" -command "scorerQuit $num"
  642:     pack $buttonFrame.pause $buttonFrame.cont $buttonFrame.restart \
  643: 	$buttonFrame.final $buttonFrame.exit -side left
  644: 
  645:    
  646:     message $statusFrame.mesg -text "Messages:" -aspect 2000
  647:     set statusText [frame $statusFrame.statusText]
  648:     set student [frame $statusFrame.student]
  649:     set errors [frame $statusFrame.errors]
  650:     set statusButtons [frame $statusFrame.button]
  651:     pack $statusFrame.mesg $statusFrame.statusText $statusFrame.student \
  652: 	$statusFrame.errors $statusFrame.button
  653:     pack configure $statusFrame.mesg $statusFrame.student $statusFrame.errors \
  654: 	-anchor w 
  655:     pack configure $statusText -expand 1 -fill both
  656:     
  657:     set gScorer(status.$num) [text $statusText.text -wrap char \
  658: 				  -yscrollcommand "$statusText.scroll set"]
  659:     $gScorer(status.$num) tag configure error -foreground red
  660:     $gScorer(status.$num) tag configure info -foreground #006c00
  661: 
  662:     scrollbar $statusText.scroll -orient v -command "$statusText.text yview"
  663:     pack $statusText.text $statusText.scroll -side left
  664:     pack configure $statusText.scroll -fill y
  665:     pack configure $gScorer(status.$num) -expand 1 -fill both
  666: 
  667:     label $student.mesg -text "Students completed:"
  668:     label $student.num -textvariable gScorer(student.$num)
  669:     pack $student.mesg $student.num -side left
  670: 
  671:     label $errors.mesg -text "Errors To Be Handled:"
  672:     label $errors.num -textvariable gScorer(numerrors.$num)
  673:     pack $errors.mesg $errors.num -side left
  674:     
  675:     button $statusButtons.handleErrors -text "Save Errors" \
  676: 	-command "handleErrorsScorer $num"
  677:     button $statusButtons.printMsg -text "Print Messages" \
  678: 	-command "printScorerMsg $num"
  679:     button $statusButtons.saveMsg -text "Save Messages" \
  680: 	-command "saveScorerMsg $num"
  681:     button $statusButtons.clearMsg -text "Clear Messages" \
  682: 	-command "clearScorerMsg $num"
  683:     pack $statusButtons.handleErrors $statusButtons.printMsg \
  684: 	$statusButtons.saveMsg -side left
  685: 
  686:     wm protocol $scorerWin WM_DELETE_WINDOW "usequit $num"
  687:     update idletasks 
  688:     Centre_Dialog $scorerWin default
  689: #    set gScorer(quit.$num) 0
  690:     restartScorer $num
  691: }
  692: 
  693: ###########################################################
  694: # usequit
  695: ###########################################################
  696: ###########################################################
  697: ###########################################################
  698: proc usequit { num } { scorerMessage $num "Please use the Quit Button." info }
  699: 
  700: ###########################################################
  701: # saveScorerMsg
  702: ###########################################################
  703: ###########################################################
  704: ###########################################################
  705: proc saveScorerMsg { num } {
  706:     global gScorer
  707: 
  708:     set file [tk_getSaveFile -title "Enter the name to save messages to."]
  709:     if { $file == "" } { return }
  710:     if { [catch {set fileId [open $file "w"] } ] } { 
  711: 	displayError "Unable to open $file"
  712: 	return 
  713:     }
  714:     set tag [getWhichTags "All {Errors Only} {NonErrors Only}" "{} error normal" "saved"]
  715:     puts -nonewline $fileId [getTextTagged $gScorer(status.$num) $tag ]
  716:     close $fileId
  717: }
  718: 
  719: ###########################################################
  720: # printScorerMsg
  721: ###########################################################
  722: ###########################################################
  723: ###########################################################
  724: proc printScorerMsg { num } {
  725:     global gScorer gFile
  726: 
  727:     set file [file join $gFile($num) managertemp.txt]
  728:     set lprCommand [getLprCommand $file $num]
  729:     if  { $lprCommand == "Cancel" } { return }
  730:     if { [catch {set fileId [open $file "w"] } ] } { 
  731: 	displayError "Unable to open $file"
  732: 	return 
  733:     }
  734:     set tag [getWhichTags "All {Errors Only} {NonErrors Only}" "{} error normal" printed]
  735:     puts -nonewline $fileId [getTextTagged $gScorer(status.$num) $tag ]
  736:     close $fileId
  737:     set errorMsg ""
  738:     set error [catch {set output [ eval "exec $lprCommand" ] } errorMsg ]
  739:     exec rm -f $file
  740:     if { $error == 1 } {
  741:         displayError "An error occurred while printing: $errorMsg"
  742:     } else {
  743: 	displayMessage "Print job sent to the printer.\n $output"
  744:     }
  745: }
  746: 
  747: ###########################################################
  748: # initScorer
  749: ###########################################################
  750: ###########################################################
  751: ###########################################################
  752: proc initScorer { num } {
  753:     global gScorer gFile
  754:     
  755:     scorerMessage $num "Initializing. . ."
  756: 
  757:     if { ![info exists gScorer(in.$num)] || ( $gScorer(in.$num) == "" ) } {
  758: 	if { [catch {set gScorer(in.$num) \
  759: 			 [ open $gScorer(scoreFile.$num) "r" ] } ] } {
  760: 	    displayError "Unable to open input file $gScorer(scoreFile.$num)"
  761: 	    exit
  762: 	} 
  763:     }
  764: 
  765:     set filename [file join $gFile($num) records scorer.output.$gScorer(set.$num)]
  766:     if { ![info exists gScorer(out.$num)] || ( $gScorer(out.$num) == "" ) } {
  767: 	if { [catch {set gScorer(out.$num) [ open $filename "a+" ] } ] } {
  768: 	    displayError "Unable to open input file $filename"	    
  769: 	    exit
  770: 	}
  771:     }
  772: 
  773:     scorerMessage $num "Building List of Students. . ." 
  774:     update
  775:     set oldDir [pwd]
  776:     cd $gFile($num)
  777:     
  778: #4 is the length of the CapaID
  779:     set a $gScorer(HalfSheet.CapaID)
  780:     set capaidplus [expr {[lindex $a 1] - [lindex $a 0] - 3}]
  781: #    puts "$capaidplus, $a"
  782:     set gScorer(studentList.$num) [buildStudentList $num $gScorer(class.$num) \
  783: 				       $gScorer(set.$num) $capaidplus]
  784:     cd $oldDir
  785: }
  786: 
  787: ###########################################################
  788: # getLine
  789: ###########################################################
  790: ###########################################################
  791: ###########################################################
  792: proc getLine { num } {
  793:     global gScorer
  794:     
  795:     scorerMessage $num "\nGetting Responses"
  796: 
  797:     set done 0
  798:     while { ! $done } {
  799: 	gets $gScorer(in.$num) aline
  800: 	if { [eof $gScorer(in.$num) ] } { error EOF }
  801: 	if { ![string match "#*" $aline] } {
  802: 	    set done 1
  803: 	}
  804:     }
  805:     return $aline
  806: }
  807: 
  808: ###########################################################
  809: # oneResponse
  810: ###########################################################
  811: ###########################################################
  812: ###########################################################
  813: proc oneResponse { response max which } {
  814:     upvar $which whichVar
  815:     set whichVar ""
  816:     set howmany 0
  817:     for { set i 0 } { $i < $max } { incr i } {
  818: 	if { [string index "$response" $i] == "1" } {
  819: 	    lappend whichVar $i
  820: 	    incr howmany
  821: 	}
  822:     }
  823:     return $howmany
  824: }
  825: ###########################################################
  826: # parseLine
  827: ###########################################################
  828: ###########################################################
  829: ###########################################################
  830: proc parseLine { num answerLine answerStruct } {
  831:     global gScorer gMult
  832:     upvar $answerStruct parsedIn
  833:     set result ""
  834: 
  835:     scorerMessage $num "Understanding Responses"
  836: 
  837: # Only support HalfSheets
  838: #    if { $gScorer(Form.$num) } {
  839: #	set sheet FullSheet
  840: #    } else {
  841: #	set sheet HalfSheet 
  842: #    }
  843:     set sheet HalfSheet
  844: 
  845:     set parsedIn(orignalLine) "$answerLine"
  846:     foreach type { SerialNumber LastName FirstName MiddleInitial
  847: 	StudentNumber Section CapaID } {
  848: 	if { [ catch {set parsedIn($type) [string range "$answerLine" \
  849: 					   [lindex $gScorer($sheet.$type) 0] \
  850: 					   [lindex $gScorer($sheet.$type) 1] ] } ] } {
  851: 	    set parsedIn($type) ""
  852: 	}
  853:     }
  854:     set letter "ABCDEFGHIJ"
  855:     set number "1234567890"
  856:     set offset   [lindex $gScorer($sheet.Question) 0]
  857:     set maxQuest [lindex $gScorer($sheet.Question) 1]
  858:     set perQuest [lindex $gScorer($sheet.Question) 2]
  859:     set parsedIn(multiplemarks) 0
  860:     set parsedIn(spaces) 0
  861:     set parsedIn(maxQuest) $maxQuest
  862:     for { set i 0 } { $i < $maxQuest } { incr i } {
  863: 	if { [ catch { set gScorer(quest.$i.type.$num) } ] } {
  864: 	    set parsedIn(maxQuest) $i
  865: 	    set gScorer(numQuest.$num) $i
  866: 	    break
  867: 	}
  868: 	set array $letter
  869: 	set start [expr $i * $perQuest + $offset ]
  870: 	set stop [expr $start + $perQuest - 1 ]
  871: 	set response [string range "$answerLine" $start $stop]
  872: 	switch $gScorer(quest.$i.type.$num) {
  873: 	    ASSIGNED -
  874: 	    SINGLE_DIGIT -
  875: 	    ONE_OUT_OF_10 {
  876: 		if { $gScorer(quest.$i.type.$num) != "ONE_OUT_OF_10" } {
  877: 		    set array $number
  878: 		}
  879: 		set howmany [oneResponse "$response" $perQuest which]
  880: 		if { $howmany == 1 } {
  881: 		    set parsedIn(answer.$i) [string index $array $which]
  882: 		} else {
  883: 		    if { $howmany > 1 } { 
  884: 			set options ""
  885: 			foreach possible $which {
  886: 			    append options "[string index $array $possible] "
  887: 			}
  888: 			set selected [multipleChoice . "There were multiple marks on\nPaper Number $parsedIn(SerialNumber)\nStudentNumber $parsedIn(StudentNumber)\nProblem Number [expr $i+1]" $options]
  889: 			#puts ":$parsedIn(StudentNumber):$parsedIn(SerialNumber):[format %2d [expr $i+1]]:$selected:$options"
  890: 			set parsedIn(answer.$i) $selected
  891: 			#puts $parsedIn(answer.$i)
  892: 			incr parsedIn(multiplemarks)
  893: 		    } else {
  894: 			if { $howmany < 1 } { 
  895: 			    set parsedIn(answer.$i) " "
  896: 			    incr parsedIn(spaces)
  897: 			}
  898: 		    }
  899: 		}
  900: 	    }
  901: 	    GLE -
  902: 	    TF {
  903: 		if { $gScorer(quest.$i.type.$num) != "GLE" } {
  904: 		    set stepsize 2
  905: 		} else {
  906: 		    set stepsize 3
  907: 		}
  908: 		set leafs $gScorer(quest.$i.leafs.$num)
  909: 		for { set j 0 } { $j < $leafs } { incr j } {
  910: 		    set start [expr $j*$stepsize]
  911: 		    set stop  [expr $start + $stepsize - 1]
  912: 		    set howmany [oneResponse [string range \
  913:                         $response $start $stop] $perQuest which]
  914: 		    if { $howmany == 1 } {
  915: 			append parsedIn(answer.$i) [string index $array \
  916: 							[expr {$start + $which}]]
  917: 		    } else {
  918: 			if { $howmany > 1 } { 
  919: 			    set options ""
  920: 			    foreach possible $which {
  921: 				append options "[string index $array [expr {$start + $possible}]] "
  922: 			    }
  923: 			    set selected [multipleChoice . "There were multiple marks on\nPaper Number $parsedIn(SerialNumber)\nStudentNumber $parsedIn(StudentNumber)\nProblem Number [expr $i+1]" $options]
  924: 			    #puts ":$parsedIn(StudentNumber):$parsedIn(SerialNumber):[format %2d [expr $i+1]]:$selected:$options"
  925: 			    append parsedIn(answer.$i) $selected
  926: 			    #puts $parsedIn(answer.$i)
  927: 			    incr parsedIn(multiplemarks)
  928: 			} else {
  929: 			    if { $howmany < 1 } { 
  930: 				append parsedIn(answer.$i) " "
  931: 				incr parsedIn(spaces)
  932: 			    }
  933: 			}
  934: 		    }
  935: 		}
  936: 	    }
  937: 	    N_OUT_OF_M -
  938: 	    STRING_MATCH { 
  939: 		set found 0
  940: 		for { set j 0 } { $j < $perQuest } { incr j } {
  941: 		    set char [string index "$response" $j]
  942: 		    if { "$char" == 1 } {
  943: 			append parsedIn(answer.$i) [string index $array $j]
  944: 			incr found
  945: 		    }
  946: 		}
  947: 		if { ! $found } { 
  948: 		    incr parsedIn(spaces) 
  949: 		    set parsedIn(answer.$i) ""
  950: 		}
  951: 	    }
  952: 	}
  953:     }
  954:     #if there isn't a capaId already, treat the first four questions as
  955:     # capaID
  956: #    if { $parsedIn(CapaID) == "" && $gScorer(CheckPIN.$num) } {
  957: #	set pinWrong 0
  958: #	for {set j 0} {$j < 4} {incr j} {
  959: #	    switch -regexp "$parsedIn(answer.$j)" {
  960: #		^[A-J]$ {
  961: #		    append parsedIn(CapaID) \
  962: 			[string first $parsedIn(answer.$j) "ABCDEFGHIJ" ]
  963: #		}
  964: #		default {
  965: #		    set pinWrong 1
  966: #		}
  967: #	    }
  968: #	}
  969: #	if { $pinWrong } {
  970: #	    scorerError $num PINWRONG parsedIn
  971: #	    lappend result PINWRONG
  972: #	}
  973: #    } 
  974: #    parray parsedIn
  975:     if { $result != "" } {
  976: 	error "$result"
  977:     }
  978:     if { [catch {incr gMult $parsedIn(multiplemarks)}] } {
  979: 	set gMult $parsedIn(multiplemarks)
  980:     }
  981: #    puts $gMult
  982: }
  983: 
  984: proc getAnswers2 { PID set maxQuest num } {
  985:     global gFile
  986:     set pwd [pwd]
  987:     cd $gFile($num)
  988:     set result [getAnswersFromSet $PID $set $maxQuest]
  989:     cd $pwd
  990:     return $result
  991: }
  992: 
  993: proc getAnswers { PID set maxQuest num } {
  994:     global gFile gCapaConfig
  995:     set pwd [pwd]
  996:     cd $gFile($num)
  997:     set temp [exec $gCapaConfig($num.answers_command) $PID {} 0 $set]
  998:     cd $pwd
  999:     set result ""
 1000:     foreach line [split $temp "\n"] {
 1001: 	switch -- [lindex [split $line :] 0] {
 1002: 	    ANS { lappend result [string range $line 4 end] }
 1003: 	}
 1004:     }
 1005:     return $result
 1006: }
 1007: 
 1008: ###########################################################
 1009: # checkStudentNumber
 1010: ###########################################################
 1011: ###########################################################
 1012: ###########################################################
 1013: proc checkStudentNumber { num answerStructVar } {
 1014:     global gScorer gFile
 1015:     upvar $answerStructVar answerStruct
 1016: 
 1017: #    puts "Stunum1:$answerStruct(StudentNumber):"
 1018:     if { ![inClasslist $num $answerStruct(StudentNumber)] } {
 1019: #	puts "Stunum2:$answerStruct(StudentNumber):"
 1020: 	set matched [findByStudentName [string trim $answerStruct(LastName)] $gFile($num)]
 1021: 	if { [llength $matched] != 1 } {
 1022: 	    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)"
 1023: 	} else {
 1024: 	    set id [lindex [lindex $matched 0] 0]
 1025: 	    if { [makeSure "Unable to find bubbled id: $answerStruct(StudentNumber), name: $answerStruct(LastName) in classl, however I did find $matched. Use this one?"] != "Yes" } {
 1026: 		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)"
 1027: 	    } else {
 1028: 	    }
 1029: 	}
 1030: 	if { $id == "" } {
 1031: 	    scorerError $num NO_SUCH_STUDENT "$answerStruct(orignalLine)" \
 1032: 		$answerStruct(StudentNumber)
 1033: 	    return 0
 1034: 	} else {
 1035: 	    scorerMessage $num "Student Number $answerStruct(StudentNumber) not found in classl using $id instead." info
 1036: 	    set answerStruct(StudentNumber) $id
 1037: 	}
 1038:     }
 1039: #    puts "Stunum3:$answerStruct(StudentNumber):"
 1040:     return 1
 1041: }
 1042: 
 1043: ###########################################################
 1044: # handleStudent 
 1045: ###########################################################
 1046: ###########################################################
 1047: ###########################################################
 1048: proc handleStudent { num answerStructVar} {
 1049:     global gScorer gFile
 1050:     upvar $answerStructVar answerStruct
 1051:     
 1052:     if { ![checkStudentNumber $num answerStruct] } { return 0 }
 1053: 
 1054:     scorerMessage $num "Finding Possible Students. . ."
 1055:     if { ! $gScorer(AnonMode.$num) } {
 1056: 	set answerStruct(questionPID) $answerStruct(StudentNumber)
 1057:     } else {
 1058: #	puts "$answerStruct(StudentNumber):$answerStruct(CapaID):"
 1059: 	if { [string trim $answerStruct(CapaID)] == "" } { 
 1060: 	    scorerError $num NO_CODE_IN_ANON_MODE "$answerStruct(orignalLine)" \
 1061: 		$answerStruct(StudentNumber)
 1062: 	    return 0
 1063: 	}
 1064: 	set answerStruct(questionPID) [getAnonModeID $num answerStruct]
 1065: 	if { [llength $answerStruct(questionPID)] > 6 } {
 1066: 	    scorerError $num LOTS_OF_ANON_MODE_MATCHES "$answerStruct(orignalLine)" \
 1067: 		$answerStruct(StudentNumber)
 1068: 	    return 0
 1069: 	} else {
 1070: 	    if { [llength $answerStruct(questionPID)] == 0 } {
 1071: 		scorerError $num INVALID_CAPAID "$answerStruct(orignalLine)" \
 1072: 		    $answerStruct(StudentNumber)
 1073: 		return 0
 1074: 	    }
 1075: 	}
 1076:     }
 1077:     set answerStruct(Name) "$answerStruct(LastName) $answerStruct(FirstName) $answerStruct(MiddleInitial)"
 1078: 
 1079:     scorerMessage $num "Getting Possible Answers for $answerStruct(StudentNumber), paper#  $answerStruct(SerialNumber). . ."
 1080:     foreach questionPID $answerStruct(questionPID) {
 1081: 	scorerMessage $num "Getting Answers for $questionPID. . ."
 1082: 	if { [catch { set answerStruct(correct.$questionPID) \
 1083: 			  [getAnswers $questionPID $gScorer(set.$num) \
 1084: 			       $answerStruct(maxQuest) $num] } errorMsg ] } {
 1085: 	    catch {puts $errorMsg}
 1086: 	    scorerError $num UNABLE_TO_PARSE "$answerStruct(orignalLine)" \
 1087: 		$answerStruct(StudentNumber)
 1088: 	    error UNABLE_TO_PARSE
 1089: 	}
 1090: #	puts "$answerStruct(correct.$questionPID)"
 1091:     }
 1092: 
 1093:     scorerMessage $num "Grading Answers. . ."
 1094:     foreach questionPID $answerStruct(questionPID) {
 1095: 	set answerStruct($questionPID.grade) [gradeSet $num answerStruct $questionPID] 
 1096: 	scorerMessage $num "Correct: $answerStruct($questionPID.correct) #correct: $answerStruct($questionPID.grade) PID: $questionPID"
 1097:     }
 1098:     scorerMessage $num "Given:   $answerStruct($questionPID.given)"
 1099:     if { [llength $answerStruct(questionPID)] >  1 } {
 1100: 	scorerMessage $num "Selecting Student. . ."
 1101: 	if { $gScorer(QueryAboutPID.$num) } {
 1102: 	    set answerStruct(questionPID) \
 1103: 		[getWhichAnon $num answerStruct $answerStruct(indices)]
 1104: 	} else {
 1105: 	    set answerStruct(questionPID) \
 1106: 		[pickAnonHighest $num answerStruct $answerStruct(indices)]
 1107: 	}
 1108: 	scorerMessage $num "Student $answerStruct(StudentNumber) selected $answerStruct(questionPID)'s paper." info
 1109:     } 
 1110:     return 1
 1111: }
 1112: 
 1113: ###########################################################
 1114: # gradeQuestion
 1115: ###########################################################
 1116: ###########################################################
 1117: ###########################################################
 1118: proc gradeQuestion { num questNum correct given answerStructVar } {
 1119:     global gScorer
 1120:     upvar $answerStructVar answerStruct
 1121:     set numRight 0
 1122:     switch $gScorer(quest.$questNum.type.$num) {
 1123: 	ONE_OUT_OF_10 -
 1124: 	GLE -
 1125: 	TF -
 1126: 	SINGLE_DIGIT {
 1127: #	    scorerMessage $num "The correct answer: $correct, The student's answer: $given"
 1128: 	    set fmt "%-$gScorer(quest.$questNum.leafs.$num)s," 
 1129: 	    append answerStruct(correct) [format $fmt $correct]
 1130: 	    append answerStruct(given) [format $fmt $given]
 1131: 	    for { set leafs 0 } { $leafs < $gScorer(quest.$questNum.leafs.$num) 
 1132: 			      }   { incr leafs } {
 1133: 		if { [string index $correct $leafs] ==
 1134: 		     [string index $given $leafs] } {
 1135: 		    incr numRight
 1136: 		}
 1137: 	    }
 1138: 	}
 1139: 	ASSIGNED {
 1140: #	    scorerMessage $num "The student got a $given out of $gScorer(quest.$questNum.points.$num) "
 1141: 	    append answerStruct(correct) "$gScorer(quest.$questNum.points.$num),"
 1142: 	    append answerStruct(given) "$given,"
 1143: 	    if { [catch {incr given 0}] } {
 1144: 		set numRight 0
 1145: 	    } else {
 1146: 		set numRight $given
 1147: 	    }
 1148: 	}
 1149: 	N_OUT_OF_M {
 1150: #	    scorerMessage $num "The correct answer: $correct, The student's answer: $given"
 1151: 	    set fmt "%-$gScorer(quest.$questNum.leafs.$num)s," 
 1152: 	    append answerStruct(correct) [format $fmt $correct]
 1153: 	    append answerStruct(given) [format $fmt $given]
 1154: 	    set letters "ABCDEFGHIJ"
 1155: 	    set maxLeaf $gScorer(quest.$questNum.leafs.$num)
 1156: 	    for { set leaf 0 } { $leaf < $maxLeaf } { incr leaf } {
 1157: 		if { [string first [string index $letters $leaf] $correct] != -1 } {
 1158: 		    set ansOn($leaf) 1
 1159: 		} else { 
 1160: 		    set ansOn($leaf) 0 
 1161: 		}
 1162: 	    }
 1163: 	    for { set leaf 0 } { $leaf < $maxLeaf } { incr leaf } {
 1164: 		if { [string first [string index $letters $leaf] $given] != -1 } {
 1165: 		    set stuOn($leaf) 1
 1166: 		} else { 
 1167: 		    set stuOn($leaf) 0 
 1168: 		}
 1169: 	    }
 1170: 	    for { set leaf 0 } { $leaf < $maxLeaf } { incr leaf } {
 1171: 		if { $ansOn($leaf) == $stuOn($leaf) } { incr numRight } 
 1172: 	    }
 1173: 	}
 1174: 	STRING_MATCH {
 1175: #	    scorerMessage $num "The correct answer: $correct, The student's answer: $given"
 1176: 	    set fmt "%-$gScorer(quest.$questNum.leafs.$num)s," 
 1177: 	    append answerStruct(correct) [format $fmt $correct]
 1178: 	    append answerStruct(given) [format $fmt $given]
 1179: 	    set letters "ABCDEFGHIJ"
 1180: 	    set maxLeaf 10
 1181: 	    for { set leaf 0 } { $leaf < $maxLeaf } { incr leaf } {
 1182: 		if { [string first [string index $letters $leaf] $correct] != -1 } {
 1183: 		    set ansOn($leaf) 1
 1184: 		} else { 
 1185: 		    set ansOn($leaf) 0 
 1186: 		}
 1187: 	    }
 1188: 	    for { set leaf 0 } { $leaf < $maxLeaf } { incr leaf } {
 1189: 		if { [string first [string index $letters $leaf] $given] != -1 } {
 1190: 		    set stuOn($leaf) 1
 1191: 		} else { 
 1192: 		    set stuOn($leaf) 0 
 1193: 		}
 1194: 	    }
 1195: 	    for { set leaf 0 } { $leaf < $maxLeaf } { incr leaf } {
 1196: 		if { $ansOn($leaf) == $stuOn($leaf) } { incr numRight } 
 1197: 	    }
 1198: 	    if { $numRight != $maxLeaf } { set numRight 0 }
 1199: 	}
 1200: 	default {
 1201: 	    scorerMessage $num "Unknown question type while grading,"
 1202: 	}
 1203:     }
 1204:     return $numRight
 1205: }
 1206: 
 1207: ###########################################################
 1208: # gradeSet
 1209: ###########################################################
 1210: ###########################################################
 1211: ###########################################################
 1212: proc gradeSet { num answerStructVar questionPID } {
 1213:     global gScorer
 1214:     upvar $answerStructVar answerStruct
 1215:     
 1216:     set numRight 0
 1217:     for { set i 0 } { $i < $answerStruct(maxQuest) } { incr i } {
 1218: 	set correct [lindex $answerStruct(correct.$questionPID) $i]
 1219: 	set given $answerStruct(answer.$i) 
 1220: 	set probRight [gradeQuestion $num $i $correct $given answerStruct]
 1221: 	incr numRight $probRight
 1222: 	append answerStruct($questionPID.numRight) $probRight
 1223:     }
 1224:     set answerStruct($questionPID.correct) $answerStruct(correct)
 1225:     set answerStruct(correct) ""
 1226:     set answerStruct($questionPID.given) $answerStruct(given)
 1227:     set answerStruct(given) ""
 1228:     return $numRight
 1229: }
 1230: 
 1231: 
 1232: ###########################################################
 1233: # getScorerEntry
 1234: ###########################################################
 1235: ###########################################################
 1236: ###########################################################
 1237: proc getScorerEntry { num PID } {
 1238:     global gScorer
 1239:     
 1240:     set fileId $gScorer(out.$num) 
 1241:     seek $fileId 0 start
 1242:     set done 0
 1243:     set found 0
 1244:     set aline ""
 1245:     set offset 0
 1246:     while { ! $done } {
 1247: 	set readamt [gets $fileId aline]
 1248: 	if { [eof $fileId] } { set done 0 ; break}
 1249: 	if { 0 == [ string compare [string toupper [lindex $aline 0]] \
 1250: 			[string toupper $PID] ] } {
 1251: 	    set done 1
 1252: 	    set found 1
 1253: 	} else { 
 1254: 	    #plus one because gets swallows the newline it reads
 1255: 	    set offset [expr $offset + $readamt + 1]	
 1256: 	}
 1257:     }
 1258:     if { ! $found } { set offset -$offset }
 1259:     return $offset
 1260: }
 1261: 
 1262: ###########################################################
 1263: # setScorerEntry
 1264: ###########################################################
 1265: ###########################################################
 1266: ###########################################################
 1267: proc setScorerEntry { num aline offset } {
 1268:     global gScorer
 1269:     
 1270:     set fileId $gScorer(out.$num)
 1271:     seek $fileId [expr abs($offset)] start
 1272:     puts $fileId $aline
 1273: }
 1274: 
 1275: ###########################################################
 1276: # setOutput
 1277: ###########################################################
 1278: ###########################################################
 1279: ###########################################################
 1280: proc setOutput { num answerStructVar} {
 1281:     global gScorer
 1282:     upvar $answerStructVar answerStruct
 1283: 
 1284: #FIXME what if questions PID is empty
 1285:     set questionPID $answerStruct(questionPID)
 1286:     set out [format "%9s %-30s %s %4s %3s %s %s %s" $answerStruct(StudentNumber) \
 1287: 		 $answerStruct(Name) $answerStruct($questionPID.numRight) \
 1288: 		 $answerStruct($questionPID.grade) $answerStruct(Section) \
 1289: 		 $answerStruct($questionPID.given) $questionPID \
 1290: 		 $answerStruct(SerialNumber)]
 1291:     set offset [getScorerEntry $num $answerStruct(StudentNumber)]
 1292:     setScorerEntry $num "$out" $offset
 1293: }
 1294: 
 1295: ###########################################################
 1296: # finishScoring
 1297: ###########################################################
 1298: ###########################################################
 1299: ###########################################################
 1300: proc finishScoring { num answerStructVar} {
 1301:     global gScorer gMult
 1302:     scorerMessage $num "Finishing . . ."
 1303:     #puts $gMult
 1304: #    puts "errors:"
 1305: #    puts "$gScorer(errors.$num)"
 1306:     scorerMessage $num "Finished, Feel free to Update .sb"
 1307:     if { [makeSure "Would you like to update the .sb file?"] == "Yes" } {
 1308: 	scorerToSet $num
 1309:     }
 1310:     trace variable gScorer(quit.$num) w "scorerClose $num 0"
 1311: }
 1312: 
 1313: proc scorerStudentTime { num } {
 1314:     puts [ time "scorerStudent $num" ]
 1315: }
 1316: 
 1317: ###########################################################
 1318: # scorerStudent
 1319: ###########################################################
 1320: ###########################################################
 1321: ###########################################################
 1322: proc scorerStudent { num } {
 1323:     global gScorer
 1324: 
 1325:     if { $gScorer(pause.$num) } {
 1326: 	if { [array names gScorer quit.$num] != "" } { 
 1327: 	    if { ![scorerClose $num] } {
 1328: 		unset gScorer(quit.$num)
 1329: 		set gScorer(pause.$num) 0
 1330: 	    } else {
 1331: 		return
 1332: 	    }
 1333: 	}
 1334: 	if { $gScorer(pause.$num) == 1 } { 
 1335: 	    scorerMessage $num "Pausing. . . " info
 1336: 	    set gScorer(pause.$num) 2
 1337: 	}
 1338: 	after 100 "scorerStudent $num"
 1339: 	return
 1340:     }
 1341: #getanswerline
 1342:     if { [ catch { set answer [ getLine $num ] } ] } {
 1343: 	finishScoring $num answerStruct
 1344: 	return
 1345:     }
 1346:     set gScorer(needToUpdateDB) 1
 1347: #parseanswerline
 1348:     if { [catch {parseLine $num $answer answerStruct} errorMsg ] } {
 1349: 	global errorInfo
 1350: 	displayError "Error parsing line: $errorMsg $errorInfo"
 1351:     } else {
 1352: #parse the set and grades it for any possiblely matching student
 1353: 	if { ! [ catch { set result [handleStudent $num answerStruct]} errorMsg ] } {
 1354: 	    #write entry to outputfile if student was succesfully handled
 1355: 	    if { $result } { setOutput $num answerStruct } 		
 1356: 	} else { #error handling Student
 1357: 	    global errorCode errorInfo
 1358: 	    displayError "An error occured when attempting to grade a student. The error is: $errorMsg"
 1359: 	}
 1360:     }
 1361:     incr gScorer(student.$num)
 1362:     update
 1363:     after idle "scorerStudent $num"
 1364: }
 1365: 
 1366: ###########################################################
 1367: # restartScorer
 1368: ###########################################################
 1369: ###########################################################
 1370: ###########################################################
 1371: proc restartScorer { num } {
 1372:     global gScorer
 1373:     if { ! [info exists gScorer(pause.$num) ] } {
 1374: 	initScorer $num
 1375: 	set gScorer(pause.$num) 0
 1376:     } else {
 1377:     }
 1378:     after idle "scorerStudent $num"
 1379: }
 1380: 
 1381: ###########################################################
 1382: # pauseScorer
 1383: ###########################################################
 1384: ###########################################################
 1385: ###########################################################
 1386: proc pauseScorer { num } {
 1387:     global gScorer
 1388:     set gScorer(pause.$num) 1
 1389: }
 1390: 
 1391: ###########################################################
 1392: # stopScorer
 1393: ###########################################################
 1394: ###########################################################
 1395: ###########################################################
 1396: proc stopScorer { num } {
 1397: }
 1398: 
 1399: ###########################################################
 1400: # unpauseScorer
 1401: ###########################################################
 1402: ###########################################################
 1403: ###########################################################
 1404: proc unpauseScorer { num } {
 1405:     global gScorer
 1406:     set gScorer(pause.$num) 0
 1407: }
 1408: 
 1409: ###########################################################
 1410: ###########################################################
 1411: ###########################################################
 1412: ###########################################################
 1413: proc finalScorer { num method studentNumber numRight } {
 1414:     global gScorer
 1415: 
 1416:     #puts ":$numRight:"
 1417:     set answers ""
 1418:     for { set i 0 } { $i < $gScorer(numQuest.$num) } { incr i } {
 1419: 	switch $gScorer(quest.$i.type.$num) {
 1420: 	    ONE_OUT_OF_10 -
 1421: 	    SINGLE_DIGIT {
 1422: 		append answers [ expr [string index $numRight $i] * \
 1423: 				 $gScorer(quest.$i.points.$num) ]
 1424: 	    }
 1425: 	    GLE -
 1426: 	    TF -
 1427: 	    N_OUT_OF_M {
 1428: 		set right [string index $numRight $i]
 1429: 		set leafs $gScorer(quest.$i.leafs.$num)
 1430: 		set points $gScorer(quest.$i.points.$num)
 1431: 		set unit [expr double($points)/double($leafs)]
 1432: 		if { $unit == 0 } { set unit $points } 
 1433: 		switch $method {
 1434: 		    CAPA {
 1435: 			set score [expr int($points-(2*$unit*($leafs-$right)))]
 1436: 			if { $score < 0 } { set score 0 }
 1437: 		    }
 1438: 		    Lenient {
 1439: 			set score [expr int($points-($unit*($leafs-$right)))]
 1440: 		    }
 1441: 		    Strict {
 1442: 			if { $right == $leafs } { 
 1443: 			    set score $points 
 1444: 			} else { 
 1445: 			    set score 0 
 1446: 			}
 1447: 		    }
 1448: 		    default {
 1449: 			scorerError $num UNKNOWN_GRADING_METHOD $method
 1450: 		    }
 1451: 		}
 1452: 		append answers $score
 1453: 	    }
 1454: 	    STRING_MATCH -
 1455: 	    ASSIGNED {
 1456: 		append answers [string index $numRight $i]
 1457: 	    }
 1458: 	    default {
 1459: 	    }
 1460: 	}
 1461:     }
 1462:     return $answers
 1463: }
 1464: 
 1465: ###########################################################
 1466: # scorerToSet2
 1467: ###########################################################
 1468: ###########################################################
 1469: ###########################################################
 1470: proc scorerToSet2 { num method } {
 1471:     global gScorer gFile
 1472:     destroy .getGradingMethod$num
 1473:     
 1474:     set processed 0
 1475:     set done 0
 1476:     set fileId $gScorer(out.$num)
 1477:     set setId $gScorer(set.$num)
 1478:     seek $fileId 0 start
 1479: 
 1480: #remove the header line
 1481:     gets $fileId aline 
 1482: 
 1483:     scorerMessage $num "Processing. . ."
 1484:     while { ! $done } {
 1485: 	gets $fileId aline
 1486: 	if { [eof $fileId] } {
 1487: 	    set done 1
 1488: 	    break
 1489: 	}
 1490: 	set studentNumber [lindex $aline 0]
 1491: 	incr processed
 1492: 	if { [ expr $processed % 100 ] == 0 } { scorerMessage $num $processed }
 1493: 	update idletasks
 1494: 	set cwd [pwd]
 1495: 	cd $gFile($num)
 1496: 	if { ![file exists [file join records set$setId.sb] ] } {
 1497: 	    if { ![file exists [file join records set$setId.db] ] } {
 1498: 		cd $cwd
 1499: 		scorerMessage $num "set$setId.db does not exist" error
 1500: 		return
 1501: 	    } else {
 1502: 		scorerMessage $num "Copying set$setId.db to set$setId.sb" 
 1503: 		if { [catch {file copy [file join records set$setId.db] \
 1504: 				 [file join records set$setId.sb] }] } {
 1505: 		    cd $cwd
 1506: 		    scorerMessage $num "Unable to create set$setId.sb from set$setId.db, please create it by hand" error
 1507: 		    return
 1508: 		}
 1509: 	    }
 1510: 	}
 1511: 	if { [catch { set offset [ scorer_get_entry $studentNumber $setId ] } errors] } {
 1512: 	    cd $cwd
 1513: 	    scorerMessage $num "Error trying to read set$setId.sb" error
 1514: 	    return
 1515: 	}
 1516: 	cd $cwd
 1517: 	set name [string range $aline 10 39]
 1518: 	set numRight [lindex [string range $aline 40 end] 0]
 1519: 	set entry(answers) [ finalScorer $num $method $studentNumber $numRight ]
 1520: 	set entry(tries) ""
 1521: 	for { set i 0 } { $i < $gScorer(numQuest.$num) } { incr i } {
 1522: 	    append entry(tries) ", 1"
 1523: 	}
 1524: 	set entry(tries) [string range $entry(tries) 1 end]
 1525: 	set cwd [pwd]
 1526: 	cd $gFile($num)
 1527: 	if { [ catch { scorer_set_entry $studentNumber $setId $offset \
 1528: 			   $entry(answers) $entry(tries) } errors ] } {
 1529: 	    cd $cwd
 1530: 	    scorerMessage $num "Error trying to update set$setId.sb" error
 1531: 	    return
 1532: 	}
 1533: 	cd $cwd
 1534:     }
 1535:     scorerMessage $num "Finished updating. . ."
 1536:     update idletasks
 1537: 
 1538:     set gScorer(needToUpdateDB) 0
 1539:     if { [makeSure "Should I copy the updated set$setId.sb to set$setId.db"] == "Yes" } {
 1540: 	if { [file exists [file join $gFile($num) records set$setId.db] ] } {
 1541: 	    if { [catch {file delete [file join $gFile($num) records set$setId.db]}]} {
 1542: 		scorerMessage $num "An error occured while trying to copy. Please do this by hand." error
 1543: 	    }
 1544: 	}
 1545: 	if { [catch {file copy [file join $gFile($num) records set$setId.sb] \
 1546: 			 [file join $gFile($num) records set$setId.db] }] } {
 1547: 	    scorerMessage $num "An error occured while trying to copy. Please do this by hand." error
 1548: 	}
 1549:     }
 1550:     scorerMessage $num "Done"
 1551: }
 1552: 
 1553: ###########################################################
 1554: # scorerToSet
 1555: ###########################################################
 1556: ###########################################################
 1557: ###########################################################
 1558: proc scorerToSet { num } {
 1559:     global gScorer
 1560:     
 1561:     #getGradingMethod
 1562:     set gradeWindow [toplevel .getGradingMethod$num]
 1563:     
 1564:     set messageFrame [frame $gradeWindow.mesg]
 1565:     set capaFrame [frame $gradeWindow.capa]
 1566:     set lenientFrame [frame $gradeWindow.lenient]
 1567:     set strictFrame [frame $gradeWindow.strict]
 1568:     set cancelFrame [frame $gradeWindow.cancel]
 1569:     pack $messageFrame $capaFrame $lenientFrame $strictFrame $cancelFrame \
 1570: 	-side top
 1571: 
 1572:     label $messageFrame.mesg -text "Please Select a Grading Method:" 
 1573:     pack $messageFrame.mesg
 1574: 
 1575:     button $capaFrame.capa -text "CAPA Standard" -command "scorerToSet2 $num CAPA"
 1576: #    button $capaFrame.huh -text "Huh?"
 1577:     pack $capaFrame.capa  -side left
 1578: 
 1579:     button $lenientFrame.lenient -text "Lenient Method" \
 1580: 	-command "scorerToSet2 $num Lenient"
 1581: #    button $lenientFrame.huh -text "Huh?"
 1582:     pack $lenientFrame.lenient  -side left
 1583: 
 1584:     button $strictFrame.strict -text "Strict Method" \
 1585: 	-command "scorerToSet2 $num Strict"
 1586: #    button $strictFrame.huh -text "Huh?"
 1587:     pack $strictFrame.strict -side left
 1588:     
 1589:     button $cancelFrame.cancel -text "Cancel" -command "destroy $gradeWindow"
 1590:     pack $cancelFrame.cancel
 1591:     Centre_Dialog $gradeWindow default
 1592: }
 1593: 
 1594: ###########################################################
 1595: # scorerQuit
 1596: ###########################################################
 1597: ###########################################################
 1598: ###########################################################
 1599: proc scorerQuit { num } {
 1600:     global gScorer
 1601:     set gScorer(pause.$num) 1
 1602:     set gScorer(quit.$num) 1
 1603:     #puts [trace vinfo gScorer(quit.$num)]
 1604:     catch {scorerMessage $num "Quitting. . . " info}
 1605: }
 1606: 
 1607: ###########################################################
 1608: # scorerClose
 1609: ###########################################################
 1610: ###########################################################
 1611: ###########################################################
 1612: proc scorerClose { num {mustClose 0} {dummy ""} {dummy2 ""} {dummy3 ""}} {
 1613:     global gScorer
 1614: 
 1615:     set message "Are you sure you wish to close?"
 1616:     catch {
 1617: 	if { $gScorer(needToUpdateDB) } {
 1618: 	    set message \
 1619: 		"Are you sure you wish to close, you haven't yet updated the .sb file."
 1620: 	}
 1621:     }
 1622:     if { (! $mustClose ) && [makeSure $message ] == "Cancel" } { return 0 }
 1623:     stopScorer $num
 1624:     destroy .beginScorer$num
 1625: #    freeStudentList $num
 1626:     return 1
 1627: }
 1628: 
 1629: ###########################################################
 1630: # loadScorerQuest
 1631: ###########################################################
 1632: ###########################################################
 1633: ###########################################################
 1634: proc loadScorerQuest { num } {
 1635:     global gScorer gFile
 1636:     
 1637:     set filename [file join $gFile($num) records scorer.output.$gScorer(set.$num)]
 1638:     if { [ catch { set fileId [ open $filename "r" ] } ] } {
 1639: 	displayError "The set $gScorer(set.$num) does not yet have an scorer.output file. "
 1640: 	return
 1641:     }
 1642:     set line [gets $fileId ]
 1643:     close $fileId
 1644:     set numQuestions [lindex $line 2]
 1645:     set flags [lindex $line 4]
 1646:     $gScorer(quest.$num) delete 0 end
 1647:     for { set i 0 } { $i < $numQuestions } { incr i } {
 1648: 	switch [string index $flags [expr $i * 3] ] {
 1649: 	    a { set gScorer(questType.$num) ONE_OUT_OF_10 }
 1650: 	    b { set gScorer(questType.$num) GLE }
 1651: 	    c { set gScorer(questType.$num) TF }
 1652: 	    d { set gScorer(questType.$num) ASSIGNED }
 1653: 	    e { set gScorer(questType.$num) N_OUT_OF_M }
 1654: 	    f { set gScorer(questType.$num) SINGLE_DIGIT }
 1655: 	    g { set gScorer(questType.$num) STRING_MATCH }
 1656: 	}
 1657: 	set gScorer(questPoint.$num) [string index $flags [expr $i * 3 + 1] ]
 1658: 	set gScorer(questLeaf.$num) [string index $flags [expr $i * 3 + 2] ]
 1659: 	insertQuest $num end
 1660:     }
 1661: }
 1662: 
 1663: ###########################################################
 1664: # reScore
 1665: ###########################################################
 1666: ###########################################################
 1667: ###########################################################
 1668: proc reScore { file } {
 1669:     global gUniqueNumber gScorer gFile
 1670:     set num [incr gUniqueNumber]
 1671:     if { [catch {set gScorer(out.$num) [open $file "r"]}]} { 
 1672: 	displayError "Unable to open $file"
 1673: 	return
 1674:     }
 1675:     set gScorer(set.$num) [lindex [split $file .] end]
 1676:     set gFile($num) [file dirname [file dirname $file]]
 1677:     set line [gets $gScorer(out.$num) ]
 1678:     set gScorer(numQuest.$num) [lindex $line 2]
 1679:     set flags [lindex $line 4]
 1680:     for { set i 0 } { $i < $gScorer(numQuest.$num) } { incr i } {
 1681: 	switch [string index $flags [expr $i * 3] ] {
 1682: 	    a { set gScorer(quest.$i.type.$num) ONE_OUT_OF_10 }
 1683: 	    b { set gScorer(quest.$i.type.$num) GLE }
 1684: 	    c { set gScorer(quest.$i.type.$num) TF }
 1685: 	    d { set gScorer(quest.$i.type.$num) ASSIGNED }
 1686: 	    e { set gScorer(quest.$i.type.$num) N_OUT_OF_M }
 1687: 	    f { set gScorer(quest.$i.type.$num) SINGLE_DIGIT }
 1688: 	    g { set gScorer(quest.$i.type.$num) STRING_MATCH }
 1689: 	}
 1690: 	set gScorer(quest.$i.points.$num) [string index $flags [expr $i * 3 + 1] ]
 1691: 	set gScorer(quest.$i.leafs.$num) [string index $flags [expr $i * 3 + 2] ]
 1692:     }
 1693: 
 1694:     set reScore [toplevel .reScore$num]
 1695:     wm title $reScore "ReScoring $file"
 1696: 
 1697:     set windowFrame [frame $reScore.windowFrame]
 1698:     set buttonFrame [frame $reScore.buttonFrame]
 1699:     pack $windowFrame $buttonFrame -side bottom 
 1700:     pack configure $windowFrame -expand true -fill both
 1701:     pack configure $buttonFrame -anchor e
 1702: 
 1703:     scrollbar $windowFrame.scroll -orient vertical -command \
 1704: 	"$windowFrame.text yview"
 1705:     set gScorer(status.$num) [text $windowFrame.text -yscrollcommand \
 1706: 				  "$windowFrame.scroll set" -wrap char -height 40]
 1707:     pack $windowFrame.scroll $gScorer(status.$num) -side left -expand 0
 1708:     pack configure $windowFrame.scroll -expand 0 -fill y
 1709:     pack configure $gScorer(status.$num) -expand true -fill both
 1710: 	    
 1711:     button $buttonFrame.ok -text Dismiss -command \
 1712: 		    "destroy $reScore
 1713:                      catch {close $gScorer(out.$num)}"
 1714:     bind $reScore <Destroy> "catch {close $gScorer(out.$num)}"
 1715:     button $buttonFrame.save -text "Save Messages" -command "saveScorerMsg $num"
 1716:     button $buttonFrame.print -text "Print Messages" -command "printScorerMsg $num"
 1717:     pack $buttonFrame.print $buttonFrame.save $buttonFrame.ok -side left
 1718:     
 1719:     Centre_Dialog $reScore default
 1720:     update
 1721:     scorerToSet $num
 1722: }
 1723: 
 1724: #The flags struct is
 1725: # name
 1726: # question to ask
 1727: # yes (1) response
 1728: # no (0) response
 1729: set gScorer(flags) \
 1730: {
 1731:     {
 1732: 	CheckPIN 
 1733: 	{Is there a capaID/CODE on the paper?}
 1734: 	Yes
 1735: 	No
 1736: 	1
 1737:     }
 1738:     {
 1739: 	AnonMode 
 1740: 	{Is this an anonymous Exam?}
 1741: 	Yes
 1742: 	No
 1743: 	0
 1744:     }
 1745:     {
 1746: 	QueryAboutPID 
 1747: 	{When finding multiple PIDs matching a capaID:}
 1748: 	{Ask which to use}
 1749: 	{Pick one with highest score}
 1750: 	0
 1751:     }
 1752: }
 1753: #    { 
 1754: #	SurveyMode 
 1755: #	{What is being scanned?} 
 1756: #	Survey
 1757: #	Exam/Quiz 
 1758: #	0
 1759: #    }  
 1760: #    {
 1761: #	SurveyHeader 
 1762: #	{Does the Survey have a header?}
 1763: #	Yes
 1764: #	No
 1765: #	0
 1766: #    }
 1767: 
 1768: #    {
 1769: #	CheckSpaces
 1770: #	{Should scorer worry about blank questions?}
 1771: #	Yes
 1772: #	No
 1773: #	0
 1774: #    }
 1775: #    { 
 1776: #	CheckMultipleMarks 
 1777: #	{Should scorer worry about multiple marks on single mark questions?}
 1778: #	Yes
 1779: #	No
 1780: #	0
 1781: #    }
 1782: #    {
 1783: #	IdFormat 
 1784: #	{What format is the student number in?}
 1785: #	A<number>
 1786: #	{Social Security}
 1787: #	1
 1788: #    }
 1789: #    {
 1790: #	Form
 1791: #	{Which form size is being used? Select Half Sheet}
 1792: #	{Full sheet}
 1793: #	{Half Sheet}
 1794: #	0
 1795: #    }
 1796: #    {
 1797: #	log
 1798: #	{When encountering errors: Select Query the User}
 1799: #	{Log them}
 1800: #	{Query the user}
 1801: #	1
 1802: #    }
 1803: 
 1804: #Counting from zero, first number is column of start of the field,
 1805: #second number is end of the field. The Question field is an 
 1806: #exception first comes start of question responses then # of
 1807: #responses, and then the number of bubbles per response
 1808: #Full Sheet Specs
 1809: set gScorer(FullSheet.SerialNumber)  {  5  8 }
 1810: set gScorer(FullSheet.LastName)      { 40 49 }
 1811: set gScorer(FullSheet.FirstName)     { 50 54 }
 1812: set gScorer(FullSheet.MiddleInitial) { 55 55 }
 1813: set gScorer(FullSheet.StudentNumber) { 56 64 }
 1814: set gScorer(FullSheet.Section)       { 65 67 }
 1815: set gScorer(FullSheet.CapaID)        { } 
 1816: #No CapaID spot on full sheet
 1817: set gScorer(FullSheet.Question)      { 76 50 10 }
 1818:  
 1819: #Half Sheet Specs
 1820: set gScorer(HalfSheet.SerialNumber)  {  5  8 }
 1821: set gScorer(HalfSheet.LastName)      { 40 49 }
 1822: set gScorer(HalfSheet.FirstName)     { 50 50 }
 1823: set gScorer(HalfSheet.MiddleInitial) { } 
 1824: #No Middle Initial
 1825: set gScorer(HalfSheet.StudentNumber) { 56 64 }
 1826: set gScorer(HalfSheet.Section)       { 65 67 }
 1827: set gScorer(HalfSheet.CapaID)        { 68 73 }
 1828: set gScorer(HalfSheet.Question)      { 76 50 10 }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>