File:  [LON-CAPA] / capa / capa51 / GUITools / grader.tcl
Revision 1.3: download - view: text, annotated - select for diffs
Wed Jan 12 21:00:25 2000 UTC (24 years, 9 months ago) by albertel
Branches: MAIN
CVS tags: HEAD
- typos in the word occur

###########################################################
# grader.tcl - 
# Copyright Guy Albertelli II 1996
###########################################################
set gTclVer 2.0

###########################################################
# createControlWindow
###########################################################
# Creates the menu window 
###########################################################
# Arguments: none
# Returns: nothing
# Globals: gWindowMenu - set to the name of Menu for the windows
#                        menu
###########################################################
proc createControlWindow {} {
    global gWindowMenu gParseMode gParseModeButton gLprCommand gCapaConfig 

    after 500 { dateUpdate }
    after 1000 { cleanWindowList }

    set gCapaConfig(Printer_selected) "0"
    set gCapaConfig(lprOneSided_command) "lpr "
    set gCapaConfig(lprTwoSided_command) ""
    set gCapaConfig(printer_option) ""
    
    wm withdraw .

    set menuFrame [menu .main -tearoff 0 -type tearoff -font 8x13bold \
	    -disabledforeground grey85 ]

    wm title $menuFrame "Grader"

    $menuFrame post 0 0

    wm geometry $menuFrame "+0+20"
    $menuFrame add command -label "Grader" -foreground grey85 -background \
	    black -state disabled 
    $menuFrame add command -label "Info..." -command { createInfoWindow }
    $menuFrame add command -label "Specify Class" -command { specifyClass }
    $menuFrame add command -label "Create Class Report" -command { \
	    createSummaryWindow }
    $menuFrame add command -label "Grade Subjective" -command { gradeSubjective }

#    $menuFrame add cascade -label "File" -menu $menuFrame.file
    $menuFrame add command -label "Excuse Problem" -command { \
	    createExcuseWindow }
    $menuFrame add cascade -label "Windows" -menu $menuFrame.windows
    $menuFrame add cascade -label "Print" -menu $menuFrame.print
    $menuFrame add command -label "Remap..." -command { createRemapWindow }
    $menuFrame add command -label "Quit" -command { quit }

#    set file  [menu $menuFrame.file -tearoff 1 -font 8x13bold ]
    set windows [menu $menuFrame.windows -tearoff 1 -font 8x13bold]
    set print    [menu $menuFrame.print -tearoff 1  -font 8x13bold]
    set gWindowMenu $windows
    
    $print add command -label "Set Summary" -command { printSetSummary }
    $print add command -label "Term Summary" -command { printTermSummary }

    set gParseMode 2
    set gParseModeButton "Both, Questions Answers"    
}

###########################################################
# createInfoWindow
###########################################################
# creates the Information window
###########################################################
# Arguments: None
# Returns: Nothing
# Globals: gDate - the variable containg the current date 
#          gWindowMenu - used to register the new window in the
#                        windows menu
#          gVer - Stores the current version of Grader (set in 
#                 C init code
###########################################################
proc createInfoWindow {} {
    global gDate gWindowMenu gVer gTclVer gCmd gCompileDate

    if { [winfo exists .about] } {
	capaRaise .about
	return 
    }

    set about [toplevel .about]

    $gWindowMenu add command -label "About" -command "capaRaise $about"

    wm title $about "About" 
    
    label $about.l1 -font 12x24 -text "Grader $gVer" -pady 20
    label $about.l4 -font 8x13 -text "Grader.tcl Version $gTclVer" -pady 20
    label $about.l6  -font 8x13 -text "$gCompileDate" 
    message $about.l2 -font 8x13 -text "Code by: Y. Tsai, G. Albertelli II Copyright Michigan State University Board of Trustees, 1992-1999, No Unauthorized Commercial Use" \
       -pady 20 -aspect 300
    label $about.l3 -font 8x13 -textvariable gDate 
    label $about.l5  -font 8x13 -textvariable gCmd

    button $about.close -text "Close" -command "destroy $about
                                                removeWindowEntry About"
    
    pack $about.l1 $about.l4 $about.l6 $about.l2 $about.l3 $about.l5 \
	    $about.close -side top 

    Centre_Dialog $about default
}

###########################################################
# quit
###########################################################
# called when the quit option is selected on the menu, unmaps
# all keys.
###########################################################
# Arguments: None
# Returns: Nothing
# Globals: None
###########################################################
proc quit {} {
    if { [makeSure "Are you sure you wish to quit?"] == "Cancel" } {
	return 
    }
    
    if { [winfo exists .gradesubjective] } { subjDone }
    catch { rm -f [file join / tmp gkc[pid]]}
    catch { rm -f [file join / tmp g[pid]]}

    unmapAllKeys
    exit
}

