Annotation of capa/capa51/GUITools/capastats.tcl, revision 1.1
1.1 ! albertel 1: ###########################################################
! 2: # runCapaTools
! 3: ###########################################################
! 4: ###########################################################
! 5: ###########################################################
! 6: proc runCapaTools { classDirConfigFile } {
! 7: global gUniqueNumber gWindowMenu gFile gCT
! 8:
! 9: set num [incr gUniqueNumber]
! 10:
! 11: set classDir [file dirname $classDirConfigFile]
! 12: set gFile($num) $classDir
! 13:
! 14: set utilsMenu [menu .utilsMenu$num -tearoff 0 -type tearoff -font 8x13bold \
! 15: -disabledforeground grey85 ]
! 16: set gCT($num) $utilsMenu
! 17:
! 18: set pathLength [string length $gFile($num)]
! 19: if { $pathLength > 22 } {
! 20: set pathSubset ...[string range $gFile($num) [expr $pathLength - 22 ] end]
! 21: } else {
! 22: set pathSubset $gFile($num)
! 23: }
! 24: $utilsMenu add command -label "CapaUtils Ver 1.1" -foreground grey85 -background \
! 25: black -state disabled
! 26: $utilsMenu add command -label $pathSubset -foreground white -background \
! 27: grey30 -state disabled
! 28:
! 29: $utilsMenu add command -label "Change Class path" -command "CTchangePath $num"
! 30: $utilsMenu add command -label "Run capastat" -command "CTcapaStat $num"
! 31: $utilsMenu add command -label "Run capastat2" -command "CTcapaStat2 $num"
! 32: $utilsMenu add command -label "Summarize Log files" -command "CTlogAnalysis $num"
! 33: $utilsMenu add command -label "Student Course Profile" -command \
! 34: "CTstartStudentCourseProfile $num"
! 35: $utilsMenu add command -label "CAPA IDs for one student" \
! 36: -command "CToneStudentCapaID $num"
! 37: $utilsMenu add command -label "All CAPA IDs" -command "CTclassCapaID $num"
! 38: $utilsMenu add command -label "Item Analysis" -command "CTitemAnalysisStart $num"
! 39: $utilsMenu add command -label "Item Correlation" \
! 40: -command "CTitemCorrelationStart $num"
! 41: # $utilsMenu add command -label "Email" -command ""
! 42: # $utilsMenu add command -label "View Score File" -command ""
! 43: $utilsMenu add command -label "View Submissions" -command "CTsubmissions $num"
! 44: $utilsMenu add command -label "Analyze Class Report" -command "CTanalyzeReport $num"
! 45: $utilsMenu add command -label "Analyze Responses" -command "CTanalyzeScorer $num"
! 46: $utilsMenu add command -label "Graph a Responses Analysis" -command "CTgraphAnalyzeScorer $num"
! 47: $utilsMenu add command -label "Quit" -command "CTquit $num"
! 48: $utilsMenu post 0 0
! 49: Centre_Dialog $utilsMenu default
! 50: set geometry [wm geometry $utilsMenu]
! 51: wm geometry $utilsMenu +0+[lindex [split $geometry +] end]
! 52: parseCapaConfig $num $gFile($num)
! 53: parseCapaUtilsConfig $num $gFile($num)
! 54: }
! 55:
! 56: #menu commands
! 57:
! 58: ###########################################################
! 59: # CTchangePath
! 60: ###########################################################
! 61: ###########################################################
! 62: ###########################################################
! 63: #FIXME need to wait unit all running commands are done
! 64: proc CTchangePath { num } {
! 65: global gFile gCapaConfig
! 66: set path [tk_getOpenFile -title "Please select a capa.config file" -filetypes \
! 67: { { {Capa Config} {capa.config} } }]
! 68: if { $path == "" } { return }
! 69: set gFile($num) [file dirname $path]
! 70: foreach temp [array names gCapaConfig "$num.*"] { unset gCapaConfig($temp) }
! 71: parseCapaConfig $num $gFile($num)
! 72: parseCapaUtilsConfig $num $gFile($num)
! 73: set pathLength [string length $gFile($num)]
! 74: if { $pathLength > 22 } {
! 75: set pathSubset ...[string range $gFile($num) [expr $pathLength - 22 ] end]
! 76: } else {
! 77: set pathSubset $gFile($num)
! 78: }
! 79: .utilsMenu$num entryconfigure 1 -label $pathSubset
! 80: }
! 81:
! 82: ###########################################################
! 83: # CTcapaStat2
! 84: ###########################################################
! 85: ###########################################################
! 86: ###########################################################
! 87: proc CTcapaStat2 { num } {
! 88: global gFile gCT gUniqueNumber
! 89: if { [set setId [getOneSet $gCT($num) $gFile($num)]] == "" } { return }
! 90: set cmdnum [incr gUniqueNumber]
! 91: set gCT(cmd.$cmdnum) capastat
! 92: if { [
! 93: catch {
! 94: CTdatestamp $cmdnum
! 95: set day [CTgetWhen $cmdnum]
! 96: set file [file join $gFile($num) records "subset$setId.db"]
! 97: displayStatus "Generating [file tail $file]" both $cmdnum
! 98: CTcreateSubset $num $cmdnum $day $setId
! 99: updateStatusBar 0.0 $cmdnum
! 100: updateStatusMessage "Generating Stats [file tail $file]" $cmdnum
! 101: CTscanSetDB $cmdnum $file Q_cnt L_cnt
! 102: updateStatusBar 0.0 $cmdnum
! 103: updateStatusMessage "Generating Averages [file tail $file]" $cmdnum
! 104: CTpercentageScores $cmdnum $setId $L_cnt
! 105: CTaverage $cmdnum $Q_cnt $L_cnt faillist dodifflist numyes
! 106: if { $L_cnt != 0 } {
! 107: CTbargraph $gCT($num) $num [incr gUniqueNumber] $faillist $gFile($num) "Not-Yet-Correct Distribution for set $setId" "Problem \#" "%Wrong"
! 108: CTbargraph $gCT($num) $num [incr gUniqueNumber] $dodifflist $gFile($num) "Degree of Difficulty Distribution for set $setId" "Problem \#" "Degree Of Diff."
! 109: CTbargraph $gCT($num) $num [incr gUniqueNumber] $numyes $gFile($num) "Number of Yeses received for set $setId" "Problem \#" "\#Students"
! 110: }
! 111: removeStatus $cmdnum
! 112: CToutput $num $cmdnum
! 113: } errors ] } {
! 114: global errorCode errorInfo
! 115: displayError "$errors\n$errorCode\n$errorInfo"
! 116: unset gCT(cmd.$cmdnum)
! 117: } else {
! 118: unset gCT(cmd.$cmdnum)
! 119: }
! 120: }
! 121:
! 122: ###########################################################
! 123: # CTcapaStat
! 124: ###########################################################
! 125: ###########################################################
! 126: ###########################################################
! 127: proc CTcapaStat { num } {
! 128: global gFile gCT gUniqueNumber
! 129: if { [set setId [getOneSet $gCT($num) $gFile($num)]] == "" } { return }
! 130: set cmdnum [incr gUniqueNumber]
! 131: set gCT(cmd.$cmdnum) capastat
! 132: if { [
! 133: catch {
! 134: CTdatestamp $cmdnum
! 135: set file [file join $gFile($num) records "set$setId.db"]
! 136: displayStatus "Generating Stats [file tail $file]" both $cmdnum
! 137: CTscanSetDB $cmdnum $file Q_cnt L_cnt
! 138: updateStatusBar 0.0 $cmdnum
! 139: updateStatusMessage "Generating Averages [file tail $file]" $cmdnum
! 140: CTpercentageScores $cmdnum $setId $L_cnt
! 141: CTaverage $cmdnum $Q_cnt $L_cnt faillist dodifflist numyes
! 142: CTbargraph $gCT($num) $num [incr gUniqueNumber] $faillist $gFile($num) "Not-Yet-Correct Distribution for set $setId" "Problem \#" "%Wrong"
! 143: CTbargraph $gCT($num) $num [incr gUniqueNumber] $dodifflist $gFile($num) "Degree of Difficulty Distribution for set $setId" "Problem \#" "Degree Of Diff."
! 144: CTbargraph $gCT($num) $num [incr gUniqueNumber] $numyes $gFile($num) "Number of Yeses received for set $setId" "Problem \#" "\#Students"
! 145: removeStatus $cmdnum
! 146: CToutput $num $cmdnum
! 147: } errors ] } {
! 148: global errorCode errorInfo
! 149: displayError "$errors\n$errorCode\n$errorInfo"
! 150: unset gCT(cmd.$cmdnum)
! 151: } else {
! 152: unset gCT(cmd.$cmdnum)
! 153: }
! 154: }
! 155:
! 156: ###########################################################
! 157: # CTlogAnalysis
! 158: ###########################################################
! 159: ###########################################################
! 160: ###########################################################
! 161: proc CTlogAnalysis { num } {
! 162: global gFile gUniqueNumber gCT
! 163: if { [set setId [getOneSet $gCT($num) $gFile($num)]] == "" } { return }
! 164:
! 165: set cmdnum [incr gUniqueNumber]
! 166: set gCT(cmd.$cmdnum) loganalysis
! 167: CTdatestamp $cmdnum
! 168: if { [ catch { CTlogAnalysis2 $num $cmdnum $setId } errors ] } {
! 169: displayError $errors
! 170: unset gCT(cmd.$cmdnum)
! 171: } else {
! 172: unset gCT(cmd.$cmdnum)
! 173: }
! 174: CToutput $num $cmdnum
! 175: }
! 176:
! 177: ###########################################################
! 178: # CTstartStudentCourseProfile
! 179: ###########################################################
! 180: ###########################################################
! 181: ###########################################################
! 182: proc CTstartStudentCourseProfile { num } {
! 183: global gFile gCT
! 184: getOneStudent $gCT($num) $gFile($num) s_id s_name
! 185: if { $s_id == "" } { return }
! 186: CTstudentCourseProfile $num $s_id $s_name
! 187: }
! 188:
! 189: ###########################################################
! 190: # CTstudentCourseProfile
! 191: ###########################################################
! 192: ###########################################################
! 193: ###########################################################
! 194: proc CTstudentCourseProfile { num s_id s_name {loginAnalysis 2} } {
! 195: global gFile gUniqueNumber gCapaConfig gCT
! 196:
! 197: set cmdnum [incr gUniqueNumber]
! 198: set gCT(cmd.$cmdnum) studentcourseprofile
! 199: displayStatus "Collecting homework scores for $s_name" both $cmdnum
! 200: CTdatestamp $cmdnum
! 201: CTputs $cmdnum "$s_name\n"
! 202: if { [ catch { CTcollectSetScores $cmdnum $gFile($num) $s_id 1 \
! 203: $gCapaConfig($num.homework_scores_limit_set) } error ] } {
! 204: global errorCode errorInfo
! 205: displayError "$error \n $errorCode \n $errorInfo"
! 206: }
! 207: foreach type { quiz exam supp others } {
! 208: updateStatusMessage "Collecting $type scores for $s_name" $cmdnum
! 209: catch {
! 210: if { [file isdirectory $gCapaConfig($num.[set type]_path)] } {
! 211: CTcollectSetScores $cmdnum $gCapaConfig($num.[set type]_path) $s_id 1 \
! 212: $gCapaConfig($num.[set type]_scores_limit_set)
! 213: }
! 214: }
! 215: }
! 216: removeStatus $cmdnum
! 217: if { ($loginAnalysis == 2 && "Yes" == [makeSure \
! 218: "Do you wish to do a Login Analysis? It may take a while." ])
! 219: || ($loginAnalysis == 1) } {
! 220: displayStatus "Analyzing login data." both $cmdnum
! 221: if { [catch { CTloginAnalysis $cmdnum $gFile($num) $s_id \
! 222: $gCapaConfig($num.homework_scores_limit_set) } error] } {
! 223: displayError error
! 224: }
! 225: if { [catch { CTstudentSetAnalysis $cmdnum $gFile($num) $s_id \
! 226: $gCapaConfig($num.homework_scores_limit_set) } error] } {
! 227: displayError error
! 228: }
! 229: removeStatus $cmdnum
! 230: }
! 231: CTdisplayStudent $cmdnum $gCT($num) $gFile($num) $s_id
! 232: unset gCT(cmd.$cmdnum)
! 233: CToutput $num $cmdnum
! 234: }
! 235:
! 236: ###########################################################
! 237: # CToneStudentCapaID
! 238: ###########################################################
! 239: ###########################################################
! 240: ###########################################################
! 241: proc CToneStudentCapaID { num } {
! 242: global gFile gUniqueNumber gCapaConfig gCT
! 243:
! 244: getOneStudent $gCT($num) $gFile($num) s_id s_name
! 245: if { $s_id == "" } { return }
! 246:
! 247: set cmdnum [incr gUniqueNumber]
! 248: set gCT(cmd.$cmdnum) onestudentcapaid
! 249: set setlist [getSetRange $gCT($num) $gFile($num)]
! 250: set command "$gCapaConfig($num.allcapaid_command) -i -stu $s_id -s [lindex $setlist 0] -e [lindex $setlist 1] -c $gFile($num)"
! 251: if { "Yes" == [makeSure "CMD: $command\n Do you wish to execute this command?"] } {
! 252: CTdatestamp $cmdnum
! 253: CTputs $cmdnum "CapaIDs for: $s_id, $s_name\n"
! 254: displayStatus "Getting CapaIDs" spinner $cmdnum
! 255: set fileId [open "|$command" "r"]
! 256: fconfigure $fileId -blocking 0
! 257: fileevent $fileId readable "CTrunCommand $num $cmdnum $fileId"
! 258: }
! 259: }
! 260:
! 261: ###########################################################
! 262: # CTclassCapaID
! 263: ###########################################################
! 264: ###########################################################
! 265: ###########################################################
! 266: proc CTclassCapaID { num } {
! 267: global gFile gUniqueNumber gCapaConfig gCT
! 268:
! 269: set cmdnum [incr gUniqueNumber]
! 270: set gCT(cmd.$cmdnum) classcapaid
! 271: set setlist [getSetRange $gCT($num) $gFile($num)]
! 272: if { $setlist == "" } { return }
! 273: set command "$gCapaConfig($num.allcapaid_command) -i -s [lindex $setlist 0] -e [lindex $setlist 1] -c $gFile($num)"
! 274: if { "Yes" == [makeSure "CMD: $command\n Do you wish to execute this command?"] } {
! 275: CTdatestamp $cmdnum
! 276: displayStatus "Getting all CapaIDs" spinner $cmdnum
! 277: set fileId [open "|$command" "r"]
! 278: fconfigure $fileId -blocking 0
! 279: fileevent $fileId readable "CTrunCommand $num $cmdnum $fileId"
! 280: }
! 281: }
! 282:
! 283: ###########################################################
! 284: # CTitemAnalysisStart
! 285: ###########################################################
! 286: ###########################################################
! 287: ###########################################################
! 288: proc CTitemAnalysisStart { num } {
! 289: global gFile gUniqueNumber gCapaConfig gCT
! 290:
! 291: set cmdnum [incr gUniqueNumber]
! 292: set gCT(cmd.$cmdnum) itemanalysis
! 293: set paths ""
! 294: lappend paths [list "classpath" $gFile($num)]
! 295: foreach path [lsort [array names gCapaConfig "$num.*_path"]] {
! 296: lappend paths [list [lindex [split $path "."] 1] $gCapaConfig($path) ]
! 297: }
! 298: if {[set select [multipleChoice $gCT($num) "Select a class path" $paths ] ] == ""} {
! 299: unset gCT(cmd.$cmdnum)
! 300: return
! 301: }
! 302: if { [set sets [getSetRange $gCT($num) $gFile($num)]] == "" } {
! 303: unset gCT(cmd.$cmdnum)
! 304: return
! 305: }
! 306: CTdatestamp $cmdnum
! 307: if { [ catch {CTitemAnalysisRange $cmdnum [lindex $select 1] \
! 308: [lindex $sets 0] [lindex $sets 1] } errors ] } {
! 309: displayError $errors
! 310: }
! 311: unset gCT(cmd.$cmdnum)
! 312: CToutput $num $cmdnum
! 313: }
! 314:
! 315: ###########################################################
! 316: # CTitemCorrelationStart
! 317: ###########################################################
! 318: ###########################################################
! 319: ###########################################################
! 320: proc CTitemCorrelationStart { num } {
! 321: global gFile gUniqueNumber gCapaConfig gCT
! 322:
! 323: ## FIXME:
! 324: ## Let user specify how many categories to calculate correlation
! 325: ## For each category, the user can specify problem numbers to
! 326: ## be in that category
! 327: ## Then, the correlations between each category is calculated
! 328: ##
! 329: set cmdnum [incr gUniqueNumber]
! 330: set gCT(cmd.$cmdnum) itemanalysis
! 331: set paths ""
! 332: lappend paths [list "classpath" $gFile($num)]
! 333: foreach path [lsort [array names gCapaConfig "$num.*_path"]] {
! 334: lappend paths [list [lindex [split $path "."] 1] $gCapaConfig($path) ]
! 335: }
! 336: if { [set select [multipleChoice $gCT($num) "Select a class path" $paths ] ] == "" } {
! 337: unset gCT(cmd.$cmdnum)
! 338: return
! 339: }
! 340: if { [set setId [getOneSet $gCT($num) $gFile($num)]] == "" } {
! 341: unset gCT(cmd.$cmdnum)
! 342: return
! 343: }
! 344: CTdatestamp $cmdnum
! 345: if { [ catch { CTitemCorrelation $cmdnum [lindex $select 1] \
! 346: $setId } errors ] } { displayError $errors }
! 347: unset gCT(cmd.$cmdnum)
! 348: CToutput $num $cmdnum
! 349: }
! 350:
! 351: ###########################################################
! 352: # CTsubmissions
! 353: ###########################################################
! 354: ###########################################################
! 355: ###########################################################
! 356: proc CTsubmissions { num } {
! 357: global gCT gFile gUniqueNumber gCapaConfig
! 358:
! 359: getOneStudent $gCT($num) $gFile($num) s_id s_name
! 360: if { $s_id == "" } { return }
! 361:
! 362: set cmdnum [incr gUniqueNumber]
! 363: set gCT(cmd.$cmdnum) submissions
! 364: if { "" == [set setlist [getSetRange $gCT($num) $gFile($num)]] } { return }
! 365: CTdatestamp $cmdnum
! 366: CTputs $cmdnum "Submissions for: $s_id, $s_name\n"
! 367: displayStatus "Getting submissions" spinner $cmdnum
! 368: CTsubmissionsLaunch $num $cmdnum telnet $s_id $s_name \
! 369: [lindex $setlist 0] [lindex $setlist 1]
! 370: }
! 371:
! 372: ###########################################################
! 373: # CTanalyzeReport
! 374: ###########################################################
! 375: ###########################################################
! 376: ###########################################################
! 377: proc CTanalyzeReport { num } {
! 378: global gUniqueNumber gCT gFile
! 379:
! 380: set cmdnum [incr gUniqueNumber]
! 381: set gCT(cmd.$cmdnum) analyzereport
! 382:
! 383: set reportFile [tk_getOpenFile -title "Please select the Report file" \
! 384: -filetypes { {{Capa Reports} {*.rpt}} {{All Files} {*}} }]
! 385: if { $reportFile == "" } { return }
! 386: set percentage [tk_dialog $gCT($num).dialog "How would you like scores displayed?" \
! 387: "How would you like scores displayed?" "" "" "Points Earned" \
! 388: "Percentage" "Cancel"]
! 389: if { $percentage == 2 } { return }
! 390: set pwd [pwd];cd $gFile($num)
! 391: set sectionList [pickSections [getExistingSections] "Select Sections To Analyze:" $gCT($num) ]
! 392: CTdatestamp $cmdnum
! 393: CTputs $cmdnum "Analyzing Report File $reportFile\n"
! 394: CTputs $cmdnum " For Sections $sectionList\n"
! 395: CTputs $cmdnum " Report Created at [clock format [file mtime $reportFile]]\n"
! 396: cd $pwd
! 397: set scorelist [CTreportDist $cmdnum $reportFile $percentage $sectionList]
! 398: set label [lindex "{Grade} {Grade(%)}" $percentage]
! 399: set ptsearned 0
! 400: set totalnumstu 0
! 401: foreach element $scorelist {
! 402: set numstu [lindex $element 0]
! 403: set score [lindex $element 1]
! 404: set ptsearned [expr $ptsearned + ($numstu*$score)]
! 405: incr totalnumstu $numstu
! 406: }
! 407: set average [expr $ptsearned / double($totalnumstu)]
! 408: set avgmsg [format "Average: %.2f" $average]
! 409: CTputs $cmdnum $avgmsg\n
! 410: CTbargraph $gCT($num) $num $cmdnum $scorelist $gFile($num) "Score Distribution for [file tail $reportFile] $avgmsg" $label "\# Students" SCP
! 411: unset gCT(cmd.$cmdnum)
! 412: CToutput $num $cmdnum
! 413: }
! 414:
! 415: ###########################################################
! 416: # CTanalyzeScorer
! 417: ###########################################################
! 418: ###########################################################
! 419: ###########################################################
! 420: proc CTanalyzeScorer { num } {
! 421: global gFile gUniqueNumber gCapaConfig gCT
! 422: set cmdnum [incr gUniqueNumber]
! 423: set gCT(cmd.$cmdnum) analyzescorer
! 424: if { "" == [set file [tk_getOpenFile -title "Pick a scorer.output file" -filetypes { { {scorer.output} {scorer.output.*} } { {Submissions File} {*submissions*.db} } { {All Files} {*} } }]] } { return }
! 425: set path [file dirname [file dirname $file]]
! 426: if { "" == [set gCT($cmdnum.questNum) [getString $gCT($num) "Which questions?"]]} {
! 427: return
! 428: }
! 429: set gCT($cmdnum.max) [lindex [exec wc -l $file] 0]
! 430: set gCT($cmdnum.done) 1
! 431: set gCT($cmdnum.graphup) 0
! 432: set gCT($cmdnum.num) $num
! 433: displayStatus "Getting student reponses" both $cmdnum
! 434: set gCT($cmdnum.fileId) [open $file r]
! 435: if { [regexp {scorer\.output\.([0-9]|([0-9][0-9]))} $file] } {
! 436: set gCT($cmdnum.setId) [string range [file extension $file] 1 end]
! 437: set gCT($cmdnum.parse) CTparseScorerOutputLine
! 438: set aline [gets $gCT($cmdnum.fileId)]
! 439: } else {
! 440: set gCT($cmdnum.setId) [lindex [split [file tail $file] s.] 4]
! 441: set gCT($cmdnum.parse) CTparseSubmissionsLine
! 442: }
! 443: set aline [gets $gCT($cmdnum.fileId)]
! 444: $gCT($cmdnum.parse) $aline $cmdnum
! 445: set pwd [pwd];cd $path
! 446: getSet $gCT($cmdnum.question) $gCT($cmdnum.setId) "CTcontinueAnalyze $cmdnum $path"
! 447: cd $pwd
! 448: }
! 449:
! 450: proc CTcontinueAnalyze { num path arrayVar } {
! 451: global gCT gResponse
! 452: upvar $arrayVar question
! 453: CTgetQuestions $num question
! 454: set numAdded 0
! 455: foreach which $gCT($num.questNum) {
! 456: incr numAdded [CTgetStudentResponses $num [lindex $gCT($num.response) \
! 457: [expr $which-1]] $which \
! 458: question]
! 459: }
! 460: updateStatusBar [expr $gCT($num.done)/double($gCT($num.max))] $num
! 461: if { $numAdded > 0 } { CTupdateAnalyzeScorer $num }
! 462: set interesting 0
! 463: while {!$interesting} {
! 464: incr gCT($num.done)
! 465: set stunum $gCT($num.question)
! 466: set aline [gets $gCT($num.fileId)]
! 467: if { [eof $gCT($num.fileId)] } { CTfinishAnalyzeScorer $num; return }
! 468: set interesting [$gCT($num.parse) $aline $num]
! 469: }
! 470: if { $stunum != $gCT($num.question) } {
! 471: set pwd [pwd];cd $path
! 472: getSet $gCT($num.question) $gCT($num.setId) "CTcontinueAnalyze $num $path"
! 473: cd $pwd
! 474: } else {
! 475: CTcontinueAnalyze $num $path question
! 476: }
! 477: }
! 478:
! 479: proc CTupdateAnalyzeScorer { cmdnum } {
! 480: global gCT gResponse gUniqueNumber gFile
! 481: set num $gCT($cmdnum.num)
! 482: set i 0
! 483: foreach correct [array names gResponse "$cmdnum.correct.*"] {
! 484: set probnum [lindex [split $correct .] 2]
! 485: set answer [join [lrange [split $correct .] 3 end] .]
! 486: if { $gResponse($correct) } {
! 487: set color($probnum.$answer) green
! 488: } else {
! 489: set color($probnum.$answer) red
! 490: }
! 491: }
! 492: set results ""
! 493: set oldprobnum [lindex [split [lindex [lsort [array names gResponse $cmdnum.\[0-9\]*]] 0] .] 1]
! 494: foreach response [lsort -dictionary [array names gResponse $cmdnum.\[0-9\]*]] {
! 495: incr i
! 496: set probnum [lindex [split $response .] 1]
! 497: if { $probnum > $oldprobnum } {
! 498: set oldprobnum $probnum
! 499: lappend results [list 0 0 "Problem Divider" white]
! 500: }
! 501: set answer [join [lrange [split $response .] 2 end] .]
! 502: lappend results [list $gResponse($response) $i $answer $color($probnum.$answer)]
! 503: }
! 504: if { $results == "" } { return }
! 505: if { $gCT($cmdnum.graphup)} {
! 506: CTchangeBargraphData $cmdnum $results
! 507: } else {
! 508: CTbargraph $gCT($num) $num $cmdnum $results $gFile($num) "Reponse Distribution" "Which Response" "\#Picked" "Showresponse"
! 509: set gCT($cmdnum.graphup) 1
! 510: }
! 511:
! 512: update idletasks
! 513: }
! 514:
! 515: proc CTsaveAnalyzeScorer { num cmdnum } {
! 516: global gResponse gCT gFile
! 517: set file [tk_getSaveFile -initialdir $gFile($num)]
! 518: set fileId [open $file w]
! 519: puts $fileId [array get gResponse "$cmdnum.*"]
! 520: close $fileId
! 521: }
! 522:
! 523: proc CTfinishAnalyzeScorer { cmdnum } {
! 524: global gCT gResponse gUniqueNumber gFile
! 525:
! 526: set num $gCT($cmdnum.num)
! 527: set i 0
! 528: removeStatus $cmdnum
! 529: foreach correct [array names gResponse "$cmdnum.correct.*"] {
! 530: set probnum [lindex [split $correct .] 2]
! 531: set answer [join [lrange [split $correct .] 3 end] .]
! 532: if { $gResponse($correct) } {
! 533: set color($probnum.$answer) green
! 534: } else {
! 535: set color($probnum.$answer) red
! 536: }
! 537: }
! 538: foreach response [lsort -dictionary [array names gResponse $cmdnum.\[0-9\]*]] {
! 539: incr i
! 540: set probnum [lindex [split $response .] 1]
! 541: set answer [join [lrange [split $response .] 2 end] .]
! 542: lappend results($probnum) [list $gResponse($response) $i $answer $color($probnum.$answer)]
! 543: }
! 544: foreach probnum [lsort -dictionary [array names results]] {
! 545: CTputs $cmdnum "\nFor Problem $probnum #, Responses:\n"
! 546: foreach response $results($probnum) {
! 547: CTputs $cmdnum "[lindex $response 0], [lindex $response 2]\n"
! 548: }
! 549: }
! 550: if { "Yes" ==[makeSure "Would you like to save the results to a file?"] } {
! 551: CTsaveAnalyzeScorer $num $cmdnum
! 552: }
! 553: unset gCT(cmd.$cmdnum)
! 554: CToutput $num $cmdnum
! 555: }
! 556:
! 557: proc CTparseScorerOutputLine { aline num } {
! 558: global gCT
! 559: set gCT($num.stunum) [lindex $aline 0]
! 560: set aline [string range $aline 40 end]
! 561: set length [llength [split [lrange $aline 3 end] ,] ]
! 562: set gCT($num.response) [lrange [split [lrange $aline 3 end] ,] 0 \
! 563: [expr {$length-2}]]
! 564: set gCT($num.question) [lindex [lindex [split $aline ,] end] 0]
! 565: return 1
! 566: }
! 567:
! 568: proc CTparseSubmissionsLine { aline num } {
! 569: global gCT
! 570: set aline [split $aline \t]
! 571: set gCT($num.stunum) [lindex $aline 0]
! 572: set gCT($num.question) $gCT($num.stunum)
! 573: set gCT($num.response) ""
! 574: set interesting 0
! 575: set current 1
! 576: foreach {quest response} [lrange $aline 2 end] {
! 577: if { $quest == "" } break
! 578: while { $quest > $current } {
! 579: lappend gCT($num.response) {}
! 580: incr current
! 581: }
! 582: if { [lsearch $gCT($num.questNum) $quest] != -1} { set interesting 1 }
! 583: lappend gCT($num.response) [string toupper $response]
! 584: incr current
! 585: }
! 586: return $interesting
! 587: }
! 588:
! 589: proc CTgetQuestions { num questionVar } {
! 590: global gCT
! 591: upvar $questionVar question
! 592: # parray question
! 593: foreach quest $gCT($num.questNum) {
! 594: foreach line $question($quest.quest) {
! 595: if { [regexp {^ *([A-Z])\)(.*)} $line temp letter rest] } {
! 596: set question($quest.$letter) $rest
! 597: if { [string first $letter $question($quest.ans)] != -1} {
! 598: set question($quest.correct.$letter) 1
! 599: set question($quest.$letter) "$rest - Correct"
! 600: } else {
! 601: set question($quest.correct.$letter) 0
! 602: set question($quest.$letter) "$rest - Incorrect"
! 603: }
! 604: }
! 605: }
! 606: }
! 607: }
! 608:
! 609: proc CTgetStudentResponses { num responses which questionVar } {
! 610: global gCT gResponse
! 611: upvar $questionVar question
! 612: # parray question
! 613: set i 0
! 614: foreach response [split $responses {}] {
! 615: if { $response == "" || $response == " "} { continue }
! 616: incr i
! 617: if { [catch {incr gResponse($num.$which.$question($which.$response))}] } {
! 618: if {[catch {set gResponse($num.$which.$question($which.$response)) 1}]} {
! 619: #set gResponse($num.$which.Illegal\ Bubble) 1
! 620: puts "not an option $response $which"
! 621: continue
! 622: }
! 623: }
! 624: if { $question($which.correct.$response) } {
! 625: set gResponse($num.correct.$which.$question($which.$response)) 1
! 626: } else {
! 627: set gResponse($num.correct.$which.$question($which.$response)) 0
! 628: }
! 629: }
! 630: return $i
! 631: }
! 632:
! 633: ###########################################################
! 634: # CTgraphAnalyzeScorer
! 635: ###########################################################
! 636: ###########################################################
! 637: ###########################################################
! 638: proc CTgraphAnalyzeScorer { num } {
! 639: global gFile gUniqueNumber gCapaConfig gCT gResponse
! 640: set cmdnum [incr gUniqueNumber]
! 641: set gCT(cmd.$cmdnum) graphanalyzescorer
! 642: if { "" == [set file [tk_getOpenFile -title "Pick a Output file" -filetypes { { {All Files} {*} } } -initialdir $gFile($num)]] } { return }
! 643: set fileId [open $file r]
! 644: set temp [read $fileId [file size $file]]
! 645: close $fileId
! 646: foreach {name value} $temp {
! 647: set name [join "$cmdnum [lrange [split $name .] 1 end]" .]
! 648: set gResponse($name) $value
! 649: }
! 650: unset temp
! 651: foreach name [array names gResponse $cmdnum.\[0-9\]*] {
! 652: puts "[split $name .]"
! 653: puts "[lindex [split $name .] 1]"
! 654: lappend probnums [lindex [split $name .] 1]
! 655: }
! 656: set probnums [lsort [lunique $probnums]]
! 657: event generate . <1> -x 1 -y 1
! 658: event generate . <ButtonRelease-1>
! 659: if { "" == [set probnums [multipleChoice $gCT($num) "Select which problems" $probnums 0]] } { return }
! 660: foreach name [array names gResponse $cmdnum.\[0-9\]*] {
! 661: set probnum [lindex [split $name .] 1]
! 662: if { -1 == [lsearch $probnums $probnum] } {
! 663: set answer [join [lrange [split $name .] 2 end] .]
! 664: unset gResponse($name)
! 665: unset gResponse($cmdnum.correct.$probnum.$answer)
! 666: }
! 667: }
! 668: set gCT($cmdnum.num) $num
! 669: set gCT($cmdnum.graphup) 0
! 670: CTupdateAnalyzeScorer $cmdnum
! 671: unset gCT(cmd.$cmdnum)
! 672: }
! 673:
! 674: ###########################################################
! 675: # CTquit
! 676: ###########################################################
! 677: ###########################################################
! 678: ###########################################################
! 679: proc CTquit { num } {
! 680: global gCT
! 681: destroy $gCT($num)
! 682: }
! 683:
! 684: #menu command helpers
! 685: ###########################################################
! 686: # CTscanSetDB
! 687: ###########################################################
! 688: ###########################################################
! 689: ###########################################################
! 690: proc CTscanSetDB { num file Q_cntVar L_cntVar } {
! 691: global gMaxSet gTotal_try gYes_cnt gyes_cnt gStudent_cnt gStudent_try \
! 692: gTotal_weight gTotal_scores gEntry gScore gNewStudent_cnt
! 693: upvar $Q_cntVar Q_cnt
! 694: upvar $L_cntVar L_cnt
! 695:
! 696: set line_cnt 0
! 697: set valid_cnt 0
! 698:
! 699: for { set ii 0 } { $ii <= $gMaxSet } { incr ii } {
! 700: set gTotal_try($num.$ii) 0
! 701: set gYes_cnt($num.$ii) 0
! 702: set gyes_cnt($num.$ii) 0
! 703: for { set jj 0 } { $jj <= $gMaxSet } { incr jj } {
! 704: set gStudent_cnt($num.$ii.$jj) 0
! 705: set gStudent_try($num.$ii.$jj) 0
! 706: }
! 707: set gNewStudent_cnt($num.$ii) 0
! 708: }
! 709: set gTotal_weight($num) 0
! 710: set gTotal_scores($num) 0
! 711:
! 712: set maxLine [lindex [exec wc $file] 0]
! 713: set tries ""
! 714: set fileId [open $file "r"]
! 715: set aline [gets $fileId]
! 716: while { ! [eof $fileId] } {
! 717: incr line_cnt
! 718: if { ($line_cnt%20) == 0 } {
! 719: updateStatusBar [expr $line_cnt/double($maxLine)] $num
! 720: }
! 721: if { $line_cnt == 2 } {
! 722: set aline [string trim $aline]
! 723: set weight [split $aline {}]
! 724: }
! 725: if { $line_cnt > 3 } {
! 726: catch {
! 727: set aline [string trim $aline]
! 728: set prefix [lindex [split $aline ,] 0]
! 729: set s_num [lindex [split $aline " "] 0]
! 730: set ans_str [lindex [split $prefix " "] 1]
! 731: set ans_char [split $ans_str {} ]
! 732: set tries [lrange [split $aline ,] 1 end]
! 733: for { set valid 0; set ii 0 } { $ii < [llength $ans_char] } { incr ii } {
! 734: if {([lindex $ans_char $ii] != "-")&&([lindex $ans_char $ii] != "E")
! 735: && ([lindex $ans_char $ii] != "e") } { set valid 1 }
! 736: }
! 737: if { $valid } {
! 738: for {set score 0; set ii 0} { $ii < [llength $tries] } { incr ii } {
! 739: set triesii 0
! 740: incr gTotal_weight($num) [lindex $weight $ii]
! 741: if { [lindex $ans_char $ii] == "Y" } {
! 742: set triesii [string trim [lindex $tries $ii]]
! 743: incr gYes_cnt($num.$ii)
! 744: incr score [lindex $weight $ii]
! 745: incr gNewStudent_cnt($num.$ii)
! 746: } elseif { [lindex $ans_char $ii] == "y" } {
! 747: set triesii [string trim [lindex $tries $ii]]
! 748: incr triesii
! 749: incr gyes_cnt($num.$ii)
! 750: incr score [lindex $weight $ii]
! 751: incr gNewStudent_cnt($num.$ii)
! 752: } elseif { ( [lindex $ans_char $ii] > 0 ) && \
! 753: ( [lindex $ans_char $ii] <= 9) } {
! 754: set triesii [string trim [lindex $tries $ii]]
! 755: incr score [lindex $ans_char $ii]
! 756: incr gYes_cnt($num.$ii)
! 757: incr gNewStudent_cnt($num.$ii)
! 758: } elseif { ( [lindex $ans_char $ii] == 0 ) } {
! 759: set triesii [string trim [lindex $tries $ii]]
! 760: incr gNewStudent_cnt($num.$ii)
! 761: } elseif {([lindex $ans_char $ii]=="n") || \
! 762: ([lindex $ans_char $ii]=="N")} {
! 763: set triesii [string trim [lindex $tries $ii]]
! 764: if { [lindex $ans_char $ii] == "n" } { incr triesii }
! 765: incr gNewStudent_cnt($num.$ii)
! 766: }
! 767: set gStudent_try($num.$valid_cnt.$ii) $triesii
! 768: incr gTotal_try($num.$ii) $triesii
! 769: incr gStudent_cnt($num.$ii.$triesii)
! 770: }
! 771: incr gTotal_scores($num) $score
! 772: set gEntry($num.$valid_cnt) "$aline"
! 773: set gScore($num.$valid_cnt) $score
! 774: incr valid_cnt
! 775: }
! 776: }
! 777: }
! 778: set aline [gets $fileId]
! 779: }
! 780: close $fileId
! 781: set Q_cnt [llength $tries]
! 782: set L_cnt $valid_cnt
! 783: return
! 784: }
! 785:
! 786: ###########################################################
! 787: # CTpercentageScores
! 788: ###########################################################
! 789: ###########################################################
! 790: ###########################################################
! 791: proc CTpercentageScores { num setId valid_cnt } {
! 792: global gTotal_weight gTotal_scores
! 793:
! 794: if { $gTotal_weight($num) > 0 } {
! 795: set ratio [expr double($gTotal_scores($num)) / double($gTotal_weight($num))]
! 796: set ratio [expr $ratio * 100.0 ]
! 797: CTputs $num "\nScore (total scores / total valid weights) for set$setId.db: [format %7.2f%% $ratio]\n"
! 798: }
! 799: CTputs $num "The number of valid records for set$setId.db is: $valid_cnt\n"
! 800: }
! 801:
! 802: ###########################################################
! 803: # CTaverage
! 804: ###########################################################
! 805: ###########################################################
! 806: ###########################################################
! 807: proc CTaverage { num q_cnt l_cnt faillistVar dodifflistVar numyesVar} {
! 808: upvar $faillistVar faillist $dodifflistVar dodifflist $numyesVar numyes
! 809: global gMaxTries gStudent_cnt gStudent_try gTotal_try gYes_cnt gyes_cnt \
! 810: gNewStudent_cnt
! 811:
! 812: set maxIter [expr $q_cnt * 4]
! 813:
! 814: for { set ii 0 } { $ii < $q_cnt } { incr ii } {
! 815: updateStatusBar [expr $ii/double($maxIter)] $num
! 816: set s_cnt($ii) 0
! 817: set avg($ii) 0.0
! 818: set max_try($ii) 0
! 819: for { set jj 1 } { $jj < $gMaxTries } { incr jj } {
! 820: if { $gStudent_cnt($num.$ii.$jj) > 0 } {
! 821: set avg($ii) [expr $avg($ii) + ($jj * $gStudent_cnt($num.$ii.$jj))]
! 822: incr s_cnt($ii) $gStudent_cnt($num.$ii.$jj)
! 823: }
! 824: }
! 825: set s_cnt($ii) $gNewStudent_cnt($num.$ii)
! 826: if { $s_cnt($ii) > 0 } { set avg($ii) [expr $avg($ii) / $s_cnt($ii)] }
! 827: }
! 828:
! 829: for { set ii 0 } { $ii < $q_cnt } { incr ii } {
! 830: updateStatusBar [expr ($ii+$q_cnt)/double($maxIter)] $num
! 831: set sd($ii) 0.0
! 832: set sum 0.0
! 833: for { set jj 0 } { $jj < $l_cnt } { incr jj } {
! 834: if { $gStudent_try($num.$jj.$ii) > $max_try($ii) } {
! 835: set max_try($ii) $gStudent_try($num.$jj.$ii)
! 836: }
! 837: if { $gStudent_try($num.$jj.$ii) > 0 } {
! 838: set sq [expr ( $gStudent_try($num.$jj.$ii) - $avg($ii) ) * \
! 839: ( $gStudent_try($num.$jj.$ii) - $avg($ii)) ]
! 840: set sum [expr $sum + $sq]
! 841: }
! 842: if { $s_cnt($ii) > 1 } {
! 843: set sd($ii) [expr $sum / ( $s_cnt($ii) - 1.0 )]
! 844: }
! 845: if { $sd($ii) > 0 } { set sd($ii) [ expr sqrt($sd($ii)) ] }
! 846: }
! 847: }
! 848:
! 849: for { set ii 0 } { $ii < $q_cnt } { incr ii } {
! 850: updateStatusBar [expr ($ii+(2*$q_cnt))/double($maxIter)] $num
! 851: set sd3($ii) 0.0
! 852: set sum 0.0
! 853: for { set jj 0 } { $jj < $l_cnt } { incr jj } {
! 854: if { $gStudent_try($num.$jj.$ii) > 0 } {
! 855: set tmp1 [expr $gStudent_try($num.$jj.$ii) - $avg($ii)]
! 856: set tmp2 [expr $tmp1 * $tmp1 * $tmp1]
! 857: set sum [expr $sum + $tmp2]
! 858: }
! 859: if { ( $s_cnt($ii) > 0 ) && ( $sd($ii) != 0.0 ) } {
! 860: set sd3($ii) [expr $sum / $s_cnt($ii) ]
! 861: set sd3($ii) [expr $sd3($ii) / ($sd($ii) * $sd($ii) * $sd($ii)) ]
! 862: }
! 863: }
! 864: }
! 865: CTputs $num "This is the statistics for each problem: \n"
! 866: CTputs $num "Prob\# MxTries avg. s.d. s.k. \#Stdnts"
! 867: CTputs $num " \#Yes \#yes Tries DoDiff %Wrong\n"
! 868: set numyes [set dodifflist [set faillist ""]]
! 869: # parray s_cnt
! 870: for { set ii 0 } { $ii < $q_cnt } { incr ii } {
! 871: updateStatusBar [expr ($ii+(3*$q_cnt))/double($maxIter)] $num
! 872: if { $gTotal_try($num.$ii) > 0 } {
! 873: set dod [expr $gTotal_try($num.$ii)/(0.1 + $gYes_cnt($num.$ii) \
! 874: + $gyes_cnt($num.$ii))]
! 875: } else {
! 876: set dod 0.0
! 877: }
! 878: if {[catch {set success [expr 100.0*($s_cnt($ii)-($gYes_cnt($num.$ii)+ \
! 879: $gyes_cnt($num.$ii)))/$s_cnt($ii)]}]} {
! 880: set success 0.0
! 881: set s_cnt($ii) 0
! 882: }
! 883: CTputs $num [format "P %2d" [expr int($ii + 1)] ]
! 884: CTputs $num [format "%6d %8.2f %7.2f %6.2f %5d %5d %5d %5d %5.1f %6.2f\n"\
! 885: $max_try($ii) $avg($ii) $sd($ii) $sd3($ii) $s_cnt($ii) \
! 886: $gYes_cnt($num.$ii) $gyes_cnt($num.$ii) \
! 887: $gTotal_try($num.$ii) $dod $success]
! 888: if { $success < 0 } { set success 0 }
! 889: lappend faillist [list $success [expr int($ii + 1)]]
! 890: lappend dodifflist [list $dod [expr int($ii + 1)]]
! 891: lappend numyes [list [expr $gYes_cnt($num.$ii)+$gyes_cnt($num.$ii)] \
! 892: [expr int($ii + 1)]]
! 893: }
! 894: }
! 895:
! 896: ###########################################################
! 897: # CTlogAnalysis2
! 898: ###########################################################
! 899: ###########################################################
! 900: ###########################################################
! 901: proc CTlogAnalysis2 { num cmdnum setId } {
! 902: global gFile
! 903: set logFile [file join $gFile($num) records "log$setId.db"]
! 904: if { [file exists $logFile] } {
! 905: CTputs $cmdnum "Log analysis for telnet session log$setId.db\n"
! 906: CTscanLogDB $cmdnum $logFile l(Y) l(N) l(S) l(U) l(u)
! 907: } else {
! 908: set l(Y) [set l(N) [set l(S) [set l(U) [set l(u) 0]]]]
! 909: }
! 910: set webLogFile [file join $gFile($num) records "weblog$setId.db" ]
! 911: if { [file exists $webLogFile] } {
! 912: CTputs $cmdnum "===============================================\n"
! 913: CTputs $cmdnum "Log analysis for web session weblog$setId.db\n"
! 914: CTscanLogDB $cmdnum $webLogFile w(Y) w(N) w(S) w(U) w(u)
! 915: } else {
! 916: set w(Y) [set w(N) [set w(S) [set w(U) [set w(u) 0]]]]
! 917: }
! 918: set telnet_total [expr $l(Y)+$l(N)+$l(S)+$l(U)+$l(u)]
! 919: set web_total [expr $w(Y)+$w(N)+$w(S)+$w(U)+$w(u)]
! 920: CTputs $cmdnum "============== SUMMARY ====================\n"
! 921: CTputs $cmdnum " #Y #N #S #U #u Total\n"
! 922: CTputs $cmdnum [format "telnet: %6d %6d %6d %6d %6d %6d\n" \
! 923: $l(Y) $l(N) $l(S) $l(U) $l(u) $telnet_total ]
! 924: CTputs $cmdnum [format " web: %6d %6d %6d %6d %6d %6d\n" \
! 925: $w(Y) $w(N) $w(S) $w(U) $w(u) $web_total]
! 926: foreach v { Y N S U u } {
! 927: set sum($v) [expr $l($v) + $w($v)]
! 928: if { $sum($v) > 0 } {
! 929: set ratio($v) [expr 100.0*$w($v)/double($sum($v))]
! 930: } else {
! 931: set ratio($v) 0.0
! 932: }
! 933: }
! 934: set overall_entries [expr $telnet_total + $web_total]
! 935: if { $overall_entries > 0 } {
! 936: set ratio(web) [expr 100.0*(double($web_total)/double($overall_entries))]
! 937: } else {
! 938: set ratio(web) 0.0
! 939: }
! 940: CTputs $cmdnum [format " %%web: % 6.1f % 6.1f % 6.1f % 6.1f % 6.1f % 6.1f\n" \
! 941: $ratio(Y) $ratio(N) $ratio(S) $ratio(U) $ratio(u) $ratio(web) ]
! 942: }
! 943:
! 944:
! 945: ###########################################################
! 946: # CTscanLogDB
! 947: ###########################################################
! 948: ###########################################################
! 949: ###########################################################
! 950: proc CTscanLogDB { num file Y_lVar N_lVar S_lVar U_lVar u_lVar } {
! 951: upvar $Y_lVar Y_l
! 952: upvar $N_lVar N_l
! 953: upvar $S_lVar S_l
! 954: upvar $U_lVar U_l
! 955: upvar $u_lVar u_l
! 956:
! 957: set line_cnt 0
! 958:
! 959: displayStatus "Analyzing [file tail $file]" both $num
! 960: set maxLine [lindex [exec wc $file] 0]
! 961: set fileId [open $file "r"]
! 962:
! 963: set aline [gets $fileId]
! 964: while { ! [eof $fileId] } {
! 965: incr line_cnt
! 966: if { ($line_cnt%20) == 0 } {
! 967: updateStatusBar [expr $line_cnt/double($maxLine)] $num
! 968: }
! 969: set aline [string trim $aline]
! 970: set ans_str [string range $aline 35 end]
! 971: set ans_char [split $ans_str {}]
! 972: if { ! [info exists count] } {
! 973: for { set i 0 } { $i < [llength $ans_char] } { incr i } {
! 974: set count(Y.$i) 0; set count(N.$i) 0; set count(S.$i) 0
! 975: set count(U.$i) 0; set count(u.$i) 0
! 976: }
! 977: set count(Y.total) 0; set count(N.total) 0; set count(S.total) 0
! 978: set count(U.total) 0; set count(u.total) 0
! 979: }
! 980: set i -1
! 981: foreach char $ans_char {
! 982: incr i
! 983: if { $char == "-" } { continue }
! 984: if { [catch {incr count($char.$i)}] } {
! 985: set count(Y.$i) 0; set count(N.$i) 0; set count(S.$i) 0
! 986: set count(U.$i) 0; set count(u.$i) 0
! 987: incr count($char.$i)
! 988: }
! 989: incr count($char.total)
! 990: }
! 991: set aline [gets $fileId]
! 992: }
! 993: close $fileId
! 994: removeStatus $num
! 995: CTputs $num "Prob #: #Y #N #S #U #u\n"
! 996: for { set i 0 } { $i < [llength $ans_char] } { incr i } {
! 997: CTputs $num [format " %2d: %6d %6d %6d %6d %6d\n" [expr $i + 1] \
! 998: $count(Y.$i) $count(N.$i) $count(S.$i) $count(U.$i) $count(u.$i) ]
! 999: }
! 1000: CTputs $num "===========================================\n"
! 1001: CTputs $num [format " Total: %6d %6d %6d %6d %6d\n" $count(Y.total) $count(N.total) \
! 1002: $count(S.total) $count(U.total) $count(u.total) ]
! 1003: set Y_l $count(Y.total)
! 1004: set N_l $count(N.total)
! 1005: set S_l $count(S.total)
! 1006: set U_l $count(U.total)
! 1007: set u_l $count(u.total)
! 1008: return
! 1009: }
! 1010:
! 1011: ###########################################################
! 1012: # CTcollectSetScores
! 1013: ###########################################################
! 1014: ###########################################################
! 1015: ###########################################################
! 1016: proc CTcollectSetScores { num path id on_screen limit } {
! 1017: set id [ string toupper $id ]
! 1018: set total_scores 0
! 1019: set total_weights 0
! 1020: set set_idx 0
! 1021: set done 0
! 1022: while { ! $done } {
! 1023: incr set_idx
! 1024: if { $set_idx > $limit } { set done 1; continue }
! 1025: updateStatusBar [expr $set_idx/double($limit)] $num
! 1026: set filename [file join $path records "set$set_idx.db"]
! 1027: if { ![file readable $filename ] } { continue }
! 1028: set fileId [open $filename "r"]
! 1029: set line_cnt 0
! 1030: set found 0
! 1031: set aline [ gets $fileId ]
! 1032: while { ! [eof $fileId] && ! $found } {
! 1033: incr line_cnt
! 1034: if { $line_cnt > 3 } {
! 1035: set aline [string trim $aline]
! 1036: set prefix [lindex [split $aline ","] 0]
! 1037: set s_num [string toupper [lindex [split $aline " "] 0] ]
! 1038: set ans_str [lindex [split $prefix " "] 1]
! 1039: if { $id == $s_num } {
! 1040: set ans_char [split $ans_str {} ]
! 1041: set valid 0
! 1042: foreach char $ans_char { if { $char != "-" } { set valid 1; break } }
! 1043: if { ! $valid } {
! 1044: set score "-"
! 1045: } else {
! 1046: set score 0
! 1047: for {set i 0} { $i < [llength $ans_char] } { incr i } {
! 1048: set char [lindex $ans_char $i]
! 1049: if { $char == "N" || $char == "n"} { set found 1 }
! 1050: if { $char == "Y" || $char == "y"} {
! 1051: incr score [lindex $weights $i];set found 1
! 1052: }
! 1053: if { $char >= 0 && $char <= 9 } {
! 1054: incr score $char;set found 1
! 1055: }
! 1056: if { $char == "E" } {
! 1057: incr valid_weights "-[lindex $weights $i]"
! 1058: }
! 1059: }
! 1060: incr total_scores $score
! 1061: }
! 1062: }
! 1063: } elseif { $line_cnt == 2 } {
! 1064: set aline [string trim $aline]
! 1065: set weights [split $aline {} ]
! 1066: set valid_weights 0
! 1067: foreach weight $weights { incr valid_weights $weight }
! 1068: } else {
! 1069: #do nothing for line 1 and 3
! 1070: }
! 1071: set aline [ gets $fileId ]
! 1072: }
! 1073: close $fileId
! 1074: incr total_weights $valid_weights
! 1075: set set_weights([expr $set_idx - 1]) $valid_weights
! 1076: if { $found } {
! 1077: set set_scores([expr $set_idx - 1]) $score
! 1078: } else {
! 1079: set set_scores([expr $set_idx - 1]) "-"
! 1080: }
! 1081: }
! 1082: set abscent_cnt 0
! 1083: set present_cnt 0
! 1084: set summary_str ""
! 1085: if { $on_screen } { CTputs $num " " }
! 1086: foreach i [lsort -integer [array names set_scores]] {
! 1087: if { $set_scores($i) == "-" || $set_scores($i) == "" } {
! 1088: if { $on_screen } { CTputs $num " - " }
! 1089: append summary_str "x/$set_weights($i) "
! 1090: incr abscent_cnt
! 1091: } else {
! 1092: if { $on_screen } { CTputs $num [format " %3d" $set_scores($i)] }
! 1093: append summary_str "$set_scores($i)/$set_weights($i) "
! 1094: incr present_cnt
! 1095: }
! 1096: }
! 1097: if { $on_screen } {
! 1098: CTputs $num "\n [file tail $path]:"
! 1099: foreach i [lsort -integer [array names set_scores]] { CTputs $num " ---" }
! 1100: CTputs $num "\n "
! 1101: if { [info exists set_weights] } {
! 1102: set num_set_weights [llength [array names set_weights]]
! 1103: } else {
! 1104: set num_set_weights 0
! 1105: }
! 1106: for {set i 0} {$i < $num_set_weights} {incr i} {
! 1107: if { [info exists set_weights($i)] } {
! 1108: CTputs $num [format " %3d" $set_weights($i)]
! 1109: } else {
! 1110: set num_set_weights $i
! 1111: }
! 1112: }
! 1113: CTputs $num "\n"
! 1114: if { $total_weights != 0 } {
! 1115: set ratio [expr 100.0 * $total_scores / double($total_weights) ]
! 1116: CTputs $num [format " %5d\n" $total_scores]
! 1117: if { [info exists set_scores] } {
! 1118: CTputs $num [format " ------- = %3.2f%%, scores absent in %d/%d\n" \
! 1119: $ratio $abscent_cnt [llength [array names set_scores]]]
! 1120: } else {
! 1121: CTputs $num [format " ------- = %3.2f%%, scores absent in %d/%d\n" \
! 1122: $ratio $abscent_cnt 0 ]
! 1123: }
! 1124: } else {
! 1125: set ratio "-"
! 1126: CTputs $num [format " %5d\n" $total_scores]
! 1127: if { [info exists set_scores] } {
! 1128: CTputs $num [format " ------- = %s%%, scores absent in %d/%d\n" \
! 1129: $ratio $abscent_cnt [llength [array names set_scores]]]
! 1130: } else {
! 1131: CTputs $num [format " ------- = %s%%, scores absent in %d/%d\n" \
! 1132: $ratio $abscent_cnt 0 ]
! 1133: }
! 1134: }
! 1135:
! 1136: CTputs $num [format " %5d\n" $total_weights]
! 1137: }
! 1138: return [list $total_scores $total_weights $abscent_cnt \
! 1139: [llength [array names set_scores] ] $summary_str]
! 1140: }
! 1141:
! 1142: ###########################################################
! 1143: # CTloginAnalysis
! 1144: ###########################################################
! 1145: ###########################################################
! 1146: ###########################################################
! 1147: proc CTloginAnalysis { num path id limit } {
! 1148:
! 1149: CTputs $num "Login analysis: telnet session web session\n\n"
! 1150: CTputs $num " set #: #Y #N #S #U #u #Y #N #S #U #u\n"
! 1151: set set_idx 0
! 1152: set done 0
! 1153: while { ! $done } {
! 1154: incr set_idx
! 1155: if { $set_idx > $limit } { set done 1; continue }
! 1156: CTputs $num [format " %2d: " $set_idx]
! 1157: set filename [file join $path records "log$set_idx.db"]
! 1158: updateStatusMessage "Analyzing [file tail $filename]" $num
! 1159: updateStatusBar 0.0 $num
! 1160: if { [file readable $filename] } {
! 1161: set result [CTstudentLoginData $num $filename $id]
! 1162: CTputs $num [eval format \"%4d %4d %4d %4d %4d\" $result]
! 1163: set no_log 0
! 1164: } else {
! 1165: CTputs $num "========================"
! 1166: set no_log 1
! 1167: }
! 1168: CTputs $num " "
! 1169: set filename [file join $path records "weblog$set_idx.db"]
! 1170: updateStatusMessage "Analyzing [file tail $filename]" $num
! 1171: updateStatusBar 0.0 $num
! 1172: if { [file readable $filename] } {
! 1173: set result [CTstudentLoginData $num $filename $id]
! 1174: CTputs $num [eval format \"%4d %4d %4d %4d %4d\" $result]
! 1175: set no_weblog 0
! 1176: } else {
! 1177: CTputs $num "========================"
! 1178: set no_weblog 1
! 1179: }
! 1180: CTputs $num "\n"
! 1181: if { $no_log && $no_weblog } { set done 1 }
! 1182: }
! 1183: }
! 1184:
! 1185: ###########################################################
! 1186: # CTstudentSetAnalysis
! 1187: ###########################################################
! 1188: ###########################################################
! 1189: ###########################################################
! 1190: proc CTstudentSetAnalysis { num path id limit } {
! 1191: set set_idx 0
! 1192: set id [string toupper $id]
! 1193: CTputs $num " set \#:\n"
! 1194: set done 0
! 1195: while { ! $done } {
! 1196: incr set_idx
! 1197: if { $set_idx > $limit } { set done 1; continue }
! 1198: set filename [file join $path records "set$set_idx.db"]
! 1199: updateStatusMessage "Analyzing [file tail $filename]" $num
! 1200: if { ![file readable $filename] } { continue }
! 1201: CTputs $num [format " %2d: " $set_idx]
! 1202: set fileId [open $filename "r"]
! 1203: set line_cnt 0
! 1204: set found 0
! 1205: set aline [gets $fileId]
! 1206: while { ! [eof $fileId] && !$found } {
! 1207: incr line_cnt
! 1208: if { $line_cnt > 3 } {
! 1209: set aline [string trim $aline]
! 1210: set s_id [string toupper [string range $aline 0 8]]
! 1211: if {$id == $s_id} {
! 1212: set found 1
! 1213: set breakpt [string first "," $aline]
! 1214: set data [list [string range $aline 10 [expr $breakpt - 1] ] \
! 1215: [string range $aline [expr $breakpt + 1] end ] ]
! 1216: CTputs $num "[lindex $data 0]\n [lindex $data 1]\n"
! 1217: }
! 1218: }
! 1219: set aline [gets $fileId]
! 1220: }
! 1221: close $fileId
! 1222: if { ! $found } { CTputs $num "\n\n" }
! 1223: }
! 1224: }
! 1225:
! 1226: ###########################################################
! 1227: # CTstudentLoginData
! 1228: ###########################################################
! 1229: ###########################################################
! 1230: ###########################################################
! 1231: proc CTstudentLoginData { num filename id } {
! 1232:
! 1233: set Y_total 0
! 1234: set N_total 0
! 1235: set U_total 0
! 1236: set u_total 0
! 1237: set S_total 0
! 1238: set maxLine [expr double([lindex [exec wc $filename] 0])]
! 1239: set line_cnt 0
! 1240: set fileId [open $filename "r"]
! 1241: set aline [gets $fileId]
! 1242: while { ![eof $fileId] } {
! 1243: incr line_cnt
! 1244: if { $line_cnt%300 == 0 } {
! 1245: updateStatusBar [expr $line_cnt/$maxLine] $num
! 1246: }
! 1247: set aline [string trim $aline]
! 1248: set s_id [string toupper [string range $aline 0 8]]
! 1249: set id [string toupper $id]
! 1250: if {$id == $s_id} {
! 1251: set ans_char [split [string range $aline 35 end] {} ]
! 1252: for {set i 0} {$i< [llength $ans_char]} {incr i} {
! 1253: if {[lindex $ans_char $i] == "Y"} { incr Y_total
! 1254: } elseif {[lindex $ans_char $i] == "N"} { incr N_total
! 1255: } elseif {[lindex $ans_char $i] == "U"} { incr U_total
! 1256: } elseif {[lindex $ans_char $i] == "u"} { incr u_total
! 1257: } elseif {[lindex $ans_char $i] == "S"} { incr S_total }
! 1258: }
! 1259: }
! 1260: set aline [gets $fileId]
! 1261: }
! 1262: close $fileId
! 1263: return [list $Y_total $N_total $S_total $U_total $u_total]
! 1264: }
! 1265:
! 1266: ###########################################################
! 1267: # CTrunCommand
! 1268: ###########################################################
! 1269: ###########################################################
! 1270: ###########################################################
! 1271: proc CTrunCommand { num cmdnum fileId {followup "" }} {
! 1272: global gCT
! 1273:
! 1274: set data [read $fileId]
! 1275: updateStatusSpinner $cmdnum
! 1276: if { $data != "" } {
! 1277: CTputs $cmdnum $data
! 1278: }
! 1279: if { [eof $fileId] } {
! 1280: fileevent $fileId readable ""
! 1281: catch {close $fileId}
! 1282: if { $followup == "" } {
! 1283: CToutput $num $cmdnum
! 1284: removeStatus $cmdnum
! 1285: unset gCT(cmd.$cmdnum)
! 1286: } else {
! 1287: eval $followup
! 1288: }
! 1289: }
! 1290: }
! 1291:
! 1292: ###########################################################
! 1293: # CTitemAnalysisRange
! 1294: ###########################################################
! 1295: ###########################################################
! 1296: ###########################################################
! 1297: proc CTitemAnalysisRange { num classpath setIdStart setIdEnd } {
! 1298: for { set i $setIdStart } { $i <= $setIdEnd } { incr i } {
! 1299: if { [ catch { CTitemAnalysis $num $classpath $i } errors ] } {
! 1300: displayError $errors
! 1301: }
! 1302: }
! 1303: }
! 1304:
! 1305: ###########################################################
! 1306: # CTitemAnalysis
! 1307: ###########################################################
! 1308: ###########################################################
! 1309: ###########################################################
! 1310: proc CTitemAnalysis { num classpath setId } {
! 1311: global gMaxSet
! 1312: set done 0
! 1313:
! 1314: set total_scores 0
! 1315: set total_weights 0
! 1316: set upper_percent 0.0
! 1317: set lower_percent 0.0
! 1318:
! 1319: set Y_total 0
! 1320: set N_total 0
! 1321: for { set ii 0} { $ii<$gMaxSet } {incr ii} {
! 1322: set Y_cnt($ii) 0
! 1323: set N_cnt($ii) 0
! 1324: set Ycnt_upper($ii) 0.0
! 1325: set Ycnt_lower($ii) 0.0
! 1326: }
! 1327:
! 1328: set filename [file join $classpath records "set$setId.db"]
! 1329: if { ! [file readable $filename] } {
! 1330: CTputs $num "FILE: $filename does not exist!\n"
! 1331: return
! 1332: }
! 1333:
! 1334: displayStatus "Analyzing [file tail $filename]" both $num
! 1335: set maxLine [lindex [exec wc $filename] 0]
! 1336:
! 1337: set fileId [open "$filename" "r"]
! 1338: set valid_cnt 0
! 1339: set line_cnt 0
! 1340: set ans_char ""
! 1341: set aline [gets $fileId]
! 1342: while {![eof $fileId]} {
! 1343: incr line_cnt
! 1344: if { ($line_cnt%20) == 0 } {
! 1345: updateStatusBar [expr $line_cnt/double($maxLine)] $num
! 1346: }
! 1347: if { $line_cnt == 2 } {
! 1348: set aline [string trim $aline]
! 1349: set weights [split $aline {}]
! 1350: # set valid_weights 0
! 1351: # for { set ii 0 } { $ii < [llength $weights] } { incr ii } {
! 1352: # incr valid_weights [lindex $weights $ii]
! 1353: # }
! 1354: } elseif { $line_cnt > 3} {
! 1355: set aline [string trim $aline]
! 1356: set prefix [lindex [split $aline ","] 0]
! 1357: set s_num [string toupper [lindex [split $aline " " ] 0 ] ]
! 1358: set ans_str [lindex [split $prefix " "] 1]
! 1359: set ans_char [split $ans_str {} ]
! 1360: set valid 0
! 1361: for { set ii 0 } { $ii < [llength $ans_char] } { incr ii } {
! 1362: if { [lindex $ans_char $ii] != "-"} { set valid 1 }
! 1363: }
! 1364: if { $valid } {
! 1365: incr valid_cnt
! 1366: set score 0
! 1367: for { set ii 0 } { $ii < [llength $ans_char] } { incr ii } {
! 1368:
! 1369: if { [lindex $ans_char $ii] == "Y" || \
! 1370: [lindex $ans_char $ii] == "y" } {
! 1371: incr score [lindex $weights $ii]
! 1372: set Y_cnt($ii) [expr $Y_cnt($ii) + 1]
! 1373: set Y_total [expr $Y_total + 1]
! 1374: }
! 1375: if { [lindex $ans_char $ii] == "N" || \
! 1376: [lindex $ans_char $ii] == "n" } {
! 1377: set N_cnt($ii) [expr $N_cnt($ii) + 1]
! 1378: set N_total [expr $N_total + 1]
! 1379: }
! 1380: if { [lindex $ans_char $ii] >= 0 && \
! 1381: [lindex $ans_char $ii] <= 9 } {
! 1382: incr score [lindex $ans_char $ii]
! 1383: set yes_part [expr [lindex $ans_char $ii] / \
! 1384: double([lindex $weights $ii]) ]
! 1385: set no_part [expr 1.0 - $yes_part]
! 1386: set Y_cnt($ii) [expr $Y_cnt($ii) + $yes_part]
! 1387: set Y_total [expr $Y_total + $yes_part]
! 1388: set N_cnt($ii) [expr $N_cnt($ii) + $no_part]
! 1389: set N_total [expr $N_total + $no_part]
! 1390: }
! 1391: # if { [lindex $ans_char $ii] == "E"} {
! 1392: # incr valid_weights -[lindex $weights $ii]
! 1393: # }
! 1394: }
! 1395: set s_db([format "%08d%s" $score $s_num]) $ans_str
! 1396: }
! 1397: }
! 1398: set aline [gets $fileId]
! 1399: }
! 1400: close $fileId
! 1401: removeStatus $num
! 1402: for { set ii 0 } { $ii < $gMaxSet } { incr ii } {
! 1403: set Ycnt_upper($ii) 0
! 1404: set Ycnt_lower($ii) 0
! 1405: }
! 1406: displayStatus "Pondering data . . ." spinner $num
! 1407: set upperpart_cnt [expr int(0.27 * double($valid_cnt))]
! 1408: set lowerpart_limit [expr $valid_cnt - $upperpart_cnt]
! 1409: set line_cnt 0
! 1410: foreach sort_key [lsort -decreasing [array names s_db]] {
! 1411: incr line_cnt
! 1412: if { ($line_cnt%20) == 0 } { updateStatusSpinner $num }
! 1413: set ans_str $s_db($sort_key)
! 1414: set ans_char [split $ans_str {} ]
! 1415: for { set ii 0 } { $ii < [llength $ans_char] } { incr ii } {
! 1416: if { [lindex $ans_char $ii] == "Y" || \
! 1417: [lindex $ans_char $ii] == "y" || \
! 1418: [lindex $ans_char $ii] == [lindex $weights $ii] } {
! 1419: if { $line_cnt <= $upperpart_cnt } {
! 1420: incr Ycnt_upper($ii)
! 1421: } elseif { $line_cnt > $lowerpart_limit } {
! 1422: incr Ycnt_lower($ii)
! 1423: }
! 1424: }
! 1425: }
! 1426: }
! 1427: CTputs $num " There are $valid_cnt entries in file $filename\n"
! 1428: CTputs $num [format " The upper 27%% has %d records, the lower 27%% has %d records\n"\
! 1429: $upperpart_cnt [expr $valid_cnt - $lowerpart_limit] ]
! 1430: CTputs $num " question \# DoDiff. Disc. Factor (%upper - %lower) \[\#records,\#records\]\n";
! 1431:
! 1432: for { set ii 0 } { $ii < [llength $ans_char] } { incr ii } {
! 1433: updateStatusSpinner $num
! 1434: set tmp_total [expr $N_cnt($ii) + $Y_cnt($ii)]
! 1435: if { $tmp_total > 0 } {
! 1436: set diff [expr 100.0*($N_cnt($ii) / double($N_cnt($ii) + $Y_cnt($ii)))]
! 1437: } else {
! 1438: set diff "-"
! 1439: }
! 1440: set upper_percent [expr 100.0 * ($Ycnt_upper($ii) /double($upperpart_cnt))]
! 1441: set lower_percent [expr 100.0 * ($Ycnt_lower($ii) /double($upperpart_cnt))]
! 1442: set disc [expr $upper_percent - $lower_percent]
! 1443: CTputs $num [format " %2d: " [expr $ii + 1]]
! 1444: CTputs $num [format "%6.1f %5.1f (%6.1f - %6.1f) \[%8d,%8d\]\n" \
! 1445: $diff $disc $upper_percent $lower_percent $Ycnt_upper($ii) \
! 1446: $Ycnt_lower($ii) ]
! 1447: }
! 1448: removeStatus $num
! 1449: }
! 1450:
! 1451: ###########################################################
! 1452: # CTitemCorrelation
! 1453: ###########################################################
! 1454: # INPUTS: class name with full path, set number
! 1455: #
! 1456: # r = \frac{\sum{x_i y_i} - \frac{(\sum x_i)(\sum y_i)}{n}}
! 1457: # {\sqrt{(\sum x_i^2 - \frac{}{}}}
! 1458: #
! 1459: # corr = (sum of prod_xy - (sum_x*sum_y / n) ) / sqrt( (sum of sqr_x - (sum_x*sum_x/n))*
! 1460: #
! 1461: ###########################################################
! 1462: ###########################################################
! 1463: proc CTitemCorrelation { num classpath setId } {
! 1464: global gMaxSet
! 1465:
! 1466: set filename [file join $classpath records "set$setId.db"]
! 1467: if { ! [file readable $filename] } {
! 1468: CTputs $num "FILE: $filename does not exist!\n"
! 1469: return
! 1470: }
! 1471:
! 1472: displayStatus "Analyzing [file tail $filename]" both $num
! 1473: set maxLine [lindex [exec wc $filename] 0]
! 1474:
! 1475: set initialized 0
! 1476: set question_cnt 0
! 1477: set fileId [open "$filename" "r"]
! 1478: set line_cnt 0
! 1479: set aline [gets $fileId]
! 1480: while {![eof $fileId]} {
! 1481: incr line_cnt
! 1482: if { ($line_cnt%20) == 0 } {
! 1483: updateStatusBar [expr {$line_cnt/double($maxLine)}] $num
! 1484: }
! 1485: if { $line_cnt == 2 } {
! 1486: set aline [string trim $aline]
! 1487: set weights [split $aline {}]
! 1488: }
! 1489: if { $line_cnt > 3} {
! 1490: set aline [string trim $aline]
! 1491: set data [string range $aline 10 end]
! 1492: set ans_str [lindex [split $data ","] 0]
! 1493: set ans_char_list [split $ans_str {} ]
! 1494: set try_str [string range $aline [expr {[string first "," $data] +1}] end ]
! 1495: set question_cnt [llength $ans_char_list]
! 1496: for { set ii 0 } { $ii < $question_cnt } { incr ii } {
! 1497: set ans_char($ii) [lindex $ans_char_list $ii]
! 1498: }
! 1499: if { $question_cnt > $initialized } {
! 1500: for {set ii 0} {$ii < [expr {$question_cnt - 1}]} {incr ii} {
! 1501: set start [expr {($initialized>($ii+1)) ? $initialized : ($ii+1)}]
! 1502: for { set jj $start } { $jj < $question_cnt } { incr jj } {
! 1503: set index_key "$ii.$jj"
! 1504: set prod_xy($index_key) 0.0
! 1505: set sum_x($index_key) 0
! 1506: set sum_y($index_key) 0
! 1507: set sum_x2($index_key) 0
! 1508: set sum_y2($index_key) 0
! 1509: set valid_cnt($index_key) 0
! 1510: }
! 1511: }
! 1512: set initialized $question_cnt
! 1513: }
! 1514: for { set ii 0 } { $ii < [expr {$question_cnt - 1}] } { incr ii } {
! 1515: for { set jj [expr {$ii+1}] } { $jj < $question_cnt } { incr jj } {
! 1516: set index_key "$ii.$jj"
! 1517: if { $ans_char($ii) != "-" && $ans_char($ii) != "E" && \
! 1518: $ans_char($jj) != "-" && $ans_char($jj) != "E" } {
! 1519: ## $ans_char($ii) is one of 0 .. 9, Y, y, N, n
! 1520: ## $ans_char($jj) is one of 0 .. 9, Y, y, N, n
! 1521: if { $ans_char($ii) == "Y" || $ans_char($ii) == "y" } {
! 1522: set x_data [lindex $weights $ii]
! 1523: } elseif { $ans_char($ii) == "N" || $ans_char($ii) == "n" } {
! 1524: set x_data 0
! 1525: } else { ## must be in 0 .. 9
! 1526: set x_data $ans_char($ii)
! 1527: }
! 1528: if { $ans_char($jj) == "Y" || $ans_char($jj) == "y" } {
! 1529: set y_data [lindex $weights $jj]
! 1530: } elseif { $ans_char($jj) == "N" || $ans_char($jj) == "n" } {
! 1531: set y_data 0
! 1532: } else { ## must be in 0 .. 9
! 1533: set y_data $ans_char($jj)
! 1534: }
! 1535: set prod_xy($index_key) [expr {$x_data * $y_data +
! 1536: $prod_xy($index_key)} ]
! 1537: incr sum_x($index_key) $x_data
! 1538: incr sum_y($index_key) $y_data
! 1539: incr sum_x2($index_key) [expr {$x_data * $x_data}]
! 1540: incr sum_y2($index_key) [expr {$y_data * $y_data}]
! 1541: incr valid_cnt($index_key) 1
! 1542: }
! 1543: }
! 1544: }
! 1545: }
! 1546: set aline [gets $fileId]
! 1547: }
! 1548: close $fileId
! 1549: removeStatus $num
! 1550: # print out the correlation matrix
! 1551: # parray sum_x
! 1552: # parray sum_y
! 1553: # parray prod_xy
! 1554: CTputs $num " "
! 1555: for { set ii 1 } { $ii < $question_cnt } { incr ii } {
! 1556: CTputs $num [format " %2d" [expr {$ii+1}] ]
! 1557: }
! 1558: CTputs $num "\n"
! 1559: # --------------------------------------
! 1560: for { set ii 0 } { $ii < [expr {$question_cnt -1}] } { incr ii } {
! 1561: CTputs $num [format " %2d:" [expr {$ii+1}] ]
! 1562: for { set jj 0 } { $jj < $ii } { incr jj } { CTputs $num " " }
! 1563: for { set jj [expr {$ii+1}] } { $jj < $question_cnt } { incr jj } {
! 1564: set index_key "$ii.$jj"
! 1565: if { $valid_cnt($index_key) != "0" } {
! 1566: set upper_part [ expr { $prod_xy($index_key) -
! 1567: ( ($sum_x($index_key) * $sum_y($index_key))
! 1568: / double($valid_cnt($index_key)))}]
! 1569: set lower_part [expr {$sum_x2($index_key) -
! 1570: ($sum_x($index_key) * $sum_x($index_key)
! 1571: / double($valid_cnt($index_key)))} ]
! 1572: set lower_part [expr {$lower_part * ($sum_y2($index_key) -
! 1573: ($sum_y($index_key) *
! 1574: $sum_y($index_key)
! 1575: /double($valid_cnt($index_key))))}]
! 1576: set lower_part [expr {sqrt($lower_part)}]
! 1577: if { $lower_part != 0.0 } {
! 1578: set ratio [expr {$upper_part / double($lower_part)}]
! 1579: CTputs $num [format " % .2f" $ratio]
! 1580: } else {
! 1581: CTputs $num " INF "
! 1582: }
! 1583: } else {
! 1584: CTputs $num " ----"
! 1585: }
! 1586: }
! 1587: CTputs $num "\n"
! 1588: }
! 1589: }
! 1590:
! 1591: ###########################################################
! 1592: # CTsubmissionsLaunch
! 1593: ###########################################################
! 1594: ###########################################################
! 1595: ###########################################################
! 1596: proc CTsubmissionsLaunch { num cmdnum type s_id s_nm start end } {
! 1597: global gCT gFile gUniqueNumber gCapaConfig
! 1598:
! 1599: CTputs $cmdnum "$type submissions for $s_nm for set $start\n"
! 1600: if { $type == "telnet" } {
! 1601: set command "grep -i $s_id [file join $gFile($num) records submissions$start.db]"
! 1602: set followtype web
! 1603: } else {
! 1604: set command "grep -i $s_id [file join $gFile($num) \
! 1605: records websubmissions$start.db]"
! 1606: set followtype telnet
! 1607: incr start
! 1608: }
! 1609: set done 0
! 1610: set followcmd ""
! 1611: while { !$done && ($start <= ($end+1)) } {
! 1612: if { $start <= $end } {
! 1613: set followcmd "CTsubmissionsLaunch $num $cmdnum $followtype $s_id {$s_nm} \
! 1614: $start $end"
! 1615: }
! 1616: if { ! [catch {set fileId [open "|$command" "r"]} ] } { set done 1 }
! 1617: }
! 1618: fconfigure $fileId -blocking 0
! 1619: fileevent $fileId readable "CTrunCommand $num $cmdnum $fileId {$followcmd}"
! 1620: }
! 1621:
! 1622: ###########################################################
! 1623: # CTreportDist
! 1624: ###########################################################
! 1625: ###########################################################
! 1626: ###########################################################
! 1627: proc CTreportDist { num file percentage sectionlist } {
! 1628: set fileId [open $file "r"]
! 1629: set aline [gets $fileId]
! 1630: set which [expr [llength [split $aline "\t"]] - 2]
! 1631: set maximum [lindex [lrange [split $aline "\t"] $which end] 1]
! 1632: if { $percentage } {
! 1633: for {set i 0} {$i<=100} {incr i} {
! 1634: set totals($i.score) 0
! 1635: set totals($i.stunum) ""
! 1636: }
! 1637: } else {
! 1638: for { set i 0 } { $i <= $maximum } { incr i } {
! 1639: set totals($i.score) 0
! 1640: set totals($i.stunum) ""
! 1641: }
! 1642: }
! 1643: while { ![eof $fileId]} {
! 1644: set temp [lrange [split $aline "\t"] $which end]
! 1645: set score [lindex $temp 0]
! 1646: regsub -- "-" $score "0" score
! 1647: set max [lindex $temp 1]
! 1648: set temp [lindex [split $aline "\t"] 1]
! 1649: set section [lindex $temp 1]
! 1650: set stunum [lindex $temp 0]
! 1651: if { ([lsearch $sectionlist $section] != -1) && ($max!=0) } {
! 1652: if { $percentage } {
! 1653: set percent [expr int($score/double($max)*100)]
! 1654: incr totals($percent.score)
! 1655: lappend totals($percent.stunum) $stunum
! 1656: } else {
! 1657: if { $max > $maximum } {
! 1658: for {set i [expr $maximum+1]} {$i<=$max} {incr i} {set totals($i) 0}
! 1659: set maximum $max
! 1660: }
! 1661: set score [string trim $score]
! 1662: incr totals($score.score)
! 1663: lappend totals($score.stunum) $stunum
! 1664: }
! 1665: }
! 1666: set aline [gets $fileId]
! 1667: }
! 1668: CTputs $num "Scores #acheived\n"
! 1669: set scorelist ""
! 1670: set templist [array names totals *.score]
! 1671: foreach temp $templist {lappend possiblescores [lindex [split $temp .] 0]}
! 1672: foreach score [lsort -integer $possiblescores] {
! 1673: CTputs $num [format "%5d:%6d\n" $score $totals($score.score)]
! 1674: lappend scorelist [list $totals($score.score) $score $totals($score.stunum)]
! 1675: }
! 1676: return $scorelist
! 1677: }
! 1678:
! 1679: ###########################################################
! 1680: # CTgradeDistribution
! 1681: ###########################################################
! 1682: ###########################################################
! 1683: ###########################################################
! 1684: proc CTgradeDistribution { num classpath setId } {
! 1685: set filename [file join $classpath records "set$setId.db"]
! 1686: if { ! [file readable $filename] } {
! 1687: CTputs $num "FILE: $filename does not exist!\n"
! 1688: return
! 1689: }
! 1690:
! 1691: displayStatus "Analyzing [file tail $filename]" both $num
! 1692: set maxLine [lindex [exec wc $filename] 0]
! 1693: set fileId [open "$filename" "r"]
! 1694: set valid_cnt 0
! 1695: set line_cnt 0
! 1696: set aline [gets $fileId]
! 1697: while {![eof $fileId]} {
! 1698: incr line_cnt
! 1699: if { ($line_cnt%20) == 0 } {
! 1700: updateStatusBar [expr $line_cnt/double($maxLine)] $num
! 1701: }
! 1702: if { $line_cnt == 2 } {
! 1703: set aline [string trim $aline]
! 1704: set weights [split $aline {}]
! 1705: set valid_weights 0
! 1706: foreach weight $weights { incr valid_weights $weight }
! 1707: for { set i 0 } { $i <= $valid_weights } { incr i } {
! 1708: set total_score($i) 0
! 1709: }
! 1710: } elseif { $line_cnt > 3} {
! 1711: set aline [string trim $aline]
! 1712: set prefix [lindex [split $aline ","] 0]
! 1713: set s_num [string toupper [lindex [split $aline " " ] 0 ] ]
! 1714: set ans_str [lindex [split $prefix " "] 1]
! 1715: set ans_char [split $ans_str {} ]
! 1716: set valid 0
! 1717: for { set ii 0 } { $ii < [llength $ans_char] } { incr ii } {
! 1718: if { [lindex $ans_char $ii] != "-"} { set valid 1 }
! 1719: }
! 1720: if { $valid } {
! 1721: incr valid_cnt
! 1722: set score 0
! 1723: for { set ii 0 } { $ii < [llength $ans_char] } { incr ii } {
! 1724: if { [lindex $ans_char $ii] == "Y" || \
! 1725: [lindex $ans_char $ii] == "y" } {
! 1726: incr score [lindex $weights $ii]
! 1727: }
! 1728: if { [lindex $ans_char $ii] >= 0 && \
! 1729: [lindex $ans_char $ii] <= 9 } {
! 1730: incr score [lindex $ans_char $ii]
! 1731: }
! 1732: }
! 1733: if { [catch {incr total_score($score)} ] } {
! 1734: puts "$aline:$prefix:$s_num:$ans_str:$ans_char"
! 1735: }
! 1736:
! 1737: }
! 1738: }
! 1739: set aline [gets $fileId]
! 1740: }
! 1741: close $fileId
! 1742: removeStatus $num
! 1743: displayStatus "Pondering data . . ." spinner $num
! 1744: CTputs $num " There are $valid_cnt entries in file $filename\n"
! 1745: CTputs $num "Score #acheived\n"
! 1746: set scorelist ""
! 1747: foreach score [lsort -integer [array names total_score]] {
! 1748: CTputs $num [format "%5d:%6d\n" $score $total_score($score)]
! 1749: lappend scorelist [list $total_score($score) $score]
! 1750: }
! 1751: removeStatus $num
! 1752: return $scorelist
! 1753: }
! 1754:
! 1755: ###########################################################
! 1756: # CTgetStudentScores
! 1757: ###########################################################
! 1758: ###########################################################
! 1759: ###########################################################
! 1760: proc CTgetStudentScores { studentScoresVar classpath setId num } {
! 1761: upvar $studentScoresVar studentScores
! 1762:
! 1763: set filename [file join $classpath records "set$setId.db"]
! 1764: if { ! [file readable $filename] } {
! 1765: CTputs $num "FILE: $filename does not exist!\n"
! 1766: error
! 1767: }
! 1768:
! 1769: displayStatus "Analyzing [file tail $filename]" both $num
! 1770: set maxLine [lindex [exec wc $filename] 0]
! 1771: set fileId [open "$filename" "r"]
! 1772: set valid_cnt 0
! 1773: set line_cnt 0
! 1774: set aline [gets $fileId]
! 1775: set aline [gets $fileId]
! 1776: set weights [split [string trim $aline] {}]
! 1777: set valid_weights 0
! 1778: foreach weight $weights { incr valid_weights $weight }
! 1779: set aline [gets $fileId]
! 1780: set aline [gets $fileId]
! 1781: while {![eof $fileId]} {
! 1782: incr line_cnt
! 1783: if { ($line_cnt%20) == 0 } {
! 1784: updateStatusBar [expr $line_cnt/double($maxLine)] $num
! 1785: }
! 1786: set aline [string trim $aline]
! 1787: set prefix [lindex [split $aline ","] 0]
! 1788: set s_num [string toupper [lindex [split $aline " " ] 0 ] ]
! 1789: set ans_str [lindex [split $prefix " "] 1]
! 1790: set ans_char [split $ans_str {} ]
! 1791: set valid 0
! 1792: for { set ii 0 } { $ii < [llength $ans_char] } { incr ii } {
! 1793: if { [lindex $ans_char $ii] != "-"} { set valid 1 }
! 1794: }
! 1795: if { $valid } {
! 1796: incr valid_cnt
! 1797: if {[array names studentScores $s_num] == ""} {set studentScores($s_num) 0}
! 1798: for { set ii 0 } { $ii < [llength $ans_char] } { incr ii } {
! 1799: if { [lindex $ans_char $ii] == "Y" || [lindex $ans_char $ii] == "y" } {
! 1800: incr studentScores($s_num) [lindex $weights $ii]
! 1801: }
! 1802: if { [lindex $ans_char $ii] >= 0 && [lindex $ans_char $ii] <= 9 } {
! 1803: incr studentScores($s_num) [lindex $ans_char $ii]
! 1804: }
! 1805: }
! 1806: }
! 1807: set aline [gets $fileId]
! 1808: }
! 1809: close $fileId
! 1810: removeStatus $num
! 1811: return $valid_weights
! 1812: }
! 1813:
! 1814: ###########################################################
! 1815: # CTgradeDistributionRange
! 1816: ###########################################################
! 1817: ###########################################################
! 1818: ###########################################################
! 1819: proc CTgradeDistributionRange { num classpath setIdstart setIdend } {
! 1820: set totalpoints 0
! 1821: for {set setId $setIdstart} {$setId <= $setIdend} {incr setId} {
! 1822: set points [CTgetStudentScores studentScores $classpath $setId $num]
! 1823: incr totalpoints $points
! 1824: # parray studentScores
! 1825: }
! 1826:
! 1827: displayStatus "Pondering data . . ." spinner $num
! 1828: for { set i 0 } { $i <= $totalpoints } { incr i } {
! 1829: set total_score($i) 0
! 1830: }
! 1831: foreach sNum [array names studentScores] { incr total_score($studentScores($sNum)) }
! 1832: CTputs $num "Scores #acheived\n"
! 1833: set scorelist ""
! 1834: foreach score [lsort -integer [array names total_score]] {
! 1835: CTputs $num [format "%5d:%6d\n" $score $total_score($score)]
! 1836: lappend scorelist [list $total_score($score) $score]
! 1837: }
! 1838: removeStatus $num
! 1839: return $scorelist
! 1840: }
! 1841:
! 1842: #common Input dialogs
! 1843:
! 1844: #common output methods
! 1845: proc CTdatestamp { cmdnum } {
! 1846: CTputs $cmdnum [clock format [clock seconds]]\n
! 1847: }
! 1848:
! 1849: ###########################################################
! 1850: # CTputs
! 1851: ###########################################################
! 1852: ###########################################################
! 1853: ###########################################################
! 1854: proc CTputs { num message {tag normal} } {
! 1855: global gCT
! 1856:
! 1857: lappend gCT(output.$num) [list $message $tag]
! 1858: }
! 1859:
! 1860: ###########################################################
! 1861: # CToutputWrap
! 1862: ###########################################################
! 1863: ###########################################################
! 1864: ###########################################################
! 1865: proc CToutputWrap { num } {
! 1866: global gCT
! 1867: if { $gCT($num.wrap) } {
! 1868: $gCT($num.output) configure -wrap char
! 1869: } else {
! 1870: $gCT($num.output) configure -wrap none
! 1871: }
! 1872: }
! 1873:
! 1874: ###########################################################
! 1875: # CToutput
! 1876: ###########################################################
! 1877: ###########################################################
! 1878: ###########################################################
! 1879: proc CToutput { num cmdnum } {
! 1880: global gCT
! 1881:
! 1882: if { ![winfo exists $gCT($num).output] } {
! 1883: set outputWin [toplevel $gCT($num).output]
! 1884:
! 1885: set buttonFrame [frame $outputWin.button]
! 1886: set textFrame [frame $outputWin.text]
! 1887: set bottomFrame [frame $outputWin.bottom]
! 1888: pack $buttonFrame $textFrame $bottomFrame
! 1889: pack configure $buttonFrame -anchor e -expand 0 -fill x
! 1890: pack configure $textFrame -expand 1 -fill both
! 1891: pack configure $bottomFrame -expand 0 -fill x
! 1892:
! 1893: set gCT($num.output) [text $textFrame.text \
! 1894: -yscrollcommand "$textFrame.scroll set" \
! 1895: -xscrollcommand "$bottomFrame.scroll set"]
! 1896: scrollbar $textFrame.scroll -command "$textFrame.text yview"
! 1897: pack $gCT($num.output) $textFrame.scroll -side left
! 1898: pack configure $textFrame.text -expand 1 -fill both
! 1899: pack configure $textFrame.scroll -expand 0 -fill y
! 1900:
! 1901: scrollbar $bottomFrame.scroll -command "$textFrame.text xview" -orient h
! 1902: pack $bottomFrame.scroll -expand 0 -fill x
! 1903:
! 1904: set gCT($num.wrap) 1
! 1905: checkbutton $buttonFrame.wrap -text "Wrap" -command "CToutputWrap $num" \
! 1906: -variable gCT($num.wrap)
! 1907: button $buttonFrame.save -text "Save Text" -command "CTsaveText $num"
! 1908: button $buttonFrame.print -text "Print Text" -command "CTprintText $num"
! 1909: button $buttonFrame.dismiss -text "Dismiss" -command "destroy $outputWin"
! 1910: pack $buttonFrame.wrap $buttonFrame.save $buttonFrame.print \
! 1911: $buttonFrame.dismiss -side left
! 1912: }
! 1913: set index [$gCT($num.output) index end]
! 1914: foreach line $gCT(output.$cmdnum) {
! 1915: eval $gCT($num.output) insert end $line
! 1916: }
! 1917: unset gCT(output.$cmdnum)
! 1918: raise $gCT($num).output
! 1919: $gCT($num.output) see $index
! 1920: update idletasks
! 1921: }
! 1922:
! 1923: ###########################################################
! 1924: # CTsaveText
! 1925: ###########################################################
! 1926: # saves the contents of a text window
! 1927: ###########################################################
! 1928: # Arguments: num (the unique number of the path, and window)
! 1929: # Returns : nothing
! 1930: # Globals :
! 1931: ###########################################################
! 1932: proc CTsaveText { num } {
! 1933: global gFile gCT
! 1934:
! 1935: set window $gCT($num.output)
! 1936: if {![winfo exists $window]} { return }
! 1937: set dir $gFile($num)
! 1938: set file ""
! 1939:
! 1940: if { $dir == "" || $dir == "."} { set dir [pwd] }
! 1941: set file [tk_getSaveFile -title "Enter the name to Save As" \
! 1942: -initialdir "$dir" ]
! 1943: if { $file == "" } {
! 1944: displayError "File not saved"
! 1945: return
! 1946: }
! 1947: set fileId [open $file w]
! 1948: puts -nonewline $fileId [$window get 0.0 end-1c]
! 1949: close $fileId
! 1950: }
! 1951:
! 1952: ###########################################################
! 1953: # CTprintText
! 1954: ###########################################################
! 1955: # prints the contents of the text window, creates a temp file named
! 1956: # quiztemp.txt
! 1957: ###########################################################
! 1958: # Arguments: num (the unique number of the path, and window)
! 1959: # Returns : nothing
! 1960: # Globals : gFile gCT
! 1961: ###########################################################
! 1962: proc CTprintText { num } {
! 1963: global gFile gCT
! 1964:
! 1965: set window $gCT($num.output)
! 1966: if { ![winfo exists $window]} { return }
! 1967: catch {parseCapaConfig $num $gFile($num)}
! 1968: set lprCommand [getLprCommand [file join $gFile($num) managertemp.txt] $num]
! 1969: if {$lprCommand == "Cancel"} { return }
! 1970:
! 1971: set fileId [open [file join $gFile($num) managertemp.txt] w]
! 1972: puts -nonewline $fileId [$window get 0.0 end-1c]
! 1973: close $fileId
! 1974:
! 1975: set errorMsg ""
! 1976: if { [catch {set output [ eval "exec $lprCommand" ] } errorMsg ]} {
! 1977: displayError "An error occurred while printing: $errorMsg"
! 1978: } else {
! 1979: displayMessage "Print job sent to the printer.\n $output"
! 1980: }
! 1981: exec rm -f [file join $gFile($num) mangertemp.txt]
! 1982: }
! 1983:
! 1984: ###########################################################
! 1985: # CTprintCanvas
! 1986: ###########################################################
! 1987: ###########################################################
! 1988: ###########################################################
! 1989: proc CTprintCanvas { num window path } {
! 1990:
! 1991: if { ![winfo exists $window]} { return }
! 1992: catch {parseCapaConfig $num $gFile($num)}
! 1993: set lprCommand [getLprCommand [file join $path managertemp.txt] $num]
! 1994: if {$lprCommand == "Cancel"} { return }
! 1995:
! 1996: set rotate 0
! 1997: if { [tk_messageBox -title "Print in landscape mode" -message "Would you like to print in landscape mode?" -icon question -type yesno] == "yes" } { set rotate 1 }
! 1998: $window postscript -file [file join $path managertemp.txt] -rotate $rotate
! 1999:
! 2000: set errorMsg ""
! 2001: if { [catch {set output [ eval "exec $lprCommand" ] } errorMsg ]} {
! 2002: displayError "An error occurred while printing: $errorMsg"
! 2003: } else {
! 2004: displayMessage "Print job sent to the printer.\n $output"
! 2005: }
! 2006: exec rm -f [file join $path mangertemp.txt]
! 2007: }
! 2008:
! 2009: ###########################################################
! 2010: # CTsaveCanvas
! 2011: ###########################################################
! 2012: ###########################################################
! 2013: ###########################################################
! 2014: proc CTsaveCanvas { window path } {
! 2015: if { ![winfo exists $window] } { return }
! 2016: set dir $path
! 2017: set file ""
! 2018:
! 2019: if { $dir == "" } { set dir [pwd] }
! 2020: set file [tk_getSaveFile -title "Enter the name to Save As" \
! 2021: -initialdir "$dir" ]
! 2022: if { $file == "" } {
! 2023: displayError "File not saved"
! 2024: return
! 2025: }
! 2026: $window postscript -file $file
! 2027: }
! 2028:
! 2029: ###########################################################
! 2030: # CTbargraph
! 2031: ###########################################################
! 2032: ###########################################################
! 2033: ###########################################################
! 2034: proc CTbargraph {window num barnum data {path ""} {title "" } {xlabel ""} {ylabel ""}
! 2035: {suffix ""} } {
! 2036: global gBarGraph
! 2037: set height 300
! 2038: set width 500
! 2039:
! 2040: global gWindowMenu
! 2041:
! 2042: set bargraph [toplevel $window.bargraph$barnum]
! 2043: if { $title != "" } { wm title $bargraph $title }
! 2044: $gWindowMenu add command -label "$title $barnum" -command "capaRaise $bargraph"
! 2045:
! 2046: set buttonFrame [frame $bargraph.buttons]
! 2047: set canvasFrame [frame $bargraph.canvas]
! 2048: pack $buttonFrame $canvasFrame -side top
! 2049: pack configure $canvasFrame -expand 1 -fill both
! 2050:
! 2051: set canvas [canvas $canvasFrame.canvas -height $height -width $width -background white]
! 2052: pack $canvas -expand 1 -fill both
! 2053: bind $canvas <Configure> "CTdrawBargraph $barnum"
! 2054:
! 2055: button $buttonFrame.change -text "Change Graph" -command "CTchangeBargraph $window $barnum"
! 2056: button $buttonFrame.save -text "Save Graph" -command "CTsaveCanvas $canvas $path"
! 2057: button $buttonFrame.print -text "Print Graph" -command "CTprintCanvas $num $canvas $path"
! 2058: button $buttonFrame.dismiss -text "Dismiss" -command "CTdestroyBargraph $barnum"
! 2059: pack $buttonFrame.change $buttonFrame.save $buttonFrame.print \
! 2060: $buttonFrame.dismiss -side left
! 2061: bind $bargraph <Destroy> "CTdestroyBargraph $barnum"
! 2062:
! 2063: set gBarGraph($barnum.num) $num
! 2064: set gBarGraph($barnum.suffix) $suffix
! 2065: set gBarGraph($barnum) $data
! 2066: set gBarGraph($barnum.canvas) $canvas
! 2067: set gBarGraph($barnum.title) $title
! 2068: set gBarGraph($barnum.xlabel) $xlabel
! 2069: set gBarGraph($barnum.ylabel) $ylabel
! 2070: set gBarGraph($barnum.color) green
! 2071: set gBarGraph($barnum.bucketscores) 0
! 2072: CTautoscaleBargraph $barnum
! 2073: CTdrawBargraph $barnum
! 2074: }
! 2075:
! 2076: ###########################################################
! 2077: # CTautoscaleBargraph
! 2078: ###########################################################
! 2079: ###########################################################
! 2080: ###########################################################
! 2081: proc CTautoscaleBargraph { barnum } {
! 2082: global gBarGraph
! 2083: set data $gBarGraph($barnum)
! 2084: set max [lindex [lindex [lsort -decreasing -index 0 -real $data] 0] 0]
! 2085: if { $max > int($max) } { set max [expr int($max+1)] }
! 2086: set gBarGraph($barnum.yoften) [expr int([format "%1.e" [expr $max/10.0]])]
! 2087: if { $gBarGraph($barnum.yoften) == 0 } { set gBarGraph($barnum.yoften) 1 }
! 2088: set total [llength $data]
! 2089: set gBarGraph($barnum.xoften) [expr ($total/25) + 1]
! 2090: }
! 2091:
! 2092: ###########################################################
! 2093: # CTchangeBargraphData
! 2094: ###########################################################
! 2095: ###########################################################
! 2096: ###########################################################
! 2097: proc CTchangeBargraphData { barnum data } {
! 2098: global gBarGraph
! 2099: set gBarGraph($barnum) $data
! 2100: CTautoscaleBargraph $barnum
! 2101: CTdrawBargraph $barnum
! 2102: }
! 2103:
! 2104: ###########################################################
! 2105: # CTdestroyBargraph
! 2106: ###########################################################
! 2107: ###########################################################
! 2108: ###########################################################
! 2109: proc CTdestroyBargraph { num } {
! 2110: global gBarGraph
! 2111:
! 2112: if { [catch {set window [winfo toplevel $gBarGraph($num.canvas)]}]} { return }
! 2113: set window2 [file rootname $window].changeBarGraph$num
! 2114: foreach name [array names gBarGraph "$num.*" ] {
! 2115: unset gBarGraph($name)
! 2116: }
! 2117: unset gBarGraph($num)
! 2118: destroy $window
! 2119: catch {destroy $window2}
! 2120: }
! 2121:
! 2122: ###########################################################
! 2123: # CTdrawBargraph
! 2124: ###########################################################
! 2125: ###########################################################
! 2126: ###########################################################
! 2127: proc CTdrawBargraph { num } {
! 2128: global gBarGraph
! 2129:
! 2130: set data $gBarGraph($num)
! 2131: set canvas $gBarGraph($num.canvas)
! 2132: set suffix $gBarGraph($num.suffix)
! 2133:
! 2134: set height [winfo height $canvas]
! 2135: set width [winfo width $canvas]
! 2136: set titleoffset 0
! 2137: set titleheight 15
! 2138: set labelheight 15
! 2139: set tickheight 15
! 2140: set textheight [expr $labelheight+$tickheight]
! 2141: set textwidth 40
! 2142: set graphheight [expr $height - $textheight - $titleheight]
! 2143: set graphwidth [expr $width - $textwidth]
! 2144: $canvas delete all
! 2145:
! 2146: #draw data
! 2147: set total [llength $data]
! 2148: set eachwidth [expr $graphwidth/$total]
! 2149: # set howoften [expr ($total/$gBarGraph($num.numlabels)) + 1]
! 2150: set howoften $gBarGraph($num.xoften)
! 2151: set when [expr ($total-1)%$howoften]
! 2152: set max 0
! 2153: set i 0
! 2154: set value 0
! 2155: if { $gBarGraph($num.bucketscores) } {
! 2156: foreach datum $data {
! 2157: set value [expr {$value + [lindex $datum 0]}]
! 2158: if { $i % $howoften == $when } {
! 2159: if { $value > $max } { set max $value }
! 2160: set value 0
! 2161: }
! 2162: incr i
! 2163: }
! 2164: } else {
! 2165: set max [lindex [lindex [lsort -decreasing -index 0 -real $data] 0] 0]
! 2166: }
! 2167: if { $max > int($max) } { set max [expr int($max+1)] }
! 2168: if { [catch {set pixelvalue [expr ($graphheight-1)/double($max)]} ] } {
! 2169: set pixelvalue 10
! 2170: }
! 2171: set i 0
! 2172: set value 0
! 2173: foreach datum $data {
! 2174: set value [expr {$value + [lindex $datum 0]}]
! 2175: set which [lindex $datum 1]
! 2176: set y1 [expr {$graphheight + $titleheight}]
! 2177: set x2 [expr {$eachwidth * ($i+1) + $textwidth}]
! 2178: set y2 [expr {($graphheight-1) + $titleheight - $value * $pixelvalue}]
! 2179: set tag bar.$which.[expr $which-$howoften]
! 2180: if { [set color [lindex $datum 3]] == "" } {set color $gBarGraph($num.color)}
! 2181: if { $gBarGraph($num.bucketscores) && ($i % $howoften == $when) } {
! 2182: if { $i == $when } {
! 2183: puts "$value-$which-$howoften"
! 2184: $canvas create rectangle $textwidth \
! 2185: $y1 $x2 $y2 -fill $color -tag $tag
! 2186: } else {
! 2187: puts "$value:$which:$howoften"
! 2188: $canvas create rectangle [expr {$eachwidth*($i-$howoften+1)+$textwidth}]\
! 2189: $y1 $x2 $y2 -fill $color -tag $tag
! 2190: }
! 2191: } elseif { !$gBarGraph($num.bucketscores) } {
! 2192: $canvas create rectangle [expr {$eachwidth * $i + $textwidth}] \
! 2193: $y1 $x2 $y2 -fill $color -tag bar.$which.[expr $which-1]
! 2194: set value 0
! 2195: }
! 2196: if { $i % $howoften == $when } {
! 2197: $canvas create text [expr {$eachwidth * $i + $textwidth + $eachwidth/2}] \
! 2198: [expr $graphheight+(($tickheight)/2)+$titleheight] -text $which
! 2199: set value 0
! 2200: }
! 2201: incr i
! 2202: }
! 2203:
! 2204: #draw title
! 2205: $canvas create text [expr $textwidth+$titleoffset+($graphwidth/2)] 1 -anchor n\
! 2206: -text $gBarGraph($num.title)
! 2207: #draw axis
! 2208: $canvas create line $textwidth [expr {$graphheight + $titleheight}] \
! 2209: $textwidth [expr {$titleheight + 1}]
! 2210: #label xaxis
! 2211: $canvas create text [expr ($textwidth+($graphwidth/2))] \
! 2212: [expr $titleheight+$graphheight+$tickheight+($labelheight/2)] \
! 2213: -text $gBarGraph($num.xlabel)
! 2214: #label yaxis
! 2215: $canvas create text 1 1 -anchor nw -text $gBarGraph($num.ylabel)
! 2216: #draw tickmarks
! 2217: # set delta [format "%1.e" [expr ($max)/double($gBarGraph($num.numticks))]]
! 2218: set delta $gBarGraph($num.yoften)
! 2219: set start 0.0
! 2220: while { $start < $max } {
! 2221: set center [expr {($graphheight-1)*(($start)/$max)+$titleheight+1}]
! 2222: $canvas create line $textwidth $center [expr $textwidth - 20] $center
! 2223: $canvas create text [expr $textwidth-3] $center -anchor ne -text [expr int($max-$start)]
! 2224: set start [expr $start + $delta]
! 2225: }
! 2226: if { [llength [lindex $data 0]] > 2} {
! 2227: $canvas bind current <1> "CTbargraphClick$suffix $num"
! 2228: bind $canvas <Enter> "CTbargraphDisplayCreate $num"
! 2229: bind $canvas <Leave> "CTbargraphDisplayRemove $num"
! 2230: bind $canvas <Motion> "CTbargraphDisplayMove $num"
! 2231: $canvas bind all <Enter> "CTbargraphDisplay$suffix $num"
! 2232: }
! 2233: }
! 2234:
! 2235: ###########################################################
! 2236: # CTbargraphDisplayCreate
! 2237: ###########################################################
! 2238: ###########################################################
! 2239: ###########################################################
! 2240: proc CTbargraphDisplayCreate { barnum } {
! 2241: global gBarGraph gCT gFile
! 2242: set canvas $gBarGraph($barnum.canvas)
! 2243: if {[winfo exists $canvas.bubble$barnum]} { return }
! 2244: set bubble [toplevel $canvas.bubble$barnum]
! 2245: wm overrideredirect $bubble 1
! 2246: wm positionfrom $bubble program
! 2247: wm withdraw $bubble
! 2248: pack [label $bubble.l -highlightthickness 0 -relief raised -bd 1 -background yellow]
! 2249: }
! 2250: ###########################################################
! 2251: # CTbargraphDisplayRemove
! 2252: ###########################################################
! 2253: ###########################################################
! 2254: ###########################################################
! 2255: proc CTbargraphDisplayRemove { barnum } {
! 2256: global gBarGraph gCT gFile
! 2257: set canvas $gBarGraph($barnum.canvas)
! 2258: catch {destroy $canvas.bubble$barnum}
! 2259: }
! 2260: ###########################################################
! 2261: # CTbargraphDisplayBlank
! 2262: ###########################################################
! 2263: ###########################################################
! 2264: ###########################################################
! 2265: proc CTbargraphDisplayBlank { barnum } {
! 2266: global gBarGraph gCT gFile
! 2267: set canvas $gBarGraph($barnum.canvas)
! 2268: catch {$canvas.bubble$barnum.l configure -text ""}
! 2269: }
! 2270: ###########################################################
! 2271: # CTbargraphDisplayMove
! 2272: ###########################################################
! 2273: ###########################################################
! 2274: ###########################################################
! 2275: proc CTbargraphDisplayMove { barnum } {
! 2276: global gBarGraph gCT gFile
! 2277: set canvas $gBarGraph($barnum.canvas)
! 2278: catch {wm geometry $canvas.bubble$barnum +[expr 20+[winfo pointerx .]]+[expr 20+[winfo pointery .]]}
! 2279: if {[$canvas gettags current] == ""} {CTbargraphDisplayRemove $barnum}
! 2280: }
! 2281: ###########################################################
! 2282: # CTbargraphDisplayShowresponse
! 2283: ###########################################################
! 2284: ###########################################################
! 2285: ###########################################################
! 2286: proc CTbargraphDisplayShowresponse { barnum } {
! 2287: global gBarGraph gCT gFile
! 2288: set num $gBarGraph($barnum.num)
! 2289: set canvas $gBarGraph($barnum.canvas)
! 2290:
! 2291: set high [lindex [split [lindex [$canvas gettags current] 0] .] 1]
! 2292: foreach datum $gBarGraph($barnum) {
! 2293: set bar [lindex $datum 1]
! 2294: if { $bar != $high } { continue }
! 2295: if {![winfo exists $canvas.bubble$barnum.l]} {CTbargraphDisplayCreate $barnum}
! 2296: $canvas.bubble$barnum.l configure -text "[lindex $datum 0] - \"[splitline [lindex $datum 2] 35]\""
! 2297: wm geometry $canvas.bubble$barnum +[expr 20+[winfo pointerx .]]+[expr 20+[winfo pointery .]]
! 2298: wm deiconify $canvas.bubble$barnum
! 2299: return
! 2300: }
! 2301: CTbargraphDisplayRemove $barnum
! 2302: }
! 2303: ###########################################################
! 2304: # CTbargraphDisplaySCP
! 2305: ###########################################################
! 2306: ###########################################################
! 2307: ###########################################################
! 2308: proc CTbargraphDisplaySCP { barnum } {
! 2309: global gBarGraph gCT gFile
! 2310: set num $gBarGraph($barnum.num)
! 2311: set canvas $gBarGraph($barnum.canvas)
! 2312:
! 2313: set high [lindex [split [lindex [$canvas gettags current] 0] .] 1]
! 2314: foreach datum $gBarGraph($barnum) {
! 2315: set bar [lindex $datum 1]
! 2316: if { $bar != $high } { continue }
! 2317: if {![winfo exists $canvas.bubble$barnum.l]} {CTbargraphDisplayCreate $barnum}
! 2318: $canvas.bubble$barnum.l configure -text "[lindex $datum 0]"
! 2319: wm geometry $canvas.bubble$barnum +[expr 20+[winfo pointerx .]]+[expr 20+[winfo pointery .]]
! 2320: wm deiconify $canvas.bubble$barnum
! 2321: return
! 2322: }
! 2323: CTbargraphDisplayRemove $barnum
! 2324: }
! 2325:
! 2326: ###########################################################
! 2327: # CTbargraphClickSCP
! 2328: ###########################################################
! 2329: ###########################################################
! 2330: ###########################################################
! 2331: proc CTbargraphClickSCP { barnum } {
! 2332: global gBarGraph gCT gFile
! 2333:
! 2334: set num $gBarGraph($barnum.num)
! 2335: set canvas $gBarGraph($barnum.canvas)
! 2336: set bucket $gBarGraph($barnum.bucketscores)
! 2337:
! 2338: set high [lindex [split [lindex [$canvas gettags current] 0] .] 1]
! 2339: set low [lindex [split [lindex [$canvas gettags current] 0] .] 2]
! 2340: set stunums ""
! 2341: if { $high == "" || $low == "" } { return }
! 2342: foreach datum $gBarGraph($barnum) {
! 2343: set bar [lindex $datum 1]
! 2344: if { $bar > $high || $bar <= $low } { continue }
! 2345: set stunums [concat $stunums [lindex $datum 2]]
! 2346: }
! 2347: if { $stunums == "" } { return }
! 2348: if {"" == [set stuSCP [multipleChoice $gCT($num) "Select a student" $stunums 0]]} {
! 2349: return
! 2350: }
! 2351: set loginAnalysis [expr {"Yes" == [makeSure "Do you wish to do a Login Analysis? It may take a while." ]}]
! 2352: foreach s_id $stuSCP {
! 2353: CTstudentCourseProfile $num $s_id \
! 2354: [findByStudentNumber $s_id $gFile($num)] $loginAnalysis
! 2355: }
! 2356: }
! 2357:
! 2358: ###########################################################
! 2359: # CTbargraphClickShowresponse
! 2360: ###########################################################
! 2361: ###########################################################
! 2362: ###########################################################
! 2363: proc CTbargraphClickShowresponse { barnum } {
! 2364: global gBarGraph gCT gFile gUniqueNumber
! 2365:
! 2366: set num $gBarGraph($barnum.num)
! 2367: set canvas $gBarGraph($barnum.canvas)
! 2368: set bucket $gBarGraph($barnum.bucketscores)
! 2369:
! 2370: if { [catch {set datanum $gBarGraph($barnum.shownum1)}] } {
! 2371: set datanum [set gBarGraph($barnum.shownum1) [incr gUniqueNumber]]
! 2372: set winnum [set gBarGraph($barnum.shownum2) [incr gUniqueNumber]]
! 2373: } else {
! 2374: set winnum $gBarGraph($barnum.shownum2)
! 2375: }
! 2376: set gCT($winnum) ""
! 2377: set high [lindex [split [lindex [$canvas gettags current] 0] .] 1]
! 2378: foreach datum $gBarGraph($barnum) {
! 2379: set bar [lindex $datum 1]
! 2380: if { $bar != $high } { continue }
! 2381: CTputs $datanum "[lindex $datum 0] responses \"[lindex $datum 2]\"\n"
! 2382: }
! 2383: CToutput $winnum $datanum
! 2384: }
! 2385:
! 2386: ###########################################################
! 2387: # CTchangeBargraph
! 2388: ###########################################################
! 2389: ###########################################################
! 2390: ###########################################################
! 2391: proc CTchangeBargraph { window num } {
! 2392: global gBarGraph
! 2393:
! 2394: set change [toplevel $window.changeBarGraph$num]
! 2395:
! 2396: set infoFrame [frame $change.info]
! 2397: set buttonFrame [frame $change.button]
! 2398: set title [frame $change.title]
! 2399: set xlabel [frame $change.xlabel]
! 2400: set ylabel [frame $change.ylabel]
! 2401: set xoften [frame $change.xoften]
! 2402: set yoften [frame $change.yoften]
! 2403: set color [frame $change.color]
! 2404: set bucket [frame $change.bucket]
! 2405: set font [frame $change.font]
! 2406: pack $infoFrame $buttonFrame $title $xlabel $ylabel $xoften $yoften $color $bucket
! 2407: pack configure $title $xlabel $ylabel $xoften $yoften -anchor e -expand 1 -fill both
! 2408: button $buttonFrame.update -text Update -command "CTdrawBargraph $num"
! 2409: bind $change <Return> "CTdrawBargraph $num"
! 2410: button $buttonFrame.dismiss -text Dismiss -command "destroy $change"
! 2411: pack $buttonFrame.update $buttonFrame.dismiss -side left
! 2412:
! 2413: foreach {frame label var
! 2414: } "$title { Title} title
! 2415: $xlabel { X-Axis Label} xlabel
! 2416: $ylabel { Y-Axis Label} ylabel
! 2417: $xoften {Increment on X-Axis} xoften
! 2418: $yoften {Increment on Y-Axis} yoften" {
! 2419: label $frame.label -text $label
! 2420: set entryFrame [frame $frame.entry]
! 2421: pack $frame.label $entryFrame -side left
! 2422: pack configure $entryFrame -expand 1 -fill both
! 2423: entry $entryFrame.entry -textvariable gBarGraph($num.$var) \
! 2424: -xscrollcommand "$entryFrame.scroll set"
! 2425: scrollbar $entryFrame.scroll -orient h -command \
! 2426: "$entryFrame.entry xview"
! 2427: pack $entryFrame.entry $entryFrame.scroll -fill x
! 2428: }
! 2429:
! 2430: label $color.label -text "Color of Bars"
! 2431: label $color.color -relief ridge -background $gBarGraph($num.color) \
! 2432: -text " "
! 2433: button $color.change -text "Change" -command "CTchangeBargraphColor $color $num"
! 2434: pack $color.label $color.color $color.change -side left
! 2435:
! 2436: checkbutton $bucket.bucket -text "Bucket Scores" -variable \
! 2437: gBarGraph($num.bucketscores) -command "CTdrawBargraph $num"
! 2438: pack $bucket.bucket
! 2439: }
! 2440:
! 2441: ###########################################################
! 2442: # CTchangeBargraphColor
! 2443: ###########################################################
! 2444: ###########################################################
! 2445: ###########################################################
! 2446: proc CTchangeBargraphColor { color num } {
! 2447: global gBarGraph
! 2448: set temp [tk_chooseColor -initialcolor $gBarGraph($num.color)]
! 2449: if { $temp != "" } {
! 2450: $color.color configure -background [set gBarGraph($num.color) $temp]
! 2451: }
! 2452: CTdrawBargraph $num
! 2453: }
! 2454:
! 2455: ###########################################################
! 2456: # CTdisplayStudent
! 2457: ###########################################################
! 2458: ###########################################################
! 2459: ###########################################################
! 2460: proc CTdisplayStudent { num window path id } {
! 2461:
! 2462: if { ![file exists [file join $path photo gif $id.gif]] } {
! 2463: if { [file exists [file join $path photo jpg $id.jpg]] } {
! 2464: exec /usr/local/bin/djpeg -outfile [file join $path photo gif $id.gif] \
! 2465: [file join $path photo jpg $id.jpg]
! 2466: } else {
! 2467: return
! 2468: }
! 2469: }
! 2470: set image [image create photo]
! 2471: $image read [file join $path photo gif $id.gif]
! 2472:
! 2473: set imageWin [toplevel $window.image$num]
! 2474:
! 2475: set buttonFrame [frame $imageWin.button]
! 2476: set infoFrame [frame $imageWin.info]
! 2477: set imageFrame [frame $imageWin.image]
! 2478: pack $buttonFrame $infoFrame $imageFrame
! 2479:
! 2480: button $buttonFrame.dismiss -command "destroy $imageWin" -text Dismiss
! 2481: pack $buttonFrame.dismiss
! 2482:
! 2483: label $infoFrame.label -text $id
! 2484: pack $infoFrame.label
! 2485:
! 2486: set canvas [canvas $imageFrame.canvas]
! 2487: pack $canvas
! 2488: $canvas create image 1 1 -image $image -anchor nw
! 2489: }
! 2490:
! 2491: ###########################################################
! 2492: # CTgetWhen
! 2493: ###########################################################
! 2494: ###########################################################
! 2495: ###########################################################
! 2496: proc CTgetWhen { num } {
! 2497: set day [getString . "Enter a date"]
! 2498: update
! 2499: return $day
! 2500: }
! 2501:
! 2502: ###########################################################
! 2503: # CTscanDB
! 2504: ###########################################################
! 2505: ###########################################################
! 2506: ###########################################################
! 2507: proc CTscanDB { num file outId startdate enddate } {
! 2508: global answerArray exist
! 2509: set fileId [open $file r]
! 2510: set Yes_cnt 0
! 2511: set No_cnt 0
! 2512: set line_cnt 0
! 2513: set prob_cnt 0
! 2514: set maxLine [lindex [exec wc $file] 0]
! 2515: puts $maxLine
! 2516: set aline [gets $fileId]
! 2517: while { ! [eof $fileId] } {
! 2518: incr line_cnt
! 2519: if { ($line_cnt%20) == 0 } {
! 2520: puts $curdate
! 2521: updateStatusBar [expr $line_cnt/double($maxLine)] $num
! 2522: }
! 2523: set length [llength $aline]
! 2524: set date [lrange $aline 1 [expr $length - 2]]
! 2525: set curdate [clock scan $date]
! 2526: if { $curdate < $startdate } { set aline [gets $fileId]; continue }
! 2527: if { $curdate > $enddate } { break }
! 2528: set s_num [string toupper [lindex $aline 0]]
! 2529: set ans_char [split [lindex $aline end] ""]
! 2530: set usr_ans "$s_num.ans"
! 2531: set usr_try "$s_num.try"
! 2532: if {$prob_cnt == 0} { set prob_cnt [llength $ans_char] }
! 2533: if { [array names answerArray "$usr_ans.*"] == "" } {
! 2534: for {set ii 0} { $ii <= $prob_cnt } { incr ii} {
! 2535: set answerArray($usr_ans.$ii) "-"
! 2536: }
! 2537: }
! 2538: if { [array names answerArray "$usr_try.*"] == "" } {
! 2539: for {set ii 0} { $ii <= $prob_cnt } { incr ii} {
! 2540: set answerArray($usr_try.$ii) 0
! 2541: }
! 2542: }
! 2543: for {set ii 0} { $ii <= $prob_cnt } { incr ii} {
! 2544: if { [lindex $ans_char $ii] == "Y" } {
! 2545: set answerArray($usr_ans.$ii) "Y"
! 2546: incr answerArray($usr_try.$ii)
! 2547: }
! 2548: if { [lindex $ans_char $ii] == "N"} {
! 2549: if {$answerArray($usr_ans.$ii) != "Y"} {
! 2550: set answerArray($usr_ans.$ii) "Y"
! 2551: }
! 2552: incr answerArray($usr_try.$ii)
! 2553: }
! 2554: }
! 2555: if { [array names exist $s_num] == "" } { set exist($s_num) $s_num }
! 2556: set aline [gets $fileId]
! 2557: }
! 2558: close $fileId
! 2559: return $prob_cnt
! 2560: }
! 2561:
! 2562: ###########################################################
! 2563: # CTcreateSubset
! 2564: ###########################################################
! 2565: ###########################################################
! 2566: ###########################################################
! 2567: proc CTcreateSubset { num cmdnum day setId } {
! 2568: global gFile gCT answerArray exist
! 2569:
! 2570: set outId [open [file join $gFile($num) records "subset$setId.db"] w]
! 2571: set inId [open [file join $gFile($num) records "set$setId.db"] r]
! 2572:
! 2573: set startdate [clock scan "$day 12:00 AM"]
! 2574: set enddate [clock scan "$day 11:59 PM"]
! 2575:
! 2576: puts $startdate:$enddate
! 2577: set prob_cntt [CTscanDB $cmdnum [file join $gFile($num) records log$setId.db] $outId $startdate $enddate]
! 2578: puts $startdate:$enddate
! 2579: set prob_cntw [CTscanDB $cmdnum [file join $gFile($num) records weblog$setId.db] $outId $startdate $enddate]
! 2580: puts $startdate:$enddate
! 2581: puts "$day 12:00 AM : $day 11:59 PM"
! 2582: if { $prob_cntt > $prob_cntw } {
! 2583: set prob_cnt $prob_cntt
! 2584: } else {
! 2585: set prob_cnt $prob_cntw
! 2586: }
! 2587:
! 2588: puts $outId [gets $inId]
! 2589: puts $outId [gets $inId]
! 2590: puts $outId [gets $inId]
! 2591: foreach s_num [lsort [array names exist]] {
! 2592: set usr_ans $s_num.ans
! 2593: set usr_try $s_num.try
! 2594: puts -nonewline $outId "$s_num "
! 2595: for { set ii 0 } { $ii< $prob_cnt } { incr ii } {
! 2596: puts -nonewline $outId $answerArray($usr_ans.$ii)
! 2597: }
! 2598: for { set ii 0 } { $ii< $prob_cnt } { incr ii } {
! 2599: puts -nonewline $outId [format ",%2d" $answerArray($usr_try.$ii)]
! 2600: }
! 2601: puts $outId ""
! 2602: }
! 2603: close $outId
! 2604: close $inId
! 2605: catch {unset answerArray}
! 2606: catch {unset exist}
! 2607: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>