#!/bin/sh  
# \
exec oagwish "$0" "$@"

# To install run:
# /usr/local/oag/TclDevKit/solaris/bin/tclcompiler OperatorQuizQuestions
# cppatch -comment "compiled version of OperatorQuizQuestions" OperatorQuizQuestions.tbc

# $Log: not supported by cvs2svn $
# Revision 1.13  2008/07/16 15:51:05  soliday
# Updated to check for double quotes in questions and answers. These caused
# problems recently with new questions.
#
# Revision 1.12  2008/07/08 15:21:26  soliday
# Added the ISM category.
#
# Revision 1.11  2008/06/05 15:23:33  soliday
# Updated with new version of des.
#
# Revision 1.10  2007/07/09 21:09:08  soliday
# Updated to display the average of the top 25 scores.
#
# Revision 1.9  2007/03/12 15:07:20  soliday
# Added flood to the list of allowed users because he is in so many groups
# that oagmgr does not get listed.
#
# Revision 1.8  2006/08/04 15:41:13  soliday
# Added code to check for newline characters in the questions and the answers.
# If they are found it tell the user they have to remove them. These appear
# when pasteing multiple lines at the same time. I also added new feature to
# display the current score for the ACOs.
#
# Revision 1.7  2006/07/24 19:57:53  soliday
# Added a button to view the answers the operators gave.
#
# Revision 1.6  2006/07/07 21:04:00  soliday
# Added filter options. Added categories. Added buttons to jump to the first
# and last question.
#
# Revision 1.5  2006/06/02 12:36:01  soliday
# Exclude asdops from the edit mode.
#
# Revision 1.4  2006/05/26 19:57:41  soliday
# Added pasky to the list of users who can modify and view existing questions.
#
# Revision 1.3  2006/05/26 19:45:09  soliday
# Updated so that only OAG and users in the oagmgr group can view, modify and
# delete existing questions.
#
# Revision 1.2  2006/05/10 17:49:51  soliday
# Added installation comment.
#
# Revision 1.1  2006/05/10 17:36:42  soliday
# Wrote program to add/modify/delete questions for the operator quiz web page.
#
#

set auto_path [linsert $auto_path 0  /usr/local/oag/apps/lib/$env(HOST_ARCH)]
set auto_path [linsert $auto_path 0 /usr/local/oag/lib_patch/$env(HOST_ARCH)]

set questionFilter *
set correctFilter *
set incorrectFilter *
set incorrect2Filter *
set incorrect3Filter *
set authorFilter *
set SR 1
set Booster 1 
set PAR 1 
set Linac 1 
set ACIS 1 
set MISC 1
set ISM 1

