# GUI to changing student's grades
# Copyright (C) 1992-2000 Michigan State University
#
# The CAPA system is free software; you can redistribute it and/or
# modify it under the terms of the GNU Library General Public License as
# published by the Free Software Foundation; either version 2 of the
# License, or (at your option) any later version.
#
# The CAPA system is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# Library General Public License for more details.
#
# You should have received a copy of the GNU Library General Public
# License along with the CAPA system; see the file COPYING. If not,
# write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
# Boston, MA 02111-1307, USA.
#
# As a special exception, you have permission to link this program
# with the TtH/TtM library and distribute executables, as long as you
# follow the requirements of the GNU GPL in regard to all of the
# software in the executable aside from TtH/TtM.
###########################################################
# grader.tcl -
# Created 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>