###########################################################
# createExcuseWindow
###########################################################
# runs capa_excuse for a set and section, creates a window to
# get the information from, requires that the user has already
# selected a class.
###########################################################
# Arguments: None
# Returns: Nothing
# Globals: gPrompt - used to detect when to take the modal dialog away
#          gSetLoad - global var containg the current set being graded
#          gSectionLoad - global var containg the current section
#                         being graded
#          gExcuseSet - Contains the number of the set to be excused
#          gExcuseProblem - number of the problem to be excused
#          gExcuseSection - Section number to excuse the problem for
#          gExcuseWho - contains either : Section or All, and is
#                       whether to excuse an entire class or a specific
#                       section
###########################################################
proc createExcuseWindow { } {
    global gPrompt gSetLoad gSectionLoad gExcuseSet gExcuseProblem \
	    gExcuseSection gExcuseWho
    
    if {![winfo exists .grader]} {
	displayError "You must first specify a class"
	return 
    }

    if { $gSetLoad == "" } {
	set gExcuseSet 1
    } else {
	set gExcuseSet $gSetLoad
    }

    if { $gSectionLoad == "" } {
	set gExcuseSection 1
    } else {
	set gExcuseSection $gSectionLoad
    }

    set excuse [toplevel .excuse -borderwidth 10]

    set whichFrame [frame $excuse.whichFrame -borderwidth 4 -relief groove]
    set whoFrame [frame $excuse.whoFrame -borderwidth 10]
    set buttonFrame [frame $excuse.buttonFrame]
    pack $whichFrame $whoFrame $buttonFrame -side top -anchor w

    set setFrame [frame $whichFrame.setFrame]
    set problemFrame [frame $whichFrame.problemFrame]
    pack $setFrame $problemFrame -side top -anchor e

    label $setFrame.label -text Set
    entry $setFrame.entry -textvariable gExcuseSet -width 3
    pack $setFrame.label $setFrame.entry -side left

    set gExcuseProblem 1
    label $problemFrame.label -text "Problem Number"
    entry $problemFrame.entry -textvariable gExcuseProblem -width 3
    pack $problemFrame.label $problemFrame.entry -side left

    set sectionFrame [frame $whoFrame.sectionFrame]
    set allFrame [frame $whoFrame.allFrame]
    pack $sectionFrame $allFrame -side top -anchor w

    set gExcuseWho Section
    radiobutton $sectionFrame.radio -text "For students in section:" \
	    -variable gExcuseWho -value Section    
    entry $sectionFrame.entry -textvariable gExcuseSection -width 3
    pack $sectionFrame.radio $sectionFrame.entry -side left

    radiobutton $allFrame.radio -text "For all students in the class." \
	    -variable gExcuseWho -value All
    pack $allFrame.radio

    set gPrompt(result) ""
    button $buttonFrame.excuse -text Excuse -command { set gPrompt(yes) 1 } \
	    -underline 0
    button $buttonFrame.cancel -text Cancel -command { set gPrompt(yes) 0 } \
	    -underline 0
    pack $buttonFrame.excuse $buttonFrame.cancel -side left
    
    bind $excuse <Alt-Key> break
    
    Centre_Dialog $excuse default
    update
    
    focus $excuse
    raise $excuse
    capaGrab $excuse
    vwait gPrompt(yes)
    capaGrab release $excuse
    destroy $excuse
    if {$gPrompt(yes)} {
	switch $gExcuseWho {
	    All
	    {
		capaExcuse $gExcuseSet $gExcuseProblem 0
	    }
	    Section
	    {
		capaExcuse $gExcuseSet $gExcuseProblem $gExcuseSection
	    }
	}
	loadScores
    } else {
	return
    }
}    

###########################################################
# createSummaryWindow
###########################################################
# creates a dialog to craft a summary report with
###########################################################
# Arguments: None
# Returns: Nothing
# Globals: gWindowMenu - name of the window menu widget, used to
#                        register the dialog box
#          gSetLoad - current set being graded
#          gSectionLoad - current section being graded
#          gSummaryFile - filename to save report to
#          gSummary - array with fields
#              (section) - section to create the summary for
#              (set) - set to creat the summary for
#              (who) - two possible values: section (create a section
#                       summary), all (create a class summary)
#              (which) - 2 possible values: specific (summary report
#                        for a specific set), upto (summary report upto
#                        and including a specific set)
#              (first) - first field to sort by, four values:name
#                        (student name), number (student number), 
#                        section (section), grade (grade on the sets)
#              (second) - second field to sort by, same four values as
#                         above
#              (filename) - either default, grader picks it or specified,
#                           user specified a name to be found in gSummaryFile
###########################################################
proc createSummaryWindow {} {
    global gWindowMenu gSetLoad gSectionLoad gSummary gSummaryFile
    
    if { [winfo exists .summary] } {
	raise .summary
	return
    }

    if {![winfo exists .grader]} {
	displayError "You must first specify a class"
	return 
    }

    if { $gSetLoad == "" } {
	set gSummary(set) 1
    } else {
	set gSummary(set) $gSetLoad
    }

    if { $gSectionLoad == "" } {
	set gSummary(section) 1
    } else {
	set gSummary(section) $gSectionLoad
    }

    set summary [toplevel .summary]
    $gWindowMenu add command -label "Summary" -command "capaRaise $summary"

    set whoFrame [frame $summary.whoFrame -borderwidth 4 -relief groove]
    set whichFrame [frame $summary.whichFrame -borderwidth 4 -relief groove]
    set sortFrame [frame $summary.sortFrame]
    set file2Frame [frame $summary.file2Frame]
    set buttonFrame [frame $summary.buttonFrame]
    pack $whoFrame $whichFrame $sortFrame $file2Frame $buttonFrame -side top
    pack configure $whoFrame $whichFrame -padx 10 -pady 10

    set sectionFrame [frame $whoFrame.section]
    set allFrame [frame $whoFrame.all]
    pack $sectionFrame $allFrame -side top

    set gSummary(who) section

    radiobutton $sectionFrame.section -text \
	    "For students in default section:" -variable gSummary(who) \
	    -value section 
    entry $sectionFrame.entry -textvariable gSummary(section) -width 3 
    pack $sectionFrame.section $sectionFrame.entry -side left

    radiobutton $allFrame.all -text "For all students in the class" \
	    -variable gSummary(who) -value all 
    pack $allFrame.all

    set sectionFrame [frame $whichFrame.section]
    set allFrame [frame $whichFrame.all]
    pack $sectionFrame $allFrame -side top

    set gSummary(which) specific

    radiobutton $sectionFrame.section -text "For set:" \
	    -variable gSummary(which) -value specific 
    entry $sectionFrame.entry -textvariable gSummary(set) -width 3 
    pack $sectionFrame.section $sectionFrame.entry -side left

    radiobutton $allFrame.all -text "For all sets up to:" -variable \
	    gSummary(which) -value upto 
    entry $allFrame.entry -textvariable gSummary(set) -width 3 
    pack $allFrame.all $allFrame.entry -side left

    set firstFrame [frame $sortFrame.firstFrame -borderwidth 4 -relief groove]
    set secondFrame [frame $sortFrame.secondFrame -borderwidth 4 \
	    -relief groove]
    pack $firstFrame $secondFrame -side left

    set gSummary(first) name

    label $firstFrame.label -text "Sorting Order - Primary"
    radiobutton $firstFrame.name -text "Student Name" -variable \
	    gSummary(first) -value name
    radiobutton $firstFrame.number -text "Student Number" -variable \
	    gSummary(first) -value number
    radiobutton $firstFrame.section -text "Section" -variable \
	    gSummary(first) -value section
    radiobutton $firstFrame.grade -text "Grade" -variable gSummary(first) \
	    -value grade
    pack $firstFrame.label $firstFrame.name $firstFrame.number \
	    $firstFrame.section $firstFrame.grade -side top -anchor w

    set gSummary(second) number

    label $secondFrame.label -text "Sorting Order - Secondary"
    radiobutton $secondFrame.name -text "Student Name" -variable \
	    gSummary(second) -value name
    radiobutton $secondFrame.number -text "Student Number" -variable \
	    gSummary(second) -value number
    radiobutton $secondFrame.section -text "Section" -variable \
	    gSummary(second) -value section
    radiobutton $secondFrame.grade -text "Grade" -variable gSummary(second) \
	    -value grade
    pack $secondFrame.label $secondFrame.name $secondFrame.number \
	    $secondFrame.section $secondFrame.grade -side top -anchor w

    set defaultFrame [frame $file2Frame.defaultFrame]
    set fileFrame [frame $file2Frame.fileFrame]
    pack $defaultFrame $fileFrame -side top

    if {[catch {set gSummary(filename)}]} { set gSummary(filename) default }

    radiobutton $defaultFrame.default -text "Grader Chooses File Name" \
	-variable gSummary(filename) -value default
    pack $defaultFrame.default

    radiobutton $fileFrame.label -text "Specified Output File:" \
	-variable gSummary(filename) -value specified
    set entryFrame [frame $fileFrame.entryFrame]
    button $fileFrame.select -text "Select File" \
	    -command "selectOutputFile"
    pack $fileFrame.label $entryFrame $fileFrame.select -side left
    entry $entryFrame.entry -textvariable gSummaryFile \
	-xscrollcommand "$entryFrame.scroll set"
    scrollbar $entryFrame.scroll -orient h -command \
	    "$entryFrame.entry xview"
    pack $entryFrame.entry $entryFrame.scroll
    pack configure $entryFrame.scroll -fill x

    button $buttonFrame.create -text "Create" -command \
	    "removeWindowEntry Summary
             destroy $summary
             createSummaryReport"
    button $buttonFrame.cancel -text "Cancel" -command \
	    "removeWindowEntry Summary
             destroy $summary"
    pack $buttonFrame.create $buttonFrame.cancel -side left

    Centre_Dialog $summary default
}