proc CreateWidgets {args} {
    APSStrictParseArguments {mode}

    destroy .userFrame.main
    APSFrame .main \
      -parent .userFrame \
      -label "" \
      -packOption "-fill both -expand true"
    .userFrame.main configure

    set w .userFrame.main.frame
    if {$mode == "Add"} {
        global question correctAnswer incorrectAnswer1 incorrectAnswer2 incorrectAnswer3 author env category
        set question ""
        set correctAnswer ""
        set incorrectAnswer1 ""
        set incorrectAnswer2 ""
        set incorrectAnswer3 ""
        set author $env(USER)
        set category MISC

        label $w.label -text "$mode Question"
        pack $w.label
        APSLabeledEntry .question \
          -parent $w \
          -label "                    Question:" \
          -width 100 \
          -textVariable question \
          -packOption "-fill x -expand yes"
        APSLabeledEntry .correctanswer \
          -parent $w \
          -label "              Correct Answer:" \
          -width 100 \
          -textVariable correctAnswer \
          -packOption "-fill x -expand yes"
        APSLabeledEntry .incorrectanswer1 \
          -parent $w \
          -label "           Incorrect Answer1:" \
          -width 100 \
          -textVariable incorrectAnswer1 \
          -packOption "-fill x -expand yes"
        APSLabeledEntry .incorrectanswer2 \
          -parent $w \
          -label "Incorrect Answer2: (optional)" \
          -width 100 \
          -textVariable incorrectAnswer2 \
          -packOption "-fill x -expand yes"
        APSLabeledEntry .incorrectanswer3 \
          -parent $w \
          -label "Incorrect Answer3: (optional)" \
          -width 100 \
          -textVariable incorrectAnswer3 \
          -packOption "-fill x -expand yes"
        APSLabeledEntry .author \
          -parent $w \
          -label "                      Author:" \
          -width 30 \
          -textVariable author \
          -packOption "-fill none -expand no -anchor w"
        APSRadioButtonFrame .categories \
          -parent $w \
          -label "                    Category:" \
          -buttonList "SR Booster PAR Linac ACIS ISM MISC" \
          -valueList "SR Booster PAR Linac ACIS ISM MISC" \
          -variable category \
          -orientation horizontal
        APSButton .add \
          -parent $w \
          -text "Add Question" \
          -command "AddQuestion"
    } else {
        global question correctAnswer incorrectAnswer1 incorrectAnswer2 incorrectAnswer3 author env row category
        set question ""
        set correctAnswer ""
        set incorrectAnswer1 ""
        set incorrectAnswer2 ""
        set incorrectAnswer3 ""
        set author $env(USER)
        set category MISC

        frame $w.left
        pack $w.left -side left
        frame $w.right
        pack $w.right -side left -anchor n

        label $w.right.label -text Filter
        entry $w.right.questionFilter -textvariable questionFilter
        entry $w.right.correctFilter -textvariable correctFilter
        entry $w.right.incorrectFilter -textvariable incorrectFilter
        entry $w.right.incorrect2Filter -textvariable incorrect2Filter
        entry $w.right.incorrect3Filter -textvariable incorrect3Filter
        entry $w.right.authorFilter -textvariable authorFilter

        pack $w.right.label -pady 0
        pack $w.right.questionFilter $w.right.correctFilter $w.right.incorrectFilter $w.right.incorrect2Filter $w.right.incorrect3Filter $w.right.authorFilter -anchor n -pady 1

        APSCheckButtonFrame .categories \
          -parent $w.right \
          -label "" \
          -buttonList "SR Booster PAR Linac ACIS ISM MISC" \
          -variableList "SR Booster PAR Linac ACIS ISM MISC" \
          -orientation horizontal \
          -limitPerRow 4
        

        set w $w.left
        label $w.label -text "$mode Question"
        pack $w.label
        APSLabeledEntry .question \
          -parent $w \
          -label "                    Question:" \
          -width 100 \
          -textVariable question \
          -packOption "-fill x -expand yes"
        APSLabeledEntry .correctanswer \
          -parent $w \
          -label "              Correct Answer:" \
          -width 100 \
          -textVariable correctAnswer \
          -packOption "-fill x -expand yes"
        APSLabeledEntry .incorrectanswer1 \
          -parent $w \
          -label "           Incorrect Answer1:" \
          -width 100 \
          -textVariable incorrectAnswer1 \
          -packOption "-fill x -expand yes"
        APSLabeledEntry .incorrectanswer2 \
          -parent $w \
          -label "Incorrect Answer2: (optional)" \
          -width 100 \
          -textVariable incorrectAnswer2 \
          -packOption "-fill x -expand yes"
        APSLabeledEntry .incorrectanswer3 \
          -parent $w \
          -label "Incorrect Answer3: (optional)" \
          -width 100 \
          -textVariable incorrectAnswer3 \
          -packOption "-fill x -expand yes"
        APSLabeledEntry .author \
          -parent $w \
          -label "                      Author:" \
          -width 30 \
          -textVariable author \
          -packOption "-fill none -expand no -anchor w"
        APSRadioButtonFrame .categories \
          -parent $w \
          -label "                    Category:" \
          -buttonList "SR Booster PAR Linac ACIS ISM MISC" \
          -valueList "SR Booster PAR Linac ACIS ISM MISC" \
          -variable category \
          -orientation horizontal
        APSButton .delete \
          -parent $w \
          -text "Delete Question" \
          -command "DeleteQuestion"
        APSButton .modify \
          -parent $w \
          -text "Modify Question" \
          -command "ModifyQuestion"
        APSButton .first \
          -parent $w \
          -text "<<" \
          -command "set row 1 ; PreviousQuestion"
        APSButton .previous \
          -parent $w \
          -text "<-" \
          -command "PreviousQuestion"
        set row 1
        entry $w.currentRow -textvariable row -width 4
        pack $w.currentRow -side left
        bind $w.currentRow <Return> "ListQuestion -direction up"
        APSButton .next \
          -parent $w \
          -text "->" \
          -command "NextQuestion"
        APSButton .last \
          -parent $w \
          -text ">>" \
          -command "set row 9999 ; NextQuestion"
        ListQuestion -direction up
        APSButton .sddsedit \
          -parent $w \
          -text "sddsedit" \
          -command "SDDSEdit"
    }
}

