File:  [LON-CAPA] / capa / capa51 / GUITools / capastats.tcl
Revision 1.2: download - view: text, annotated - select for diffs
Fri Oct 15 14:29:34 1999 UTC (24 years, 7 months ago) by albertel
Branches: MAIN
CVS tags: HEAD
-Added some discussion forum stats

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

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