###########################################################
# selectOutputFile
###########################################################
###########################################################
###########################################################
proc selectOutputFile {} {
    global gSummaryFile gSummary
    set gSummary(filename) specified
    if { "" != [ set temp [tk_getSaveFile] ] } {set gSummaryFile $temp}
}    

###########################################################
# createSummaryReport
###########################################################
# creates the summary report
###########################################################
# Argumnets: None
# Returns: Nothing
# Globals: gSummary - the report generation information is in here
#          gClassDir - the directory the class is in
# Files: gClassDir/ClassSet.rpt - summary report created if for the
#                                 entire class (created)
#       gClassDir/SecSet.rpt - summarry report created if for only a
#                              section (created)
###########################################################
proc createSummaryReport {} {
    global gSummary gClassDir gUniqueNumber gSummaryFile

    displayStatus "Opening File" both

    switch $gSummary(who) {
	all
	{
	    set file [file join $gClassDir ClassSet$gSummary(set).rpt ]
	}
	section
	{
	    set file [file join $gClassDir \
		    Sec$gSummary(section)Set$gSummary(set).rpt ]
	}
	default
	{
	    displayError "An error has occurred while creating a summary \
		    report $gSummary(section)"
	    return
	}
    }

    if { $gSummary(filename) == "specified" } { set file $gSummaryFile }
    if { $file == "" } { 
	removeStatus
	displayError "Must specify a valid filename"
	return
    }
    updateStatusMessage "Creating Summary"

    set error [ catch {createSummary $file} ]

    removeStatus

    if {!$error && "Yes" == [makeSure "Created summary file $file, would you like to see it?"]} {
	set fileId [open $file r]
	set num [incr gUniqueNumber] 
	set num2 [incr gUniqueNumber] 
	winputs $num [read $fileId]
	winoutput $num2 $num {}
    }
}

###########################################################
# specifyClass
###########################################################
# runs tk_getOpenFile and creates the class window if a directory is chosen
###########################################################
# Arguments: None
# Returns: Nothing
# Globals: gClassDir - remembers the directory the class is in
###########################################################
proc specifyClass {} {
    global gClassDir

    if { [winfo exists .grader] } { return }
    set var [tk_getOpenFile -title "Please select a capa.config file" -filetypes \
		 { { {Capa Config} {capa.config} } }]

    if { $var != "" } {
	set gClassDir [file dirname $var]
	cd $gClassDir
    } else {
	return
    }
    
    createClassWindow
}

###########################################################
# changeClass
###########################################################
# called when the change class button is pressed, if another class
# is chosen the class window is updated
###########################################################
# Arguments: None
# Returns: Nothing
# Globals: gClassDir - remembers the directory the class is in
#          gClass - just the name of the directory, and therefore 
#                   the class
#          gLoaded - reset to zero since we are unloading the class
###########################################################
proc changeClass {} {
    global gClassDir gClass gLoaded

    set var [tk_getOpenFile -title "Please select a capa.config file" -filetypes \
		 { { {Capa Config} {capa.config} } }]    

    if { $var != "" } {
	removeWindowEntry $gClassDir
	set gClassDir [file dirname $var]
	cd $gClassDir
	set gClass  [file tail $gClassDir]
    } else {
	return
    }
    
    set gLoaded 0
    clearClassWindow
    parseCapaConfig
}