proc SDDSEdit {args} {
    set fileName [APSTmpDir]/[APSTmpString]
    APSAddToTempFileList $fileName
    set mtime [file mtime /net/epics-ops/web_roots/ops/cgi-bin/quiz_questions.sdds.des]
    if {[catch {exec /usr/bin/des -f -k 135792468 -d /net/epics-ops/web_roots/ops/cgi-bin/quiz_questions.sdds.des $fileName} results]} {
        APSSetVarAndUpdate status $results
        bell
        return
    }
    set m2 [file mtime $fileName]
    if {[catch {exec sddsedit -fileName $fileName} results]} {
        APSSetVarAndUpdate status $results
        bell
        return
    }
    if {$m2 == [file mtime $fileName]} {
        file delete -force $fileName
        ListQuestion -direction up
        return
    }
    if {$mtime != [file mtime /net/epics-ops/web_roots/ops/cgi-bin/quiz_questions.sdds.des]} {
        APSSetVarAndUpdate status "The quesitons file has been modified while you were working on it. Your changes will not be saved because it may cause someone else's changes may be lost."
        bell
        return
    }
    if {[catch {exec /usr/bin/des -f -k 135792468 -e $fileName /net/epics-ops/web_roots/ops/cgi-bin/quiz_questions.sdds.des} results]} {
        APSSetVarAndUpdate status $results
        file delete -force $fileName
        bell
        return
    }
    file delete -force $fileName
    APSSetVarAndUpdate status "Data modified by sddsedit has been encrypted for the web site."
    ListQuestion -direction up
}

proc ViewAnswers {args} {
    set fileName [APSTmpDir]/[APSTmpString]
    APSAddToTempFileList $fileName
    if {[catch {exec /usr/bin/des -f -k 135792468 -d /net/epics-ops/web_roots/ops/cgi-bin/quiz_answers.sdds.des $fileName} results]} {
        APSSetVarAndUpdate status $results
        bell
        return
    }
    if {[catch {exec sddsedit -fileName $fileName} results]} {
        APSSetVarAndUpdate status $results
        bell
        return
    }
    file delete -force $fileName
}

proc PreviousQuestion {args} {
    global row
    incr row -1
    ListQuestion -direction down
}
proc NextQuestion {args} {
    global row
    incr row
    ListQuestion -direction up
}