###########################################################
# createClassWindow
###########################################################
# creates the rather complicated class window
###########################################################
# Arguments: None
# Returns: Nothing
# Globals: gClassDir - remembers the directory the class is in
#          gWindowMenu - the name of the window menu widget
#          gOpenDate - the label linked var the date the set opens is in
#          gOpenTime - the label linked var the time the set opens is in
#          gDueDate - the label linked var the due date for the set is in
#          gDueTime - the label linked var the due time for the set is in
#          gAnswerDate - the label linked var the date the set answer
#                        open date is in
#          gAnswerTime - the label linked var the time the set answer
#                        open time is in
#          gSectionLoad - the current section being graded
#          gSetLoad - the current set being graded
#          gFindNumber - linked var that stores the string to search
#                        through student numbers for
#          gFindName - linked var that stores the string to search
#                      through student names for
#          gButtonFrame - stores the widget name of the button frame, so 
#                         the buttons' state can be changed elsewhere
#          gNameFrame - stores the widget name of the name entry frame, so 
#                       the entry widget's state can be changed elsewhere
#          gNumberFrame - stores the widget name of the number entry 
#                         frame, so the entry widget' state can be 
#                         changed elsewhere
#          gStudentList - the widget name of the listbox containing the 
#                         list of students
#          gClass - the name of the class currently being graded
#          gLoaded - keeps track of whether a class has been loaded yet
#                    set to zero here
###########################################################
proc createClassWindow {} {
    global gClassDir gWindowMenu gOpenDate gOpenTime gDueDate gDueTime \
	    gAnswerDate gAnswerTime gSectionLoad gSetLoad gFindNumber \
	    gFindName gButtonFrame gNameFrame gNumberFrame gStudentList \
	    gClass gLoaded

    set gLoaded 0
    
    set grader [toplevel .grader]
    $gWindowMenu add command -label "$gClassDir" -command "capaRaise $grader"

    set labelFrame [frame $grader.labelFrame]
    set dataFrame [frame $grader.dataFrame]
    set columnFrame [frame $grader.columnFrame]
    set infoFrame [frame $grader.infoFrame]
    pack $labelFrame $dataFrame $columnFrame $infoFrame -side top -anchor w
    pack configure $infoFrame -expand 1 -fill both

    set gClass [file tail $gClassDir] 
    label $labelFrame.label -background black -foreground grey85 \
	    -textvariable gClass -width 51
    button $labelFrame.button -text "Change Class" -command { changeClass }
    pack $labelFrame.label $labelFrame.button -side left

    set dateFrame [frame $dataFrame.date -relief sunken -borderwidth 2]
    set actionsFrame [frame $dataFrame.actions ]
    pack $dateFrame $actionsFrame -side left

    set openDateFrame [frame $dateFrame.openDate]
    set openTimeFrame [frame $dateFrame.openTime]
    set dueDateFrame [frame $dateFrame.dueDate]
    set dueTimeFrame [frame $dateFrame.dueTime]
    set answerDateFrame [frame $dateFrame.answerDate]
    set answerTimeFrame [frame $dateFrame.answerTime]
    pack $openDateFrame $openTimeFrame $dueDateFrame $dueTimeFrame \
	    $answerDateFrame $answerTimeFrame -side top

    label $openDateFrame.text -text "Open Date:" -width 13
    label $openDateFrame.date -textvariable gOpenDate -width 10 -relief sunken \
	    -background white 
    pack $openDateFrame.text $openDateFrame.date -side left

    label $openTimeFrame.text -text "Open Time:" -width 13
    label $openTimeFrame.time -textvariable gOpenTime -width 10 -relief sunken \
	    -background white 
    pack $openTimeFrame.text $openTimeFrame.time -side left

    label $dueDateFrame.text -text "Due Date:" -width 13
    label $dueDateFrame.date -textvariable gDueDate -width 10 -relief sunken \
	    -background white 
    pack $dueDateFrame.text $dueDateFrame.date -side left

    label $dueTimeFrame.text -text "Due Time:" -width 13
    label $dueTimeFrame.time -textvariable gDueTime -width 10 -relief sunken \
	    -background white 
    pack $dueTimeFrame.text $dueTimeFrame.time -side left

    label $answerDateFrame.text -text "Answer Date:" -width 13
    label $answerDateFrame.date -textvariable gAnswerDate -width 10 -relief \
	    sunken -background white 
    pack $answerDateFrame.text $answerDateFrame.date -side left

    label $answerTimeFrame.text -text "Answer Time:" -width 13
    label $answerTimeFrame.time -textvariable gAnswerTime -width 10 -relief \
	    sunken -background white 
    pack $answerTimeFrame.text $answerTimeFrame.time -side left

    set loadFrame [frame $actionsFrame.load]
    set findFrame [frame $actionsFrame.find]
    set buttonFrame [frame $actionsFrame.buttons]
    set gButtonFrame $buttonFrame
    pack $loadFrame $findFrame $buttonFrame -side top
    pack configure $loadFrame -anchor e

    set sectionFrame [frame $loadFrame.section]
    set setFrame [frame $loadFrame.set]
    pack $sectionFrame $setFrame -side top -anchor w

    label $sectionFrame.label -text "    Section:"
    entry $sectionFrame.entry -textvariable gSectionLoad -width 3
    pack $sectionFrame.label $sectionFrame.entry -side left

    label $setFrame.label -text     "Problem Set:"
    entry $setFrame.entry -textvariable gSetLoad -width 3
    bind $setFrame.entry <KeyPress-Return> loadScores
    button $setFrame.button -text "Load Scores" -command loadScores
    pack $setFrame.label $setFrame.entry $setFrame.button -side left
    
    set nameFrame [frame $findFrame.name]
    set gNameFrame $nameFrame
    set numberFrame [frame $findFrame.number]
    set gNumberFrame $numberFrame
    pack $nameFrame $numberFrame -side top

    entry $nameFrame.name -textvariable gFindName
    button $nameFrame.button -text   "Find By Name         " -command findByName
    bind $nameFrame.name <KeyPress-Return> findByName
    pack $nameFrame.name $nameFrame.button -side left

    entry $numberFrame.name -textvariable gFindNumber
    button $numberFrame.button -text "Find By StudentNumber" -command findByNumber
    bind $numberFrame.name <KeyPress-Return> findByNumber
    pack $numberFrame.name $numberFrame.button -side left

    button $buttonFrame.report -text "Student Report" -command studentReport \
	    -state disabled
    button $buttonFrame.grading -text "Grading" -command createGradingWindow \
	    -state disabled
    pack $buttonFrame.report $buttonFrame.grading  -side left

    label $columnFrame.space -text "  "
    label $columnFrame.name -text "Student Name" -width 30
    label $columnFrame.number -text "Number" -width 11
    message $columnFrame.score -text "Current Set Score" -aspect 250
    message $columnFrame.pin -text "Current Pin" -aspect 200
    pack $columnFrame.space $columnFrame.name $columnFrame.number \
	    $columnFrame.score $columnFrame.pin -side left

    scrollbar $infoFrame.scroll -orient vertical -command \
	    "$infoFrame.listbox yview"
    set gStudentList [listbox $infoFrame.listbox -yscrollcommand \
	    "$infoFrame.scroll set" -height 30]
    pack $infoFrame.scroll $infoFrame.listbox -side left
    pack configure $infoFrame.scroll -expand false -fill y
    pack configure $infoFrame.listbox -expand true -fill both

    Centre_Dialog $grader default
    parseCapaConfig
}

###########################################################
# clearClassWindow
###########################################################
# empties the class window of all data
###########################################################
# Arguments: none
# Returns: Nothing
# Globals: gClassDir - remembers the directory the class is in
#          gWindowMenu - the name of the window menu widget
#          gOpenDate - the label linked var the date the set opens is in
#          gOpenTime - the label linked var the time the set opens is in
#          gDueDate - the label linked var the due date for the set is in
#          gDueTime - the label linked var the due time for the set is in
#          gAnswerDate - the label linked var the date the set answer
#                        open date is in
#          gAnswerTime - the label linked var the time the set answer
#                        open time is in
#          gSectionLoad - the current section being graded
#          gSetLoad - the current set being graded
#          gStudentList - the widget name of the listbox containing the 
#                         list of students
#          gClass - the name of the class currently being graded
###########################################################
proc clearClassWindow {} {
    global gWindowMenu gOpenDate gOpenTime gDueDate gDueTime gAnswerDate \
	    gAnswerTime gStudentList gSectionLoad gSetLoad gClassDir

    $gWindowMenu add command -label "$gClassDir" -command "capaRaise .grader"

    set gOpenDate ""
    set gOpenTime ""
    set gDueDate ""
    set gDueTime ""
    set gAnswerDate ""
    set gAnswerTime ""
    set gSectionLoad ""
    set gSetLoad ""

    $gStudentList delete 0 end
}