proc ListQuestion {args} {
    global question correctAnswer incorrectAnswer1 incorrectAnswer2 incorrectAnswer3 author env row displayedRow mtime category

    APSStrictParseArguments {direction}

    set mtime [file mtime /net/epics-ops/web_roots/ops/cgi-bin/quiz_questions.sdds.des]
    set fileName [APSTmpDir]/[APSTmpString]
    APSAddToTempFileList $fileName
    if {[catch {exec /usr/bin/des -f -k 135792468 -d /net/epics-ops/web_roots/ops/cgi-bin/quiz_questions.sdds.des $fileName} results]} {
        APSSetVarAndUpdate status $results
        bell
        return
    }
    if {[catch {sdds load $fileName data} results]} {
        APSSetVarAndUpdate status $results
        file delete -force $fileName
        bell
        return
    }
    file delete -force $fileName
    
    if {![string is integer $row]} {
        APSSetVarAndUpdate row 1
    }
    set totalRows [llength [lindex $data(Column.Author) 0]]
    if {$row < 1} {
        APSSetVarAndUpdate row 1
    }
    if {$row > $totalRows} {
        APSSetVarAndUpdate row $totalRows
    }
    global questionFilter correctFilter incorrectFilter incorrect2Filter incorrect3Filter authorFilter SR Booster PAR Linac ACIS ISM MISC
    while {1} {
        set i [expr {$row - 1}]
        set displayedRow $i
        
        set question [lindex [lindex $data(Column.Question) 0] $i]
        set correctAnswer [lindex [lindex $data(Column.CorrectAnswer) 0] $i]
        set incorrectAnswer1 [lindex [lindex $data(Column.IncorrectAnswer1) 0] $i]
        set incorrectAnswer2 [lindex [lindex $data(Column.IncorrectAnswer2) 0] $i]
        set incorrectAnswer3 [lindex [lindex $data(Column.IncorrectAnswer3) 0] $i]
        set author [lindex [lindex $data(Column.Author) 0] $i]
        set category [lindex [lindex $data(Column.Category) 0] $i]
        if {![llength $category]} {
            set category MISC
        }

        if {([string match -nocase *${questionFilter}* $question] == 0) || \
              ([string match -nocase *${correctFilter}* $correctAnswer] == 0) || \
              ([string match -nocase *${incorrectFilter}* $incorrectAnswer1] == 0) || \
              ([string match -nocase *${incorrect2Filter}* $incorrectAnswer2] == 0) || \
              ([string match -nocase *${incorrect3Filter}* $incorrectAnswer3] == 0) || \
              ([string match -nocase *${authorFilter}* $author] == 0) || \
              ([set $category] != 1)} {
            if {$direction == "up"} {
                if {$row == $totalRows} {
                    bell
                    APSSetVarAndUpdate status "Reached the end without finding a match"
                    break
                }
                incr row
            } else {
                if {$row == 1} {
                    bell
                    APSSetVarAndUpdate status "Reached the end without finding a match"
                    break
                }
                incr row -1
            }
            continue
        }
        break
    }
    APSSetVarAndUpdate status "Question $row displayed"
}

proc ModifyQuestion {args} {
    global question correctAnswer incorrectAnswer1 incorrectAnswer2 incorrectAnswer3 author env row displayedRow mtime category

    if {$mtime != [file mtime /net/epics-ops/web_roots/ops/cgi-bin/quiz_questions.sdds.des]} {
        APSSetVarAndUpdate status "The quesitons file has been modified while you were working on it. Your changes will not be saved because it may cause someone else's changes may be lost."
        bell
        return
    }
    if {![llength $question]} {
        APSSetVarAndUpdate status "Invalid question"
        bell
        return
    }
    if {[string first \n $question] != -1} {
        APSSetVarAndUpdate status "Please remove newline characters from the question. These probably appeared because you copied and pasted multiple lines."
        bell
        return
    }
    if {[string first \" $question] != -1} {
        APSSetVarAndUpdate status "Please remove double quotes from the question and replace them with single quotes."
        bell
        return
    }
    if {![llength $correctAnswer]} {
        APSSetVarAndUpdate status "Invalid correct answer"
        bell
        return
    }
    if {[string first \n $correctAnswer] != -1} {
        APSSetVarAndUpdate status "Please remove newline characters from the correct answer. These probably appeared because you copied and pasted multiple lines."
        bell
        return
    }
    if {[string first \" $correctAnswer] != -1} {
        APSSetVarAndUpdate status "Please remove double quotes from the correct answer and replace them with single quotes."
        bell
        return
    }
    if {![llength $incorrectAnswer1]} {
        APSSetVarAndUpdate status "Invalid incorrect answer1"
        bell
        return
    }
    if {[string first \n $incorrectAnswer1] != -1} {
        APSSetVarAndUpdate status "Please remove newline characters from the incorrect answer1. These probably appeared because you copied and pasted multiple lines."
        bell
        return
    }
    if {[string first \" $incorrectAnswer1] != -1} {
        APSSetVarAndUpdate status "Please remove double quotes from the incorrect answer1 and replace them with single quotes."
        bell
        return
    }
    if {[string first \n $incorrectAnswer2] != -1} {
        APSSetVarAndUpdate status "Please remove newline characters from the incorrect answer2. These probably appeared because you copied and pasted multiple lines."
        bell
        return
    }
    if {[string first \" $incorrectAnswer2] != -1} {
        APSSetVarAndUpdate status "Please remove double quotes from the incorrect answer2 and replace them with single quotes."
        bell
        return
    }
    if {[string first \n $incorrectAnswer3] != -1} {
        APSSetVarAndUpdate status "Please remove newline characters from the incorrect answer3. These probably appeared because you copied and pasted multiple lines."
        bell
        return
    }
    if {[string first \" $incorrectAnswer3] != -1} {
        APSSetVarAndUpdate status "Please remove double quotes from the incorrect answer3 and replace them with single quotes."
        bell
        return
    }
#    if {![llength $incorrectAnswer2]} {
#        APSSetVarAndUpdate status "Invalid incorrect answer2"
#        bell
#        return
#    }
#    if {![llength $incorrectAnswer3]} {
#        APSSetVarAndUpdate status "Invalid incorrect answer3"
#        bell
#        return
#    }
    if {![llength $author]} {
        APSSetVarAndUpdate status "Invalid author"
        bell
        return
    }
    if {[string first \n $author] != -1} {
        APSSetVarAndUpdate status "Please remove newline characters from the author line. These probably appeared because you copied and pasted multiple lines."
        bell
        return
    }

    set fileName [APSTmpDir]/[APSTmpString]
    APSAddToTempFileList $fileName
    if {[catch {exec /usr/bin/des -f -k 135792468 -d /net/epics-ops/web_roots/ops/cgi-bin/quiz_questions.sdds.des $fileName} results]} {
        APSSetVarAndUpdate status $results
        bell
        return
    }
    if {[catch {sdds load $fileName data} results]} {
        APSSetVarAndUpdate status $results
        file delete -force $fileName
        bell
        return
    }
    file delete -force $fileName

    set tmpList [lindex $data(Column.Question) 0]
    set tmpList [lreplace $tmpList $displayedRow $displayedRow $question]
    set data(Column.Question) [list $tmpList]
    
    set tmpList [lindex $data(Column.CorrectAnswer) 0]
    set tmpList [lreplace $tmpList $displayedRow $displayedRow $correctAnswer]
    set data(Column.CorrectAnswer) [list $tmpList]
    
    set tmpList [lindex $data(Column.IncorrectAnswer1) 0]
    set tmpList [lreplace $tmpList $displayedRow $displayedRow $incorrectAnswer1]
    set data(Column.IncorrectAnswer1) [list $tmpList]
    
    set tmpList [lindex $data(Column.IncorrectAnswer2) 0]
    set tmpList [lreplace $tmpList $displayedRow $displayedRow $incorrectAnswer2]
    set data(Column.IncorrectAnswer2) [list $tmpList]
    
    set tmpList [lindex $data(Column.IncorrectAnswer3) 0]
    set tmpList [lreplace $tmpList $displayedRow $displayedRow $incorrectAnswer3]
    set data(Column.IncorrectAnswer3) [list $tmpList]
    
    set tmpList [lindex $data(Column.Author) 0]
    set tmpList [lreplace $tmpList $displayedRow $displayedRow $author]
    set data(Column.Author) [list $tmpList]
    
    set tmpList [lindex $data(Column.Category) 0]
    set tmpList [lreplace $tmpList $displayedRow $displayedRow $category]
    set data(Column.Category) [list $tmpList]
    
    if {[catch {sdds save $fileName data} results]} {
        APSSetVarAndUpdate status $results
        bell
        return
    }
    if {[catch {exec /usr/bin/des -f -k 135792468 -e $fileName /net/epics-ops/web_roots/ops/cgi-bin/quiz_questions.sdds.des} results]} {
        APSSetVarAndUpdate status $results
        file delete -force $fileName
        bell
        return
    }
    file delete -force $fileName
    APSSetVarAndUpdate status "Question Modified."

}

proc DeleteQuestion {args} {
    global question correctAnswer incorrectAnswer1 incorrectAnswer2 incorrectAnswer3 author env row displayedRow mtime category

    if {$mtime != [file mtime /net/epics-ops/web_roots/ops/cgi-bin/quiz_questions.sdds.des]} {
        APSSetVarAndUpdate status "The quesitons file has been modified while you were working on it. Your changes will not be saved because it may cause someone else's changes may be lost."
        bell
        return
    }
    set fileName [APSTmpDir]/[APSTmpString]
    APSAddToTempFileList $fileName
    if {[catch {exec /usr/bin/des -f -k 135792468 -d /net/epics-ops/web_roots/ops/cgi-bin/quiz_questions.sdds.des $fileName} results]} {
        APSSetVarAndUpdate status $results
        bell
        return
    }
    if {[catch {sdds load $fileName data} results]} {
        APSSetVarAndUpdate status $results
        file delete -force $fileName
        bell
        return
    }
    file delete -force $fileName

    foreach name $data(ColumnNames) {
        set tmpList [lindex $data(Column.$name) 0]
        set tmpList [lreplace $tmpList $displayedRow $displayedRow]
        set data(Column.$name) [list $tmpList]
    }
    set rows [llength $tmpList]
    
    if {[catch {sdds save $fileName data} results]} {
        APSSetVarAndUpdate status $results
        bell
        return
    }
    if {[catch {exec /usr/bin/des -f -k 135792468 -e $fileName /net/epics-ops/web_roots/ops/cgi-bin/quiz_questions.sdds.des} results]} {
        APSSetVarAndUpdate status $results
        file delete -force $fileName
        bell
        return
    }
    file delete -force $fileName
    APSSetVarAndUpdate status "Question Deleted. $rows questions now exist."
    ListQuestion -direction up
}

proc AddQuestion {args} {
    global question correctAnswer incorrectAnswer1 incorrectAnswer2 incorrectAnswer3 author env category
    
    if {![llength $question]} {
        APSSetVarAndUpdate status "Invalid question"
        bell
        return
    }
    if {[string first \n $question] != -1} {
        APSSetVarAndUpdate status "Please remove newline characters from the question. These probably appeared because you copied and pasted multiple lines."
        bell
        return
    }
    if {![llength $correctAnswer]} {
        APSSetVarAndUpdate status "Invalid correct answer"
        bell
        return
    }
    if {[string first \n $correctAnswer] != -1} {
        APSSetVarAndUpdate status "Please remove newline characters from the correct answer. These probably appeared because you copied and pasted multiple lines."
        bell
        return
    }
    if {![llength $incorrectAnswer1]} {
        APSSetVarAndUpdate status "Invalid incorrect answer1"
        bell
        return
    }
    if {[string first \n $incorrectAnswer1] != -1} {
        APSSetVarAndUpdate status "Please remove newline characters from the incorrect answer1. These probably appeared because you copied and pasted multiple lines."
        bell
        return
    }
    if {[string first \n $incorrectAnswer2] != -1} {
        APSSetVarAndUpdate status "Please remove newline characters from the incorrect answer2. These probably appeared because you copied and pasted multiple lines."
        bell
        return
    }
    if {[string first \n $incorrectAnswer3] != -1} {
        APSSetVarAndUpdate status "Please remove newline characters from the incorrect answer3. These probably appeared because you copied and pasted multiple lines."
        bell
        return
    }
#    if {![llength $incorrectAnswer2]} {
#        APSSetVarAndUpdate status "Invalid incorrect answer2"
#        bell
#        return
#    }
#    if {![llength $incorrectAnswer3]} {
#        APSSetVarAndUpdate status "Invalid incorrect answer3"
#        bell
#        return
#    }
    if {![llength $author]} {
        APSSetVarAndUpdate status "Invalid author"
        bell
        return
    }
    if {[string first \n $author] != -1} {
        APSSetVarAndUpdate status "Please remove newline characters from the author line. These probably appeared because you copied and pasted multiple lines."
        bell
        return
    }

    set fileName [APSTmpDir]/[APSTmpString]
    APSAddToTempFileList $fileName
    if {[catch {exec /usr/bin/des -f -k 135792468 -d /net/epics-ops/web_roots/ops/cgi-bin/quiz_questions.sdds.des $fileName} results]} {
        APSSetVarAndUpdate status $results
        bell
        return
    }
    if {[catch {sdds load $fileName data} results]} {
        APSSetVarAndUpdate status $results
        file delete -force $fileName
        bell
        return
    }
    file delete -force $fileName

    set tmpList [lindex $data(Column.Question) 0]
    lappend tmpList $question
    set data(Column.Question) [list $tmpList]
    
    set tmpList [lindex $data(Column.CorrectAnswer) 0]
    lappend tmpList $correctAnswer
    set data(Column.CorrectAnswer) [list $tmpList]
    
    set tmpList [lindex $data(Column.IncorrectAnswer1) 0]
    lappend tmpList $incorrectAnswer1
    set data(Column.IncorrectAnswer1) [list $tmpList]
    
    set tmpList [lindex $data(Column.IncorrectAnswer2) 0]
    lappend tmpList $incorrectAnswer2
    set data(Column.IncorrectAnswer2) [list $tmpList]
    
    set tmpList [lindex $data(Column.IncorrectAnswer3) 0]
    lappend tmpList $incorrectAnswer3
    set data(Column.IncorrectAnswer3) [list $tmpList]
    
    set tmpList [lindex $data(Column.Category) 0]
    lappend tmpList $category
    set data(Column.Category) [list $tmpList]
    
    set tmpList [lindex $data(Column.Author) 0]
    lappend tmpList $author
    set rows [llength $tmpList]
    set data(Column.Author) [list $tmpList]
    
    set skipColumns "Question CorrectAnswer IncorrectAnswer1 IncorrectAnswer2 IncorrectAnswer3 Author Category"
    foreach name $data(ColumnNames) {
        if {[lsearch $skipColumns $name] != -1} {
            continue
        }
        if {[string range $name end-3 end] == "Time"} {
            set tmpList [lindex $data(Column.$name) 0]
            lappend tmpList 0
            set data(Column.$name) [list $tmpList]
        } else {
            set tmpList [lindex $data(Column.$name) 0]
            lappend tmpList ?
            set data(Column.$name) [list $tmpList]
        }
    }
    if {[catch {sdds save $fileName data} results]} {
        APSSetVarAndUpdate status $results
        bell
        return
    }
    if {[catch {exec /usr/bin/des -f -k 135792468 -e $fileName /net/epics-ops/web_roots/ops/cgi-bin/quiz_questions.sdds.des} results]} {
        APSSetVarAndUpdate status $results
        file delete -force $fileName
        bell
        return
    }
    file delete -force $fileName
    APSSetVarAndUpdate status "Question Added. $rows questions now exist."

    set question ""
    set correctAnswer ""
    set incorrectAnswer1 ""
    set incorrectAnswer2 ""
    set incorrectAnswer3 ""
}

proc ViewScore {args} {
    set fileName [APSTmpDir]/[APSTmpString]
    APSAddToTempFileList $fileName
    if {[catch {exec /usr/bin/des -f -k 135792468 -d /net/epics-ops/web_roots/ops/cgi-bin/quiz_questions.sdds.des $fileName} results]} {
        APSSetVarAndUpdate status $results
        bell
        return
    }
    if {[catch {exec sdds2stream $fileName -para=ChristensenScore,ChristensenRounds,ChristensenDetailed,FystroScore,FystroRounds,FystroDetailed,LaBudaScore,LaBudaRounds,LaBudaDetailed,RonzhinScore,RonzhinRounds,RonzhinDetailed,SuttonScore,SuttonRounds,SuttonDetailed} results]} {
        APSSetVarAndUpdate status $results
        bell
        file delete -force $fileName
        return
    }
    file delete -force $fileName
    
    set detailed [lindex $results 2]
    if {[llength $detailed] == 0} {
        set ChristensenBest "Best 25 Ave Score 0.00"
    } else {
        set detailed [lrange [lsort -integer $detailed] 0 24]
        set a 0
        foreach b $detailed {
            set a [expr {$a + $b}]
        }
        set a [expr {$a * 1.0 / [llength $detailed]}]
        set ChristensenBest "Best 25 Ave Score [format %8.2f $a ]"
    }
    set detailed [lindex $results 5]
    if {[llength $detailed] == 0} {
        set FystroBest "Best 25 Ave Score 0.00"
    } else {
        set detailed [lrange [lsort -integer $detailed] 0 24]
        set a 0
        foreach b $detailed {
            set a [expr {$a + $b}]
        }
        set a [expr {$a * 1.0 / [llength $detailed]}]
        set FystroBest "Best 25 Ave Score [format %8.2f $a ]"
    }
    set detailed [lindex $results 8]
    if {[llength $detailed] == 0} {
        set LaBudaBest "Best 25 Ave Score 0.00"
    } else {
        set detailed [lrange [lsort -integer $detailed] 0 24]
        set a 0
        foreach b $detailed {
            set a [expr {$a + $b}]
        }
        set a [expr {$a * 1.0 / [llength $detailed]}]
        set LaBudaBest "Best 25 Ave Score [format %8.2f $a ]"
    }
    set detailed [lindex $results 11]
    if {[llength $detailed] == 0} {
        set RonzhinBest "Best 25 Ave Score 0.00"
    } else {
        set detailed [lrange [lsort -integer $detailed] 0 24]
        set a 0
        foreach b $detailed {
            set a [expr {$a + $b}]
        }
        set a [expr {$a * 1.0 / [llength $detailed]}]
        set RonzhinBest "Best 25 Ave Score [format %8.2f $a ]"
    }
    set detailed [lindex $results 14]
    if {[llength $detailed] == 0} {
        set SuttonBest "Best 25 Ave Score 0.00"
    } else {
        set detailed [lrange [lsort -integer $detailed] 0 24]
        set a 0
        foreach b $detailed {
            set a [expr {$a + $b}]
        }
        set a [expr {$a * 1.0 / [llength $detailed]}]
        set SuttonBest "Best 25 Ave Score [format %8.2f $a ]"
    }

    APSSetVarAndUpdate status "Christensen: $ChristensenBest, Ave Score [format %8.2f [lindex $results 0]], Rounds [lindex $results 1]"

    APSSetVarAndUpdate status "Fystro:      $FystroBest, Ave Score [format %8.2f [lindex $results 3]], Rounds [lindex $results 4]"
    APSSetVarAndUpdate status "LaBuda:      $LaBudaBest, Ave Score [format %8.2f [lindex $results 6]], Rounds [lindex $results 7]"
    APSSetVarAndUpdate status "Ronzhin:     $RonzhinBest, Ave Score [format %8.2f [lindex $results 9]], Rounds [lindex $results 10]"
    APSSetVarAndUpdate status "Sutton:      $SuttonBest, Ave Score [format %8.2f [lindex $results 12]], Rounds [lindex $results 13]"

}

APSApplication . \
  -name OperatorQuizQuestions

if {![file exists /net/epics-ops/web_roots/ops/cgi-bin/quiz_questions.sdds.des]} {
    set status "You must be on a computer that has access to /net/epics-ops/web_roots/ops. Try logging into challenger."
    APSScrolledStatus .status \
      -parent .userFrame \
      -textVariable status \
      -packOption "-fill x" \
      -width 100
    bell
} else {
    set status "Ready"
    APSScrolledStatus .status \
      -parent .userFrame \
      -textVariable status \
      -packOption "-fill x" \
      -width 100 -height 10
    
    set mode Add
    APSRadioButtonFrame .mode \
      -parent .userFrame \
      -variable mode \
      -buttonList "Add Delete/Modify" \
      -valueList "Add Delete/Modify" \
      -orientation horizontal \
      -label "Mode:" \
      -commandList {"CreateWidgets -mode Add" "CreateWidgets -mode Delete/Modify"}

    APSButton .answers -parent .userFrame.mode -text "View Answers" -command "ViewAnswers"

    if {($env(USER) == "asdops") || (($env(USER) != "oag") && ($env(USER) != "pasky") && ($env(USER) != "flood") && ([lsearch -exact [exec groups] "oagmgr"] == -1))} {
        .userFrame.mode.frame.button2 configure -state disabled
        .userFrame.mode.answers.button configure -state disabled
    } else {
        ViewScore
    }


    CreateWidgets -mode Add
}