###########################################################
# loadScores
###########################################################
# load in a new set of scores
###########################################################
# Arguments: None
# Returns: Nothing
# Globals: gSectionLoad - the current section being graded
#          gSetLoad - the current set being graded
#          gButtonFrame - stores the widget name of the button frame, so 
#                         the buttons' state can be changed elsewhere
#          gNameFrame - stores the widget name of the name entry frame, so 
#                       the entry widget's state can be changed elsewhere
#          gNumberFrame - stores the widget name of the number entry 
#                         frame, so the entry widget' state can be 
#                         changed elsewhere
#          gStudentList - the widget name of the listbox containing the 
#                         list of students
#          gLoaded - 1 if a section has been loaded
###########################################################
proc loadScores {} {
    global gNumberFrame gNameFrame gButtonFrame gSectionLoad gSetLoad \
	    gStudentList gLoaded

    $gStudentList delete 0 end

    if { $gSectionLoad == "" } {
	displayError "The Section field must be completed before \
		continuing."
	return
    } elseif { $gSetLoad == "" } {
	displayError "The Set field must be completed before \
		continuing."
	return
    }    

    set result [getHeader]
    switch -- $result {
	0 { displayError "The Set and Section selected do not appear to exist"; return }
	-1 { #displayMessage "No date information is available for this set" }
	1 { #break } 
    }

    $gButtonFrame.report configure -state normal
    $gButtonFrame.grading configure -state normal

##    $gButtonFrame.log configure -state normal

    getStudents gStudentList

    set gLoaded 1
}

###########################################################
# findByName
###########################################################
# preforms a search for a student by name, findSection returns
# the section the student is in, then the correct element in the
# Student ListBox is highlighted.
###########################################################
# Arguments: None
# Returns: Nothing
# Globals: gSectionLoad - the current section being graded
#          gFindName - linked var that stores the string to search
#                      through student names for
#          gStudentList - the widget name of the listbox containing the 
#                         list of students
#          gLoaded - keeps track of whther scores have been loaded yet
###########################################################
proc findByName {} {
    global gFindName gFindNumber gStudentList gSectionLoad gLoaded

    fillInStudent gFindName gFindNumber 1
    if { $gFindNumber == "" } { return }
    set section [findSection name $gFindName]

    if { $section == "0" } { 
	displayError "Name not found in classl file"
	return 
    }

    if { !(($gSectionLoad == $section) && $gLoaded) } {
	set gSectionLoad $section
	loadScores
    }

    set size [$gStudentList size]
    set search [string tolower $gFindName]
    while { $size != 0 } {
	incr size -1
	set tempString [string tolower [$gStudentList get $size]]
	switch -- [string first $search $tempString] {
	    0
	    { 
		$gStudentList selection set $size 
		$gStudentList activate $size 
		$gStudentList see $size
	    }
	}
    }
}

###########################################################
# studentReport
###########################################################
# creates a window containg a report for the current student
###########################################################
# Arguments: None
# Returns: Nothing
# Globals: gSectionLoad - the current section being graded
#          gStudentList - the widget name of the listbox containing the 
#                         list of students
#          gWindoMenu - the name of the window menu widget
###########################################################
proc studentReport {} {
    global gStudentList gSectionLoad gWindowMenu

    set string [$gStudentList get active]

    set studentNumber [string range $string 31 39]
    
    set text [getReportInfo $studentNumber]

    if {![winfo exists .a$studentNumber]} {
	set report [toplevel .a$studentNumber]
	$gWindowMenu add command -label "$studentNumber" -command \
		"capaRaise $report"	
	set labelFrame [frame $report.labelFrame]
	set textFrame [frame $report.textFrame]
	set buttonFrame [frame $report.buttonFrame]
	pack $buttonFrame $labelFrame $textFrame -side top
	pack configure $buttonFrame -anchor e

	label $labelFrame.namel -text "Student Name: "
	label $labelFrame.namet -text [string range $string 0 30]
	label $labelFrame.numberl -text "Number: "
	label $labelFrame.numbert -text [string range $string 31 39]
	label $labelFrame.sectionl -text "Section: "
	label $labelFrame.sectiont -text $gSectionLoad
	pack $labelFrame.namel $labelFrame.namet $labelFrame.numberl \
		$labelFrame.numbert $labelFrame.sectionl $labelFrame.sectiont \
		-side left
	
	scrollbar $textFrame.scrollbar -orient vertical -command \
		"$textFrame.text yview"
	text $textFrame.text -yscrollcommand "$textFrame.scrollbar set" \
		-height 30 -width 80
	pack $textFrame.scrollbar $textFrame.text -side left
	pack configure $textFrame.scrollbar -expand false -fill y
	pack configure $textFrame.text -expand true -fill both
	
	button $buttonFrame.close -text "Close" -command \
		"destroy $report
	         removeWindowEntry $studentNumber"
	pack $buttonFrame.close
	Centre_Dialog $report default
    } else {
	.a$studentNumber.textFrame.text delete 0.0 end 
    }

    .a$studentNumber.textFrame.text insert end $text
    .a$studentNumber.textFrame.text configure -state disabled
    
}

###########################################################
# findByNumber
###########################################################
# finds a student based on a complete student number, once again
# findSection finds the correct section and then it searches through the
# list box looking for the correct student
###########################################################
# Arguments: None
# Returns: Nothing
# Globals: gSectionLoad - the current section being graded
#          gFindNumber - linked var that stores the string to search
#                        through student numbers for
#          gStudentList - the widget name of the listbox containing the 
#                         list of students
#          gLoaded - whether or not the data for the set/section has
#                    actually been loaded
###########################################################
proc findByNumber {} {
    global gFindName gFindNumber gStudentList gSectionLoad gLoaded

    fillInStudent gFindName gFindNumber 0
    if { $gFindNumber == "" } { return }
    set section [findSection number $gFindNumber]

    if { $section == "0" } { 
	displayError "Name not found in classl file"
	return 
    }

    if { ! (($gSectionLoad == $section ) && $gLoaded) } {
	set gSectionLoad $section
	loadScores
    }

    set size [$gStudentList size]
    set search [string tolower $gFindNumber]
    while { $size != 0 } {
	incr size -1
	set tempString [string range [string tolower \
		[$gStudentList get $size]] 31 39]
	switch -- [string first $search $tempString] {
	    0
	    { 
		$gStudentList selection set $size 
		$gStudentList activate $size 
		$gStudentList see $size
	    }
	}
    }
}

###########################################################
# printBody
###########################################################
# sends the file quiztemp.ps to the printer through lpr using
# the option foud in gLprCommand
###########################################################
# Arguments: none
# Returns: Nothing
# Files: /tmp/g[pid] - file containg info to print (removed)
###########################################################
proc printBody { lprCommand } {

    set errorMsg ""
    
    set error [catch {set returnMessage [eval "exec $lprCommand"] } errorMsg ]
    
    exec /bin/rm -f /tmp/g[pid]

    if { $error == 1 } {
        displayError "When attempting to print an error occurred : $errorMsg"
	return 1
    } else {
	displayMessage "Print job sent to the printer.\n $returnMessage"
    }
    
    return 0
}

###########################################################
# printSetSummary
###########################################################
# prints a set summary for the currently grading set and section
###########################################################
# Arguments: None
# Returns: Nothing
# Globals: gSetLoad - currently being graded set
#          gWindowMenu - the widget name of the window menu
#          gSectionLoad - currently being graded section
# Files: /tmp/g[pid] - file containg info to print (created)
###########################################################
proc printSetSummary {} {
    global gSetLoad gWindowMenu gSectionLoad 

    if { $gSetLoad == "" } { 
	displayError "Please enter a Set number."
	return
    }

    if { $gSectionLoad == "" } { 
	displayError "Please enter a Section number."
	return
    }

    set lprCommand [getLprCommand [file join / tmp g[pid] ] ]
    if { $lprCommand == "" } {
	displayError "Print command was empty, unable to print."
	return 1
    }
    if {$lprCommand == "Cancel" } {
	return 1
    }

    getSetSummary [file join / tmp g[pid]]

    printBody  $lprCommand
}

###########################################################
# printTermSummary
###########################################################
# creates a termsummary file and send it to the printer
###########################################################
# Arguments: None
# Returns: Nothing
# Globals: gSetLoad - currently being graded set
#          gWindowMenu - the widget name of the window menu
#          gSectionLoad - currently being graded section
# Files: /tmp/g[pid] - file containg info to print (created)
###########################################################
proc printTermSummary {} {
    global gSetLoad gWindowMenu gSectionLoad 

    if { $gSetLoad == "" } { 
	displayError "Please enter a Set number."
	return
    }

    if { $gSectionLoad == "" } { 
	displayError "Please enter a Section number."
	return
    }

    set lprCommand [getLprCommand [file join / tmp g[pid] ] ]
    if { $lprCommand == "" } {
	displayError "Print command was empty, unable to print."
	return 1
    }
    if {$lprCommand == "Cancel" } {
	return 1
    }

    displayStatus "Getting Term Summary" bar

    getTermSummary [file join / tmp g[pid] ]

    removeStatus 

    printBody $lprCommand
}

###########################################################
# createGradingWindow
###########################################################
# create the window in which the user can change the grades in
###########################################################
# Arguments: None
# Returns: Nothing
# Globals: gStudentList - the widget name of the list box the list
#                         of students is in.
#          gSectionLoad - currently being graded section
#          gWindowMenu - widget name of the window menu
#          gProblemText - stores the results of the parse of the set
#          gParseMode - stores either 1 (Both, Questions Answers) or
#                       2 (Answer Only)
#          gSetLoad - currently being graded set
#          gGrading - an array containg
#               (name) - Name of the student
#               (number) - student number 
#          gGradeCanvas - widget name of the canvas used to contain all
#                         of the radiobuttons when grading
#          gAnswer - an array containg the score for the student
#                ($i) - i contains the current problem number and the entry
#                       has one of Y, N, E, or -
#                (max$i) - i is the problem number, these entries exist only
#                          for handgraded questions, and is the maximum
#                          score for that question
#          gQuestionType - stores whether a quetion is handgraded or not
#                ($i) - i contains the current problem number and the entry
#                       has one of handGrade, or autoGrade
#          gParseModeButton - the text that will be displayed on
#                             the button that switches parse modes, 
#                             either "Answer Only" or 
#                             "Both, Questions Answers"
###########################################################
proc createGradingWindow {} {
    global gStudentList gSectionLoad gWindowMenu gProblemText gParseMode \
	    gSetLoad gGrading gGradeCanvas gAnswer gQuestionType \
	    gParseModeButton

    if { [winfo exists .grading] } { 
	capaRaise .grading
	return 
    }
    catch {unset gAnswer}
    set grading [toplevel .grading]
    $gWindowMenu add command -label "Grading" -command "capaRaise $grading"

    set labelFrame [frame $grading.labelFrame]
    set buttonFrame [frame $grading.buttonFrame]
    set winFrame [frame $grading.winFrame]
    pack $labelFrame $buttonFrame $winFrame -side top
    pack configure $buttonFrame -anchor e

    set string [$gStudentList get active]
    set gGrading(name) [string range $string 0 30]
    set gGrading(number) [string range $string 31 39]
    set gGrading(parsenum) $gGrading(number)
    label $labelFrame.namel -text "Student Name: "
    label $labelFrame.namet -text $gGrading(name)
    label $labelFrame.numberl -text "Number: "
    entry $labelFrame.numbert -width 9 -textvariable gGrading(parsenum)
    button $labelFrame.reparse -text "Parse" -command "updateGradingWindow 0"
    label $labelFrame.sectionl -text "Section: "
    label $labelFrame.sectiont -text $gSectionLoad
    pack $labelFrame.namel $labelFrame.namet $labelFrame.numberl \
	$labelFrame.numbert $labelFrame.reparse $labelFrame.sectionl \
	$labelFrame.sectiont -side left

    button $buttonFrame.button -textvariable gParseModeButton \
	    -command updateGradingWindow
    button $buttonFrame.save -text SAVE 
    button $buttonFrame.close -text Close -command "removeWindowEntry Grading
                                                   destroy $grading"
    pack $buttonFrame.button $buttonFrame.save $buttonFrame.close \
	    -side left

    set assignmentFrame [frame $winFrame.assignmentFrame]
    set gradingFrame [frame $winFrame.gradingFrame]
    pack $gradingFrame $assignmentFrame -side left

    scrollbar $assignmentFrame.scroll -orient vertical -command \
	    "$assignmentFrame.text yview"
    set gProblemText [text $assignmentFrame.text -yscrollcommand \
	    "$assignmentFrame.scroll set" -height 44 -width 80]
    pack $assignmentFrame.scroll $assignmentFrame.text -side left
    pack configure $assignmentFrame.scroll -expand false -fill y
    pack configure $assignmentFrame.text -expand true -fill both

    set numQuestions [enscriptParse $gParseMode $gSetLoad Specific 0 \
	    $gGrading(parsenum) $gGrading(name) gProblemText]
    
    $buttonFrame.save configure -command " saveGrading $numQuestions $grading "
    set setAllFrame [frame $gradingFrame.setallFrame ]
    set gradeFrame [frame $gradingFrame.gradeFrame ]
    pack $gradingFrame.setallFrame  $gradeFrame -side top

    frame $setAllFrame.space0 -width 55
    button $setAllFrame.dash -text "-" -padx -1 \
	    -command "gradeSetAll - $numQuestions"
    frame $setAllFrame.space1 -width 8
    button $setAllFrame.y -text "y" -padx -1 \
	    -command "gradeSetAll y $numQuestions"
    frame $setAllFrame.space2 -width 8
    button $setAllFrame.n -text "n" -padx -1 \
	    -command "gradeSetAll n $numQuestions"
    frame $setAllFrame.space3 -width 8
    button $setAllFrame.e -text "E" -padx -1 \
	    -command "gradeSetAll E $numQuestions"
    frame $setAllFrame.space4 -width 8
    label $setAllFrame.state -text "stat"
    label $setAllFrame.tries -text "tries"
    pack $setAllFrame.space0 $setAllFrame.dash \
	    $setAllFrame.space1 $setAllFrame.y \
	    $setAllFrame.space2 $setAllFrame.n \
	    $setAllFrame.space3 $setAllFrame.e \
	    $setAllFrame.space4 $setAllFrame.state \
	    $setAllFrame.tries -side left

    scrollbar $gradeFrame.scroll -orient vertical -command \
	    "$gradeFrame.canvas yview"
    set gGradeCanvas [canvas $gradeFrame.canvas -yscrollcommand \
	    "$gradeFrame.scroll set" -height 600 -width 200]
    pack $gradeFrame.scroll $gGradeCanvas -side left
    pack configure $gradeFrame.scroll -expand false -fill y
    pack configure $gGradeCanvas -expand true -fill both

    Centre_Dialog $grading default

    catch {unset gAnswer}
    catch {unset gQuestionType}

    getQuestionTypes $numQuestions 

    set vSize 26
    set offset 9
    set todo ""
    for { set i 1 } { $i <= $numQuestions } { incr i } {
	label $gGradeCanvas.prob$i -text "$i"
	$gGradeCanvas create window 10 [expr $offset + $vSize * ($i-1)] \
	    -window $gGradeCanvas.prob$i
	switch $gQuestionType($i) {
	    autoGrade
	    {
		radiobutton $gGradeCanvas.dash$i -variable gAnswer($i) \
			-value -
		$gGradeCanvas create window 40 [expr $offset+ $vSize * ($i-1)] -window \
			$gGradeCanvas.dash$i
		radiobutton $gGradeCanvas.y$i -variable gAnswer($i) -value y
		$gGradeCanvas create window 64 [expr $offset+ $vSize * ($i-1)] -window \
			$gGradeCanvas.y$i
		radiobutton $gGradeCanvas.n$i -variable gAnswer($i) -value n
		$gGradeCanvas create window 88 [expr $offset+ $vSize * ($i-1)] -window \
			$gGradeCanvas.n$i
		radiobutton $gGradeCanvas.e$i -variable gAnswer($i) -value E
		$gGradeCanvas create window 112 [expr $offset+ $vSize * ($i-1)] -window \
			$gGradeCanvas.e$i
		label $gGradeCanvas.state$i -textvariable gAnswer($i)
		$gGradeCanvas create window 136 [expr $offset+ $vSize * ($i-1)] -window \
			$gGradeCanvas.state$i
	    }
	    handGrade
	    {	
		radiobutton $gGradeCanvas.e$i -variable gAnswer($i) -value E
		$gGradeCanvas create window 112 [expr $offset+ $vSize * ($i-1)] -window \
			$gGradeCanvas.e$i
		scale $gGradeCanvas.hand$i -from 0 -to $gAnswer(max$i) -orient h \
		    -variable gAnswer(hand$i) -showvalue 0 -length 80
		$gGradeCanvas create window 60 [expr $offset+ $vSize * ($i-1)] -window \
			$gGradeCanvas.hand$i
		label $gGradeCanvas.current$i -textvariable gAnswer($i)
		$gGradeCanvas create window 136 [expr $offset+ $vSize * ($i-1)] -window \
			$gGradeCanvas.current$i
#		label $gGradeCanvas.max$i -textvariable gAnswer(max$i)
#		$gGradeCanvas create window 112 [expr $offset+ $vSize * ($i-1)] -window \
		    $gGradeCanvas.max$i
		trace variable gAnswer(hand$i) w handGradeExcuse
		lappend todo $i
	    }
	}
	entry $gGradeCanvas.tries$i -textvariable gAnswer($i.tries) -width 2
	$gGradeCanvas create window 170 [expr $offset+ $vSize * ($i - 1)] \
	    -window $gGradeCanvas.tries$i
    }
    $gGradeCanvas configure -scrollregion "0 0 150 \
                  [ expr ( $vSize * $numQuestions ) + $vSize ]"
    setupGAnswer $numQuestions

    foreach item $todo {
	if { $gAnswer($item) != "E" && $gAnswer($item) != "-" } { 
	    set gAnswer(hand$item) $gAnswer($item) 
	}
    }
}

###########################################################
# handGradeExcuse
###########################################################
###########################################################
###########################################################
proc handGradeExcuse { name1 name2 op } {
    global gAnswer
    scan $name2 "hand%d" num
    if { $gAnswer($name2) != "E" && $gAnswer($name2) != "-" } { 
	set gAnswer($num) $gAnswer($name2) 
    }
}
###########################################################
# gradeSetAll
###########################################################
###########################################################
###########################################################
proc gradeSetAll { type numQuestions } {
    global gAnswer gQuestionType
    
    for { set i 1 } { $i <= $numQuestions } { incr i } {
	switch $gQuestionType($i) {
	    autoGrade
	    {
		if { $gAnswer($i) != "Y" } { set gAnswer($i) $type }
	    }
	    handGrade
	    {
		switch -- $type {
		    y
		    { set gAnswer($i) $gAnswer(max$i) }
		    n
		    { set gAnswer($i) "0" }
		    E
		    -
		    -
		    { set gAnswer($i) $type }
		}
	    }
	}
    }
}

###########################################################
# saveGrading
###########################################################
# saves all changes, and updates the main window
###########################################################
# Arguments: the number of questions, and the name of the grading 
#            window
# Returns: None
# Globals: None
###########################################################
proc saveGrading { numQuestions grading } {
    if { [makeSure "You have pressed the SAVE button, Please confirm."] != \
	    "Cancel" } {
	saveGAnswer $numQuestions
	removeWindowEntry Grading
	destroy $grading
	loadScores
    }
}

###########################################################
# updateGradingWindow
###########################################################
# reparses the file and updates the parsemode button
###########################################################
# Arguments: None
# Returns: Nothing
# Globals: gProblemText - stores the results of the parse of the set
#          gParseMode - stores either 1 (Both, Questions Answers) or
#                       2 (Answer Only)
#          gSetLoad - currently being graded set
#          gGrading - an array containg
#               (name) - Name of the student
#               (number) - student number 
#          gParseModeButton - the text that will be displayed on
#                             the button that switches parse modes, 
#                             either "Answer Only" or 
#                             "Both, Questions Answers"
###########################################################
proc updateGradingWindow { { changeMode 1 } } {
    global gParseMode gSetLoad gGrading gProblemText gParseModeButton

    $gProblemText delete 0.0 end

    displayStatus "Updating Window . . ." message

    if { $changeMode } {
	switch $gParseMode {
	    1 { 
		set gParseModeButton "Both, Questions Answers" 
		set gParseMode 2
	    }
	    2 { 
		set gParseModeButton "Answer Only" 
		set gParseMode 1
	    }
	}
    }
    enscriptParse $gParseMode $gSetLoad Specific 0 $gGrading(parsenum) \
	    $gGrading(name) gProblemText
    removeStatus
}

###########################################################
# handGrade
###########################################################
# creates a dialog to get the new score for a problem from the
# user for a hand graded question
###########################################################
# Arguments: the number of the problem
# Returns: nothing
# Globals: gGradeCanvas - the name of the canvas widget that has all
#                         of the radio buttons for grading on
#          gNewHandGrade - the variable the new grade will be in
#          gAnswer - an array containg the score for the student
#                ($i) - i contains the current problem number and the entry
#                       has one of Y, N, E, or -
#                (max$i) - i is the problem number, these entries exist only
#                          for handgraded questions, and is the maximum
#                          score for that question
###########################################################
proc handGrade { problemNumber } {
    global gGradeCanvas gNewHandGrade gAnswer

    set handGrade [toplevel .handGrade]
    
    set gradeFrame [frame $handGrade.gradeFrame]
    set buttonFrame [frame $handGrade.buttonFrame]
    pack $gradeFrame $buttonFrame -side top
    
    label $gradeFrame.grade -text "Grade: "
    entry $gradeFrame.entry -textvariable gNewHandGrade
    # set gNewHandGrade $gAnswer($problemNumber)
    
    set gNewHandGrade $gAnswer(max$problemNumber)
    
    label $gradeFrame.maxGrade -textvariable gAnswer(max$problemNumber)
    pack $gradeFrame.grade $gradeFrame.entry $gradeFrame.maxGrade -side left

    button $buttonFrame.cancel -text Cancel -command "set gPrompt(ok) 0"
    button $buttonFrame.ok -text Ok -command \
	"setHandGrade $problemNumber;set gPrompt(ok) 1"
    pack $buttonFrame.cancel $buttonFrame.ok -side left
    
    Centre_Dialog $handGrade default
    capaRaise $handGrade
    capaGrab $handGrade
    vwait gPrompt(ok)
    capaGrab release $handGrade
    destroy $handGrade
    $gGradeCanvas.hand$problemNumber deselect
}

###########################################################
# main
###########################################################
# sets up the auto_path variable, some globals and adds some
# options then calls createControlWindow to give the user something
# to do
###########################################################
# Arguments: None
# Returns: Nothing
# Globals: None
###########################################################
if { [lindex $auto_path 0] == "./lib/tcl7.5" } {
    set auto_path ""
    lappend auto_path [pwd]/lib/tcl7.5
    lappend auto_path [pwd]/lib/tk4.1
}

lappend auto_path /usr/local/lib/CAPA45/Grader
lappend auto_path [pwd]
source gradesubjective.tcl
option add *font 8x13bold
set gUniqueNumber 1
createControlWindow

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