Annotation of loncom/interface/lonstatistics.pm, revision 1.27

1.1       albertel    1: # The LearningOnline Network with CAPA
                      2: # (Publication Handler
                      3: #
1.27    ! stredwic    4: # $Id: lonstatistics.pm,v 1.26 2002/05/31 16:02:11 minaeibi Exp $
1.1       albertel    5: #
                      6: # Copyright Michigan State University Board of Trustees
                      7: #
                      8: # This file is part of the LearningOnline Network with CAPA (LON-CAPA).
                      9: #
                     10: # LON-CAPA is free software; you can redistribute it and/or modify
                     11: # it under the terms of the GNU General Public License as published by
                     12: # the Free Software Foundation; either version 2 of the License, or
                     13: # (at your option) any later version.
                     14: #
                     15: # LON-CAPA is distributed in the hope that it will be useful,
                     16: # but WITHOUT ANY WARRANTY; without even the implied warranty of
                     17: # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
                     18: # GNU General Public License for more details.
                     19: #
                     20: # You should have received a copy of the GNU General Public License
                     21: # along with LON-CAPA; if not, write to the Free Software
                     22: # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
                     23: #
                     24: # /home/httpd/html/adm/gpl.txt
                     25: #
                     26: # http://www.lon-capa.org/
                     27: #
                     28: # (Navigate problems for statistical reports
                     29: # YEAR=2001
1.15      minaeibi   30: # 5/5,7/9,7/25/1,8/11,9/13,9/26,10/5,10/9,10/22,10/26 Behrouz Minaei
1.14      minaeibi   31: # 11/1,11/4,11/16,12/14,12/16,12/18,12/20,12/31 Behrouz Minaei
1.1       albertel   32: # YEAR=2002
1.18      minaeibi   33: # 1/22,2/1,2/6,2/25,3/2,3/6,3/17,3/21,3/22,3/26,4/7,5/6 Behrouz Minaei
1.21      minaeibi   34: # 5/12,5/14,5/15,5/19,5/26 Behrouz Minaei
1.14      minaeibi   35: #
1.1       albertel   36: ###
                     37: 
1.3       minaeibi   38: package Apache::lonstatistics; 
1.1       albertel   39: 
1.15      minaeibi   40: use strict; 
1.1       albertel   41: use Apache::Constants qw(:common :http);
                     42: use Apache::lonnet();
                     43: use Apache::lonhomework;
1.12      minaeibi   44: use Apache::loncommon;
1.27    ! stredwic   45: use Apache::loncoursedata;
1.1       albertel   46: use HTML::TokeParser;
                     47: use GDBM_File;
                     48: 
                     49: # -------------------------------------------------------------- Module Globals
                     50: my %hash;
                     51: my %CachData;
                     52: my %GraphDat;
1.5       minaeibi   53: my %mapsort;
1.1       albertel   54: my $Pos;
                     55: my $r;
                     56: my $GData;
1.25      minaeibi   57: my %color;
1.15      minaeibi   58: my %foil_to_concept;
                     59: my @Concepts;
                     60: my %ConceptData;
1.18      minaeibi   61: my %Answer = ();
1.15      minaeibi   62: 
1.21      minaeibi   63: sub Activity {
1.26      minaeibi   64:     my $file="/home/minaeibi/activity.log";
                     65:     my $userid='adamsde1';
1.21      minaeibi   66:     $r->print("<br>Using $file");
                     67:     $r->rflush();
                     68:     open(FILEID, "<$file");
                     69:     my $line;
                     70:     my @allaccess;
1.25      minaeibi   71:     my $Count=0;
1.21      minaeibi   72:     while ($line=<FILEID>) {
                     73: 	my ($time,$machine,$what)=split(':',$line);
1.25      minaeibi   74: 	$what=&Apache::lonnet::unescape($what);
1.21      minaeibi   75: 	my @accesses=split('&',$what);
                     76: 	foreach my $access (@accesses) {
                     77: 	    my ($date,$resource,$who,$domain,$post,@posts)=split(':',$access);
                     78: 	    if ($who ne $userid) { next; }
1.25      minaeibi   79: 	    if (!$resource) { next; }
                     80: 	    my $res=&Apache::lonnet::unescape($resource);
1.26      minaeibi   81: 	    if (($res =~ /\.(problem|htm|html)/)) {
1.25      minaeibi   82: 		$Count++;
1.26      minaeibi   83: 		$r->print("<br>$Count) ".localtime($date).": $who --> $res");
                     84: #	        if ($post) { 
                     85: #		    $Count++;
                     86: #		    $r->print("<br><b>$Count) Sent data ".join(':',
                     87: #                              &Apache::lonnet::unescape(@posts)).'</b>');
                     88: #		}
1.25      minaeibi   89: 		$r->rflush();
1.26      minaeibi   90: 	    }
1.25      minaeibi   91: 	##    push (@allaccess,unescape($access));
1.21      minaeibi   92: 	    #print $machine;
                     93: 	}
                     94:     }
1.25      minaeibi   95: #    @allaccess=sort(@allaccess);
                     96: #    $Count=0;
                     97: #    foreach my $access (@allaccess) {
                     98: #	my ($date,$resource,$who,$domain,$post,@posts)=split(':',$access);
                     99: #	$Count++;
                    100: #	$r->print("<br>$Count) $date: $who --> $resource");
                    101: #	$r->rflush();
                    102: #	if ($post) { 
                    103: #	    $r->print("<br><b>Sent data ".join(':',unescape(@posts)).'</b>');
                    104: #	}
                    105: #    }
1.21      minaeibi  106: }
                    107: 
1.27    ! stredwic  108: #---- Analyze Web Page ---------------------------------------------------
1.21      minaeibi  109: 
1.27    ! stredwic  110: sub InitAnalysis {
        !           111:     my ($uri,$part,$problem,$student,$courseID)=@_;
        !           112:     my ($username,$userdomain)=split(/\:/,$student);
1.21      minaeibi  113: 
1.27    ! stredwic  114:     # Render the student's view of the problem.  $Answ is the problem 
        !           115:     # Stringafied
        !           116:     my $Answ=&Apache::lonnet::ssi($uri,('grade_target'   => 'analyze',
        !           117:                                         'grade_username' => $username,
        !           118:                                         'grade_domain'   => $userdomain,
        !           119:                                         'grade_courseid' => $courseID,
        !           120:                                         'grade_symb'     => $problem));
        !           121: #    my $Answ=&Apache::lonnet::ssi($uri,('grade_target' => 'analyze'));
1.15      minaeibi  122: 
1.27    ! stredwic  123: #    (undef,$Answ)=split(/_HASH_REF__/,$Answ,2);
1.18      minaeibi  124:     %Answer=();
1.15      minaeibi  125:     %Answer=&Apache::lonnet::str2hash($Answ);
                    126: 
1.27    ! stredwic  127: #    foreach (sort(keys(%Answer))) {
        !           128: #        $r->print($_.'  '.$Answer{$_}.'<br>');
        !           129: #    }
        !           130: 
1.15      minaeibi  131:     my $parts='';
                    132:     foreach my $elm (@{$Answer{"parts"}}) {
                    133: 	$parts.="$elm,";
                    134:     }
                    135:     chop($parts);
                    136:     my $conc='';
                    137:     foreach my $elm (@{$Answer{"$parts.concepts"}}) {
                    138: 	$conc.="$elm@";
                    139:     }
                    140:     chop($conc);
                    141: 
                    142:     @Concepts=split(/\@/,$conc);
                    143:     foreach my $concept (@{$Answer{"$parts.concepts"}}) {
                    144: 	foreach my $foil (@{$Answer{"$parts.concept.$concept"}}) {
                    145: 	    $foil_to_concept{$foil} = $concept;
1.19      minaeibi  146: 	    #$ConceptData{$foil} = $Answer{"$parts.foil.value.$foil"};
1.15      minaeibi  147: 	}
                    148:     }
1.27    ! stredwic  149: 
        !           150:     return;
1.15      minaeibi  151: }
                    152: 
                    153: sub Interval {
1.27    ! stredwic  154:     my ($part,$symb)=@_;
        !           155:     my $interval=$ConceptData{"Interval"};
        !           156:     my $due  = &Apache::lonnet::EXT('resource.'.$part.'.duedate',$symb)+1;
        !           157:     my $open = &Apache::lonnet::EXT('resource.'.$part.'.opendate',$symb);
        !           158:     my $add=int(($due-$open)/$interval);
        !           159:     $ConceptData{'Interval.0'}=$open;
        !           160:     for (my $i=1;$i<$interval;$i++) {
        !           161: 	$ConceptData{'Interval.'.$i}=$open+$i*$add;
1.15      minaeibi  162:     }
1.27    ! stredwic  163:     $ConceptData{'Interval.'.$interval}=$due;     
        !           164:     for (my $i=0;$i<$interval;$i++) {
1.15      minaeibi  165: 	for (my $n=0; $n<=$#Concepts; $n++ ) {
                    166: 	    my $tmp=$Concepts[$n];
1.27    ! stredwic  167: 	    $ConceptData{$tmp.'.'.$i.'.true'}=0;
        !           168: 	    $ConceptData{$tmp.'.'.$i.'.false'}=0;
1.15      minaeibi  169: 	}
                    170:     }
                    171: }
                    172: 
1.27    ! stredwic  173: sub ShowOpGraph {
        !           174:     my ($cache, $students, $courseID)=@_;
        !           175:     my $uri      = $cache->{'AnalyzeURI'};
        !           176:     my $part     = $cache->{'AnalyzePart'};
        !           177:     my $problem  = $cache->{'AnalyzeProblem'};
        !           178:     my $title    = $cache->{'AnalyzeProblem'};
        !           179:     my $interval = $cache->{'Interval'};
        !           180:     $ConceptData{"Interval"} = $interval;
1.15      minaeibi  181: 
1.19      minaeibi  182:     #Initialize the option response true answers
1.27    ! stredwic  183:     &InitAnalysis($uri, $part, $problem, $students->[0],$courseID);
        !           184: 
1.19      minaeibi  185:     #compute the intervals
1.27    ! stredwic  186:     &Interval($part,$problem);
        !           187: 
        !           188:     $title =~ s/\ /"_"/eg;
        !           189:     $r->print('<br><b>'.$uri.'</b>');
1.15      minaeibi  190:     $r->rflush();
                    191:     
1.19      minaeibi  192:     #Java script Progress window
1.16      minaeibi  193:     &Create_PrgWin();
1.27    ! stredwic  194:     &Update_PrgWin("Starting to analyze problem",0,0,'');
        !           195:     for(my $index=0; $index<(scalar @$students); $index++) {
        !           196: 	&Update_PrgWin(scalar @$students, $index+1, $students->[$index]);
        !           197: 	&OpStatus($problem, $students->[$index], $courseID);
1.15      minaeibi  198:     }
                    199:     &Close_PrgWin();
                    200: 
1.19      minaeibi  201:     $r->print('<br>');
1.27    ! stredwic  202:     for(my $k=0; $k<$interval; $k++ ) {
        !           203: 	&DrawGraph($k,$title);
1.15      minaeibi  204:     }
1.27    ! stredwic  205:     for(my $k=0; $k<$interval; $k++ ) {
1.20      minaeibi  206: 	&DrawTable($k);
                    207:     }
1.17      minaeibi  208: #$Apache::lonxml::debug=1;
                    209: #&Apache::lonhomework::showhash(%ConceptData);
                    210: #$Apache::lonxml::debug=0;
1.27    ! stredwic  211:     my $Answ=&Apache::lonnet::ssi($uri);
1.15      minaeibi  212:     $r->print("<br><b>Here you can see the Problem:</b><br>$Answ");
                    213: }
                    214: 
1.20      minaeibi  215: sub DrawTable {
                    216:     my $k=shift;
1.15      minaeibi  217:     my $Max=0;
                    218:     my @data1;
                    219:     my @data2;
1.18      minaeibi  220:     my $Correct=0;
                    221:     my $Wrong=0;
1.15      minaeibi  222:     for (my $n=0; $n<=$#Concepts; $n++ ) {
                    223: 	my $tmp=$Concepts[$n];
                    224: 	$data1[$n]=$ConceptData{"$tmp.$k.true"};
1.18      minaeibi  225: 	$Correct+=$data1[$n];
1.15      minaeibi  226: 	$data2[$n]=$ConceptData{"$tmp.$k.false"};
1.18      minaeibi  227: 	$Wrong+=$data2[$n];
1.15      minaeibi  228: 	my $Sum=$data1[$n]+$data2[$n];
                    229: 	if ( $Max<$Sum ) {$Max=$Sum;}
                    230:     }
                    231:     for (my $n=0; $n<=$#Concepts; $n++ ) {
                    232: 	if ($data1[$n]+$data2[$n]<$Max) {
                    233: 	    $data2[$n]+=$Max-($data1[$n]+$data2[$n]);
                    234: 	}
                    235:     }
1.18      minaeibi  236:     my $P_No = $#data1+1;
                    237: #    $r->print('<br><b>From: ['.localtime($ConceptData{'Int.'.($k-1)}).
                    238: #              '] To: ['.localtime($ConceptData{"Int.$k"}).']</b>'); 
                    239:     my $Str = "\n".'<table border=2>'.
                    240:               "\n".'<tr>'.
                    241:               "\n".'<th> # </th>'.
                    242: 	      "\n".'<th> Concept </th>'.
                    243: 	      "\n".'<th> Correct </th>'.
                    244: 	      "\n".'<th> Wrong </th>'.
                    245: 	      "\n".'</tr>';
1.15      minaeibi  246: 
1.18      minaeibi  247:     for (my $n=0; $n<=$#Concepts; $n++ ) {
                    248: 	$Str .= "\n"."<tr>".
                    249: 	        "\n"."<td>".($n+1)."</td>".
1.25      minaeibi  250:                 "\n".'<td bgcolor='.$color{"yellow"}.'> '.$Concepts[$n]." </td>".
                    251:                 "\n".'<td bgcolor='.$color{"green"}.'> '.$data1[$n]." </td>".
                    252:                 "\n".'<td bgcolor='.$color{"red"}.'> '.$data2[$n]." </td>".
1.18      minaeibi  253:                 "\n"."</tr>";
                    254:     }
1.20      minaeibi  255:     $Str.='<td></td><td><b>From:['.localtime($ConceptData{'Int.'.$k}).
                    256:           '] To: ['.localtime($ConceptData{'Int.'.($k+1)}-1).
                    257:           "]</b></td><td>$Correct</td><td>$Wrong</td>";
                    258: 
                    259:     $Str .= "\n".'</table>';
                    260: 
                    261:     $r->print($Str);
1.19      minaeibi  262: #$Apache::lonxml::debug=1;
                    263: #&Apache::lonhomework::showhash(%ConceptData);
                    264: #$Apache::lonxml::debug=0;
1.20      minaeibi  265: }
1.19      minaeibi  266: 
1.15      minaeibi  267: 
1.20      minaeibi  268: sub DrawGraph {
1.27    ! stredwic  269:     my ($currentInterval,$title)=@_;
1.20      minaeibi  270:     my $Max=0;
                    271:     my @data1;
                    272:     my @data2;
1.15      minaeibi  273: 
1.20      minaeibi  274:     # Adjust Data and find the Max 
1.27    ! stredwic  275:     for(my $n=0; $n<=$#Concepts; $n++ ) {
1.20      minaeibi  276: 	my $tmp=$Concepts[$n];
1.27    ! stredwic  277: 	$data1[$n]=$ConceptData{$tmp.'.'.$currentInterval.'.true'};
        !           278: 	$data2[$n]=$ConceptData{$tmp.'.'.$currentInterval.'.false'};
1.20      minaeibi  279: 	my $Sum=$data1[$n]+$data2[$n];
1.27    ! stredwic  280: 	if($Max < $Sum) { $Max = $Sum; }
1.20      minaeibi  281:     }
1.27    ! stredwic  282:     for(my $n=0; $n<=$#Concepts; $n++) {
        !           283: 	if($data1[$n]+$data2[$n]<$Max) {
1.20      minaeibi  284: 	    $data2[$n]+=$Max-($data1[$n]+$data2[$n]);
                    285: 	}
                    286:     }
1.27    ! stredwic  287:     my $P_No = scalar @data1;
1.18      minaeibi  288: 
1.27    ! stredwic  289:     if($Max > 1) { 
1.18      minaeibi  290: 	$Max += (10 - $Max % 10);
                    291: 	$Max = int($Max);
1.27    ! stredwic  292:     } else { 
        !           293:         $Max = 1;
        !           294:     }
1.18      minaeibi  295: 
1.27    ! stredwic  296:     my $Titr=($ConceptData{'Interval'}>1) ? 
        !           297:         $title.'_interval_'.($currentInterval+1) : $title;
1.18      minaeibi  298: #    $GData=$Titr.'&Concepts'.'&'.'Answers'.'&'.$Max.'&'.$P_No.'&'.$data1.'&'.$data2;
1.27    ! stredwic  299:     $GData  = $Titr.'&Concepts&Answers&'.$Max.'&'.$P_No.'&';
        !           300:     $GData .= (join(',',@data1)).'&'.(join(',',@data2));
1.18      minaeibi  301: 
1.19      minaeibi  302:     $r->print('<IMG src="/cgi-bin/graph.gif?'.$GData.'" border=1/>');
1.15      minaeibi  303: }
                    304: 
                    305: 
                    306: sub Decide {
1.19      minaeibi  307:     #deciding the true or false answer belongs to each interval
1.15      minaeibi  308:     my ($type,$foil,$time)=@_; 
                    309:     my $k=0;
                    310:     while ($time>$ConceptData{'Int.'.($k+1)} && 
                    311:            $k<$ConceptData{'Interval'}) {$k++;}
                    312:     $ConceptData{"$foil_to_concept{$foil}.$k.$type"}++;
                    313: }
                    314: 
                    315: 
1.19      minaeibi  316: #restore the student submissions and finding the result
1.15      minaeibi  317: sub OpStatus {
1.27    ! stredwic  318:     my ($problem, $student, $courseID)=@_;
        !           319:     my ($username,$userdomain)=split(/':'/,$student);
1.15      minaeibi  320:     my $code='U';
1.27    ! stredwic  321:     my %reshash=&Apache::lonnet::restore($problem, $courseID, $userdomain, 
        !           322:                                          $username);
1.15      minaeibi  323:     my @True = ();
                    324:     my @False = ();
                    325:     my $flag=0;
                    326:     if ($reshash{'version'}) {
1.18      minaeibi  327:         my $tries=0;
                    328: 	&Apache::lonhomework::showhash(%Answer);
1.15      minaeibi  329: 	for (my $version=1;$version<=$reshash{'version'};$version++) {
                    330: 	    my $time=$reshash{"$version:timestamp"};
1.18      minaeibi  331: 	   
                    332: 	    foreach my $key (sort(split(/\:/,$reshash{$version.':keys'}))) {
                    333: 		if (($key=~/\.(\w+)\.(\w+)\.submission$/)) {
                    334: 		    my $Id1 = $1; my $Id2 = $2;
                    335: 		    #check if this is a repeat submission, if so skip it
                    336:           	    if ($reshash{"$version:resource.$Id1.previous"}) { next; }
                    337: 		    #if no solved this wasn't a real submission, ignore it
                    338: 		    if (!defined($reshash{"$version:resource.$Id1.solved"})) {
                    339: 			&Apache::lonxml::debug("skipping ");
                    340: 			next;
                    341: 		    }
                    342: 		    my $Resp = $reshash{"$version:$key"};
1.15      minaeibi  343: 		    my %submission=&Apache::lonnet::str2hash($Resp);
                    344: 		    foreach (keys %submission) {
1.18      minaeibi  345: 			my $Ansr = $Answer{"$Id1.$Id2.foil.value.$_"};
1.15      minaeibi  346: 			if ($submission{$_}) {
                    347: 			    if ($submission{$_} eq $Ansr) {
                    348: 				&Decide("true",$_,$time );
                    349: 			    }
                    350: 			    else {&Decide("false",$_,$time );}
                    351: 			}
                    352: 		    }
                    353: 	        }	  
                    354: 	    }
                    355:         }
                    356:     }
                    357: }
1.11      minaeibi  358: 
1.27    ! stredwic  359: #---- END Analyze Web Page ----------------------------------------------
        !           360: 
        !           361: #---- Problem Statistics Web Page ---------------------------------------
1.11      minaeibi  362: 
1.7       minaeibi  363: #------- Processing upperlist and lowerlist according to each problem
1.27    ! stredwic  364: sub ProcessDiscriminant {
        !           365:     my ($List) = @_;
        !           366:     my @sortedList = sort (@$List);
        !           367:     my $Count = scalar @sortedList;
        !           368:     my $Problem;
1.7       minaeibi  369:     my @Dis;
                    370:     my $Slvd=0;
                    371:     my $tmp;
1.8       minaeibi  372:     my $Sum1=0;
                    373:     my $Sum2=0;
1.27    ! stredwic  374:     my $nIndex=0;
        !           375:     my $nStudent=0;
        !           376:     my %Proc=undef;
        !           377:     while ($nIndex<$Count) {
        !           378: 	($Problem,$tmp)=split(/\=/,$sortedList[$nIndex]);
1.7       minaeibi  379: 	@Dis=split(/\+/,$tmp);
1.27    ! stredwic  380: 	my $Temp = $Problem;
1.7       minaeibi  381: 	do {
1.27    ! stredwic  382: 	    $nIndex++;
        !           383: 	    $nStudent++;
1.8       minaeibi  384: 	    $Sum1 += $Dis[0];
                    385: 	    $Sum2 += $Dis[1];
1.27    ! stredwic  386: 	    ($Problem,$tmp)=split(/\=/,$sortedList[$nIndex]);
1.7       minaeibi  387: 	    @Dis=split(/\+/,$tmp);
1.27    ! stredwic  388: 	} while ( $Problem eq $Temp && $nIndex < $Count );
        !           389: #	$Proc{$Temp}=($Sum1/$nStudent).':'.$nStudent;
        !           390: 	$Proc{$Temp}=($Sum1/$nStudent).':'.($Sum2/$nStudent);
        !           391: #       $r->print("$nIndex) $Temp --> ($nStudent) $Proc{$Temp} <br>");
1.8       minaeibi  392: 	$Sum1=0;
                    393: 	$Sum2=0;
1.27    ! stredwic  394: 	$nStudent=0;
1.7       minaeibi  395:     }
1.27    ! stredwic  396: 
1.7       minaeibi  397:     return %Proc;
                    398: }
                    399: 
                    400: 
                    401: #------- Creating Discimination factor   
                    402: sub Discriminant {
1.27    ! stredwic  403:     my ($discriminantFactor)=@_;
        !           404:     my @discriminantKeys=keys(%$discriminantFactor);
        !           405:     my $Count = scalar @discriminantKeys;
        !           406: 
        !           407:     my $UpCnt = int(0.27*$Count);
1.7       minaeibi  408:     my $low=0;
                    409:     my $up=$Count-$UpCnt;
                    410:     my @UpList=();
                    411:     my @LowList=();
1.27    ! stredwic  412: 
1.7       minaeibi  413:     $Count=0;
1.27    ! stredwic  414:     foreach my $key (sort(@discriminantKeys)) { 
1.7       minaeibi  415: 	$Count++;    
1.27    ! stredwic  416: 	if($low < $UpCnt || $Count > $up) {
        !           417:             $low++;
        !           418:             my $str=$discriminantFactor->{$key};
        !           419:             foreach(split(/\:/,$str)){
        !           420:                 if($_) {
        !           421:                     if($low<$UpCnt) { push(@LowList,$_); }
        !           422:                     else            { push(@UpList,$_);  }
        !           423:                 }
        !           424:             }
        !           425:         }
1.7       minaeibi  426:     }
1.27    ! stredwic  427:     my %DisUp =  &ProcessDiscriminant(\@UpList);
        !           428:     my %DisLow = &ProcessDiscriminant(\@LowList);
        !           429: 
        !           430:     return (\%DisUp, \%DisLow);
1.7       minaeibi  431: }
                    432: 
1.1       albertel  433: sub NumericSort {          
                    434:     $a <=> $b;
                    435: }
                    436: 
1.27    ! stredwic  437: sub CreateProblemStatisticsTableHeading {
        !           438:     my ($displayFormat,$sequenceSource,$sequenceTitle,$headings)=@_;
        !           439:     if($displayFormat eq 'Display CSV Format') {
        !           440:         $r->print('<br>"'.$sequenceTitle.'","');
        !           441:         $r->print($sequenceSource.'"');
1.1       albertel  442: 	return;
                    443:     }
                    444: 
1.27    ! stredwic  445:     $r->print('<br><a href="'.$sequenceSource.
        !           446:               '" target="_blank">'.$sequenceTitle.'</a>');
1.1       albertel  447: 
1.27    ! stredwic  448:     my $Result = "\n".'<table border=2><tr><th>P#</th>'."\n";
        !           449:     for(my $nIndex=0; $nIndex < (scalar (keys %$headings)); $nIndex++) { 
        !           450: 	$Result .= '<th>'.'<input type="submit" name="';
        !           451:         $Result .= 'ProblemStatisticsHeading" value="';
        !           452:         $Result .= $headings->{$nIndex}.'" />'.'</th>'."\n";
1.5       minaeibi  453:     }
                    454:     $Result .= "\n".'</tr>'."\n";    
1.27    ! stredwic  455:     $r->print($Result);
1.5       minaeibi  456:     $r->rflush();
                    457: }
1.1       albertel  458: 
1.5       minaeibi  459: sub CloseTable {
1.27    ! stredwic  460:     my ($cache)=@_;
        !           461:     if($cache->{'DisplayFormat'} eq 'Display CSV Format') {
1.18      minaeibi  462: 	return;
                    463:     }    
1.5       minaeibi  464:     $r->print("\n".'</table>'."\n");
                    465:     $r->rflush();
                    466: }
1.19      minaeibi  467: 
1.27    ! stredwic  468: # ------ Dump the Student's DB file and handling the data for statistics table 
        !           469: sub ExtractStudentData {
        !           470:     my ($cache,$name)=@_;
        !           471:     my %discriminantFactor;
        !           472:     my @list=();
        !           473: 
        !           474:     my $totalTries = 0;
        !           475:     my $totalAwarded = 0;
        !           476:     my $tempProblemOrder=0;
        !           477:     foreach my $sequence (split(':', $cache->{'orderedSequences'})) {
        !           478:         if($cache->{'ProblemStatisticsMap'} ne 'All Maps'  &&
        !           479:            $cache->{'ProblemStatisticsMap'} ne $cache->{$sequence.':title'}) {
        !           480:             next;
1.1       albertel  481:         }
1.12      minaeibi  482: 
1.27    ! stredwic  483:         my $Dis = '';
        !           484:         foreach my $problemID (split(':', $cache->{$sequence.':problems'})) {
        !           485:             my $problem = $cache->{$problemID.':problem'};
        !           486:             my $LatestVersion = $cache->{$name.':version:'.$problem};
        !           487: 
        !           488:             # Output dashes for all the parts of this problem if there
        !           489:             # is no version information about the current problem.
        !           490:             #if(!$LatestVersion) {
        !           491:             #    foreach my $part (split(/\:/,$cache->{$sequence.':'.
        !           492:             #                                          $problemID.
        !           493:             #                                          ':parts'})) {
        !           494:             #        $codes    .= "-,";
        !           495:             #        $attempts .= "0,"; 
        !           496:             #    }
        !           497:             #    next;
        !           498:             #}
        !           499: 
        !           500:             my %partData=undef;
        !           501:             # Initialize part data, display skips correctly
        !           502:             # Skip refers to when a student made no submissions on that
        !           503:             # part/problem.
        !           504:             foreach my $part (split(/\:/,$cache->{$sequence.':'.
        !           505:                                                   $problemID.
        !           506:                                                   ':parts'})) {
        !           507:                 $partData{$part.':tries'}=0;
        !           508:                 $partData{$part.':code'}='-';
        !           509:             }
1.1       albertel  510: 
1.27    ! stredwic  511:             # Looping through all the versions of each part, starting with the
        !           512:             # oldest version.  Basically, it gets the most recent 
        !           513:             # set of grade data for each part.
        !           514: 	    for(my $Version=1; $Version<=$LatestVersion; $Version++) {
        !           515:                 foreach my $part (split(/\:/,$cache->{$sequence.':'.
        !           516:                                                       $problemID.
        !           517:                                                       ':parts'})) {
        !           518: 
        !           519:                     if(!defined($cache->{$name.":$Version:$problem".
        !           520:                                                ":resource.$part.solved"})) {
        !           521:                         # No grade for this submission, so skip
        !           522:                         next;
        !           523:                     }
        !           524: 
        !           525:                     my $tries=0;
        !           526:                     my $time=0;
        !           527:                     my $awarded=0;
        !           528:                     my $code='U';
        !           529: 
        !           530:                     $awarded = $cache->{$name.
        !           531:                                         "$Version:$problem:resource.".
        !           532:                                         "$part.awarded"};
        !           533:                     $partData{$part.':awarded'} = ($awarded) ? $awarded : 0;
        !           534:                     $totalAwarded += $awarded;
        !           535: 
        !           536:                     $tries = $cache->{$name.":$Version:$problem".
        !           537:                                       ":resource.$part.tries"};
        !           538:                     $partData{$part.':tries'} = ($tries) ? $tries : 0;
        !           539:                     $partData{$part.':wrong'} = $partData{$part.':tries'};
        !           540:                     $totalTries += $tries;
        !           541: 
        !           542:                     my $val = $cache->{$name.":$Version:$problem".
        !           543:                                        ":resource.$part.solved"};
        !           544:                     if    ($val eq 'correct_by_student')   {$code = 'C';} 
        !           545:                     elsif ($val eq 'correct_by_override')  {$code = 'O';}
        !           546:                     elsif ($val eq 'incorrect_attempted')  {$code = 'I';} 
        !           547:                     elsif ($val eq 'incorrect_by_override'){$code = 'I';}
        !           548:                     elsif ($val eq 'excused')              {$code = 'x';}
        !           549:                     $partData{$part.':code'}=$code;
        !           550: 
        !           551:                     if($partData{$part.':wrong'} ne 0 && 
        !           552:                        ($code eq 'C' || $code eq 'O')) {
        !           553:                         $partData{$part.':wrong'}--;
        !           554:                     }
        !           555:                 }
        !           556:             }
1.1       albertel  557: 
1.27    ! stredwic  558:             # Loop through all the parts for the current problem in the 
        !           559:             # correct order and prepare the output
        !           560:             foreach (split(/\:/,$cache->{$sequence.':'.$problemID.
        !           561:                                          ':parts'})) {
        !           562:                 my $Yes = 0;
        !           563:                 if($partData{$_.':code'} eq 'C' || 
        !           564:                    $partData{$_.':code'} eq 'O') {
        !           565:                     $Yes=1;
        !           566:                 }
        !           567:                 #my $ptr = "$hash{'title_'.$ResId}";
        !           568:                 my $ptr = $tempProblemOrder.'&'.$problemID;
1.1       albertel  569: 
1.27    ! stredwic  570:                 if($_ > 1) {
        !           571:                     $ptr .= "*(part $_)";
        !           572:                     $Dis .= '&';
        !           573:                 }
        !           574:                 my $Fac = ($partData{$_.':Tries'}) ? 
        !           575:                     ($partData{$_.':awarded'}/$partData{$_.':tries'}) : 0;
        !           576:                 my $DisF;
        !           577:                 if($Fac > 0 &&  $Fac < 1) { 
        !           578:                     $DisF = sprintf( "%.4f", $Fac );
        !           579:                 } else {
        !           580:                     $DisF = $Fac;
        !           581:                 }
        !           582:                 $Dis .= $tempProblemOrder.'='.$DisF.'+'.$Yes;
        !           583:                 $ptr .= '&'.$partData{$_.'.Tries'}.
        !           584:                         '&'.$partData{$_.'.Wrongs'}.
        !           585:                         '&'.$partData{$_.'.Code'};
        !           586:                 push (@list, $ptr);
        !           587:                 $tempProblemOrder++;
1.5       minaeibi  588:             }
1.1       albertel  589:         }
1.27    ! stredwic  590:         if($totalTries) {
        !           591: 	    my $DisFac = ($totalAwarded/$totalTries);
1.1       albertel  592: 	    my $DisFactor = sprintf( "%.4f", $DisFac );
1.27    ! stredwic  593: 	    $discriminantFactor{$DisFactor}=$Dis;
1.1       albertel  594: 	}
                    595:     }
                    596: 
1.27    ! stredwic  597:     return (\%discriminantFactor, \@list);
1.1       albertel  598: }
                    599: 
                    600: sub MySort {          
1.6       minaeibi  601:     if ( $Pos > 0 ) {
1.1       albertel  602: 	if ($ENV{'form.order'} eq 'Descending') {$b <=> $a;}
                    603: 	else { $a <=> $b; }
                    604:     }
                    605:     else {
                    606: 	if ($ENV{'form.order'} eq 'Descending') {$b cmp $a;}
                    607: 	else { $a cmp $b; }
                    608:     }
                    609: }
                    610: 
1.27    ! stredwic  611: sub BuildStatisticsTable {
        !           612:     my ($cache,$discriminantFactor,$list,$headings)=@_;
1.1       albertel  613: 
1.27    ! stredwic  614:     my $p_count = 0;
        !           615:     my $nIndex = 0;
        !           616:     my $dummy;
        !           617:     my $p_val;
        !           618:     my $ResId;
        !           619:     my $NoElements = scalar @$list;
1.15      minaeibi  620: 
1.27    ! stredwic  621:     foreach my $sequence (split(':', $cache->{'orderedSequences'})) {
        !           622:         if($cache->{'ProblemStatisticsMap'} ne 'All Maps'  &&
        !           623:            $cache->{'ProblemStatisticsMap'} ne $cache->{$sequence.':title'}) {
        !           624:             next;
        !           625:         }
1.15      minaeibi  626: 
1.27    ! stredwic  627: 	&CreateProblemStatisticsTableHeading($cache->{'DisplayFormat'},
        !           628:                                              $cache->{$sequence.':source'}, 
        !           629:                                              $cache->{$sequence.':title'},
        !           630:                                              $headings);
1.5       minaeibi  631: 	my ($Hid,$pr)=split(/\:/,$mapsort{$_});
                    632: 	my @lpr=split(/\&/,$pr);
                    633: 	for (my $i=1; $i<=$#lpr; $i++) {
                    634: 	    my %storestats=();
1.27    ! stredwic  635: 	    my ($PrOrd,$Prob,$Tries,$Wrongs,$Code)=split(/\&/,$list->[$nIndex]);
1.5       minaeibi  636: 	    my $Temp = $Prob;
                    637: 	    my $MxTries = 0;
                    638: 	    my $TotalTries = 0;
                    639: 	    my $YES = 0;
                    640: 	    my $Incorrect = 0;
                    641: 	    my $Override = 0;
                    642: 	    my $StdNo = 0;
                    643: 	    my @StdLst;
                    644: 	    while ( $PrOrd == $lpr[$i] ) 
                    645: 	    {
1.27    ! stredwic  646: 		$nIndex++;
1.5       minaeibi  647: 		$StdNo++;
                    648: 		$StdLst[ $StdNo ] = $Tries;
                    649: 		$TotalTries += $Tries;
                    650: 		if ( $MxTries < $Tries ) { $MxTries = $Tries; } 
                    651: 		if ( $Code eq 'C' ){ $YES++; }
                    652: 		elsif( $Code eq 'I' ) { $Incorrect++; }
                    653: 		elsif( $Code eq 'O' ) { $Override++; }
                    654: 		elsif( $Code eq 'U' ) { $StdNo--; }
1.27    ! stredwic  655: 		($PrOrd,$Prob,$Tries,$Wrongs,$Code)=split(/\&/,$list->[$nIndex]);
1.5       minaeibi  656: 	    }	
                    657: 
                    658: 	    $p_count++;
                    659: 	    my $Dummy;
                    660: 	    ($ResId,$Dummy)=split(/\*/,$Temp);
1.1       albertel  661: 
1.5       minaeibi  662: 	    $Temp = '<a href="'.$hash{'src_'.$ResId}.
                    663:                 '" target="_blank">'.$hash{'title_'.$ResId}.$Dummy.'</a>';
1.15      minaeibi  664: 
1.5       minaeibi  665: 	    my $res = &Apache::lonnet::declutter($hash{'src_'.$ResId});
                    666: 	    my $urlres=$res;
1.1       albertel  667: 
1.5       minaeibi  668: 	    $ResId=~/(\d+)\.(\d+)/;
                    669: 	    my $Map = &Apache::lonnet::declutter( $hash{'map_id_'.$1} );
                    670: 	    $urlres=$Map;
1.1       albertel  671:  
1.5       minaeibi  672: 	    $res = '<a href="'.$hash{'src_'.$ResId}.'">'.$res.'</a>';
                    673: 	    #$Map = '<a href="'.$Map.'">'.$res.'</a>';
1.1       albertel  674: 
                    675: #------------------------ Compute the Average of Tries about one problem
1.5       minaeibi  676: 	    my $Average = ($StdNo) ? $TotalTries/$StdNo : 0;
1.1       albertel  677: 
1.5       minaeibi  678: 	    $storestats{$ENV{'request.course.id'}.'___'.$urlres.'___timestamp'}=time;       
                    679: 	    $storestats{$ENV{'request.course.id'}.'___'.$urlres.'___stdno'}=$StdNo;
                    680: 	    $storestats{$ENV{'request.course.id'}.'___'.$urlres.'___avetries'}=$Average;
1.1       albertel  681:    
                    682: #-------------------------------- Compute percentage of Wrong tries
1.5       minaeibi  683: 	    my $Wrong = ( $StdNo ) ? 100 * ( $Incorrect / $StdNo ) : 0;
1.1       albertel  684: 
                    685: #-------------------------------- Compute Standard Deviation
1.5       minaeibi  686: 	    my $StdDev = 0; 
                    687: 	    if ( $StdNo > 1 ) {
                    688: 		for ( my $n = 0; $n < $StdNo; $n++ ) {
                    689: 		    my $Dif = $StdLst[ $n ]-$Average;
                    690: 		    $StdDev += $Dif*$Dif;
                    691: 		} 
                    692: 		$StdDev /= ( $StdNo - 1 );
                    693: 		$StdDev = sqrt( $StdDev );
                    694: 	    }
1.1       albertel  695: 
                    696: #-------------------------------- Compute Degree of Difficulty
1.5       minaeibi  697: 	    my $DoDiff = 0;
                    698: 	    if( $TotalTries > 0 ) {
                    699: 		$DoDiff = 1 - ( ( $YES + $Override ) / $TotalTries );
1.1       albertel  700: #	    $DoDiff =  ($TotalTries)/($YES + $Override+ 0.1);	    
1.5       minaeibi  701: 	    }
1.1       albertel  702:        
1.5       minaeibi  703: 	    $storestats{$ENV{'request.course.id'}.'___'.$urlres.'___difficulty'}=$DoDiff;
1.1       albertel  704: 
                    705: #-------------------------------- Compute the Skewness
1.5       minaeibi  706: 	    my $Skewness = 0;
                    707: 	    my $Sum = 0; 
                    708: 	    if ( $StdNo > 0 && $StdDev > 0 ) {
                    709: 		for ( my $n = 0; $n < $StdNo; $n++ ) {
                    710: 		    my $Dif = $StdLst[ $n ]-$Average;
                    711: 		    $Skewness += $Dif*$Dif*$Dif;
                    712: 		} 
                    713: 		$Skewness /= $StdNo;
1.15      minaeibi  714: 		$Skewness /= $StdDev*$StdDev*$StdDev;
1.5       minaeibi  715: 	    }
1.7       minaeibi  716: 
                    717: #--------------------- Compute the Discrimination Factors
1.27    ! stredwic  718:             my ($Up1,$Up2)=split(/\:/,':');#jason$DisUp->{$lpr[$i]});
        !           719: 	    my ($Lw1,$Lw2)=split(/\:/,':');#jason$DisLow->{$lpr[$i]});
1.8       minaeibi  720: 	    my $Dis1 = $Up1 - $Lw1;
                    721: 	    my $Dis2 = $Up2 - $Lw2;
                    722: 	    my $_D1 = sprintf("%.2f", $Dis1);
                    723: 	    my $_D2 = sprintf("%.2f", $Dis2);
1.7       minaeibi  724: 
1.1       albertel  725: #-----------------  Some restition in presenting the float numbers
1.5       minaeibi  726: 	    my $Avg = sprintf( "%.2f", $Average );
                    727: 	    my $Wrng = sprintf( "%.1f", $Wrong );
                    728: 	    my $SD = sprintf( "%.1f", $StdDev );
                    729: 	    my $DoD = sprintf( "%.2f", $DoDiff );
                    730: 	    my $Sk = sprintf( "%.1f", $Skewness );
1.15      minaeibi  731: 	    my $join = $lpr[$i].'&'.$Temp.'&'.$StdNo.'&'.
1.12      minaeibi  732:                        $TotalTries.'&'.$MxTries.'&'.$Avg.'&'.
                    733:                        $YES.'&'.$Override.'&'.$Wrng.'&'.$DoD.'&'.
1.15      minaeibi  734: 		       $SD.'&'.$Sk.'&'.$_D1.'&'.$_D2.'&'.
                    735:                        $Prob;
1.5       minaeibi  736: 	    $CachData{($p_count-1)}=$join;
                    737: 
                    738: 	    $urlres=~/^(\w+)\/(\w+)/;
                    739: 	    if ($StdNo) { 
                    740: 		&Apache::lonnet::put('resevaldata',\%storestats,$1,$2); 
                    741: 	    }
1.1       albertel  742: #-------------------------------- Row of statistical table
1.27    ! stredwic  743:             &TableRow($cache,$join,$i,($p_count-1));
1.5       minaeibi  744: 	}
1.27    ! stredwic  745: 	&CloseTable($cache);
1.1       albertel  746:     }
1.15      minaeibi  747:     &Close_PrgWin();
1.1       albertel  748: }
                    749: 
1.27    ! stredwic  750: =pod
1.1       albertel  751: sub Cache_Statistics {
1.27    ! stredwic  752:     my ($cache)=@_;
1.1       albertel  753:     my @list = ();
                    754:     my $Useful;
                    755:     my $UnUseful;
1.20      minaeibi  756: #    $r->print('<input type="hidden" name="show" value="excel" />'."\n"); 
1.1       albertel  757:     my %myHeader = reverse( %Header );
                    758:     $Pos = $myHeader{$ENV{'form.sort'}};
1.5       minaeibi  759:     if ($Pos > 0) {$Pos++;}
1.27    ! stredwic  760:     my $p_count = 0;
1.1       albertel  761:     foreach my $key( keys %CachData) { 
1.12      minaeibi  762: 	my @Temp=split(/\&/,$CachData{$key});
1.6       minaeibi  763: 	if ( $Pos == 0 ) {
1.1       albertel  764: 	    ($UnUseful,$Useful)=split(/\>/,$Temp[$Pos]);
                    765: 	}
                    766: 	else {
                    767: 	    $Useful = $Temp[$Pos];
                    768: 	}   
1.12      minaeibi  769: 	$list[$p_count]=$Useful.'@'.$CachData{$key};
1.1       albertel  770:         $p_count++;
                    771:     }
                    772: 
                    773:     @list = sort MySort (@list);
                    774: 
1.27    ! stredwic  775:     my $nIndex=0;
1.5       minaeibi  776: 
                    777:     if ( $Pos == 0 ) {
                    778: 	foreach (sort keys %mapsort) {
                    779: 	    my ($Hid,$pr)=split(/\:/,$mapsort{$_});
1.27    ! stredwic  780: 	    &CreateProblemStatisticsTableHeading($cache,1,$Hid);
1.5       minaeibi  781: 	    my @lpr=split(/\&/,$pr);
                    782: 	    for (my $i=1; $i<=$#lpr; $i++) {
1.27    ! stredwic  783: 		my($Pre, $Post) = split(/\@/,$list[$nIndex]); 
1.12      minaeibi  784: 		#$r->print('<br>'.$Pre.'---'.$Post);
1.27    ! stredwic  785: 		&TableRow($cache,$Post,$i,$nIndex);
        !           786: 		$nIndex++;
1.5       minaeibi  787: 	    }
1.27    ! stredwic  788: 	    &CloseTable($cache);
1.5       minaeibi  789: 	}
                    790:     }
                    791:     else {
1.27    ! stredwic  792: 	&CreateProblemStatisticsTableHeading($cache,0);
        !           793: 	for ( my $nIndex = 0; $nIndex < $p_count; $nIndex++ ) {
        !           794: 	    my($Pre, $Post) = split(/\@/,$list[$nIndex]); 
        !           795: 	    &TableRow($cache,$Post,$nIndex,$nIndex);
1.5       minaeibi  796: 	} 
1.27    ! stredwic  797: 	&CloseTable($cache);
1.5       minaeibi  798:     }
                    799: }
1.27    ! stredwic  800: =cut
1.5       minaeibi  801: sub TableRow {
1.27    ! stredwic  802:     my ($cache,$Str,$Idx,$RealIdx)=@_;
1.12      minaeibi  803:     my($PrOrd,$Temp,$StdNo,$TotalTries,$MxTries,$Avg,$YES,$Override,
                    804:        $Wrng,$DoD,$SD,$Sk,$_D1,$_D2,$Prob)=split(/\&/,$Str);	
1.27    ! stredwic  805:     if($cache->{'DisplayFormat'} eq 'Display CSV Format') {
1.18      minaeibi  806:         my ($ResId,$Dummy)=split(/\*/,$Prob);
                    807:         my $Ptr =  "\n".'<br>'.
                    808:                "\n".'"'.($RealIdx+1).'",'.
                    809:                "\n".'"'.$hash{'title_'.$ResId}.$Dummy.'",'.
                    810:                "\n".'"'.$hash{'src_'.$ResId}.'",'.
                    811:                "\n".'"'.$StdNo.'",'.
                    812:                "\n".'"'.$TotalTries.'",'.
                    813:                "\n".'"'.$MxTries.'",'.
                    814:                "\n".'"'.$Avg.'",'.
                    815:                "\n".'"'.$YES.'",'.
                    816:                "\n".'"'.$Override.'",'.
                    817:                "\n".'"'.$Wrng.'",'.
                    818:                "\n".'"'.$DoD.'",'.
                    819:                "\n".'"'.$SD.'",'.
                    820:                "\n".'"'.$Sk.'",'.
                    821:                "\n".'"'.$_D1.'",'.
                    822: 	       "\n".'"'.$_D2.'"';
                    823:         $r->print("\n".$Ptr);
1.27    ! stredwic  824:     } else {
1.18      minaeibi  825:         my $Ptr =  "\n".'<tr>'.
1.5       minaeibi  826:                "\n".'<td>'.($RealIdx+1).'</td>'.
1.13      minaeibi  827:           #     "\n".'<td>'.$PrOrd.$Temp.'</td>'.
1.8       minaeibi  828:                "\n".'<td>'.$Temp.'</td>'.
1.25      minaeibi  829:                "\n".'<td bgcolor='.$color{"yellow"}.'> '.$StdNo.'</td>'.
                    830:                "\n".'<td bgcolor='.$color{"yellow"}.'>'.$TotalTries.'</td>'.
                    831:                "\n".'<td bgcolor='.$color{"yellow"}.'>'.$MxTries.'</td>'.
                    832:                "\n".'<td bgcolor='.$color{"gb"}.'>'.$Avg.'</td>'.
                    833:                "\n".'<td bgcolor='.$color{"gb"}.'> '.$YES.'</td>'.
                    834:                "\n".'<td bgcolor='.$color{"gb"}.'> '.$Override.'</td>'.
                    835:                "\n".'<td bgcolor='.$color{"red"}.'> '.$Wrng.'</td>'.
                    836:                "\n".'<td bgcolor='.$color{"red"}.'> '.$DoD.'</td>'.
                    837:                "\n".'<td bgcolor='.$color{"green"}.'> '.$SD.'</td>'.
                    838:                "\n".'<td bgcolor='.$color{"green"}.'> '.$Sk.'</td>'.
                    839:                "\n".'<td bgcolor='.$color{"purple"}.'> '.$_D1.'</td>'.
                    840: 	       "\n".'<td bgcolor='.$color{"purple"}.'> '.$_D2.'</td>';
1.18      minaeibi  841:         $r->print("\n".$Ptr.'</tr>' );
                    842:     }
1.5       minaeibi  843:     $GraphDat{$RealIdx}=$DoD.':'.$Wrng;
1.1       albertel  844: }
                    845: 
1.27    ! stredwic  846: sub StatusOptions {
        !           847:     my ($cache)=@_;
        !           848: 
        !           849:     my $Status = $cache->{'Status'};
        !           850:     my $OpSel1 = '';
        !           851:     my $OpSel2 = '';
        !           852:     my $OpSel3 = '';
        !           853: 
        !           854:     if($Status eq 'Any')         { $OpSel3 = ' selected'; }
        !           855:     elsif($Status eq 'Expired' ) { $OpSel2 = ' selected'; }
        !           856:     else                         { $OpSel1 = ' selected'; }
        !           857: 
        !           858:     my $Ptr = '';
        !           859:     $Ptr .= '<tr><td align="right"><b>Student Status:</b></td>'."\n";
        !           860:     $Ptr .= '<td align="left"><select name="Status">';
        !           861:     $Ptr .= '<option'.$OpSel1.'>Active</option>'."\n";
        !           862:     $Ptr .= '<option'.$OpSel2.'>Expired</option>'."\n";
        !           863:     $Ptr .= '<option'.$OpSel3.'>Any</option>'."\n";
        !           864:     $Ptr .= '</select></td></tr>'."\n";
        !           865: 
        !           866:     return $Ptr;
        !           867: }
        !           868: 
        !           869: sub AscendOrderOptions {
        !           870:     my ($cache)=@_;
        !           871: 
        !           872:     my $order = $cache->{'Ascend'};
        !           873:     my $OpSel1 = '';
        !           874:     my $OpSel2 = '';
        !           875: 
        !           876:     if($order eq 'Ascending') {
        !           877:         $OpSel1 = ' selected';
        !           878:     } else {
        !           879:         $OpSel2 = ' selected';
        !           880:     }
        !           881: 
        !           882:     my $Ptr = '';
        !           883:     $Ptr .= '<tr><td align="right"><b>Sorting Type:</b></td>'."\n";
        !           884:     $Ptr .= '<td align="left"><select name="Ascend">'."\n";
        !           885:     $Ptr .= '<option'.$OpSel1.'>Ascending</option>'."\n".
        !           886: 	    '<option'.$OpSel2.'>Descending</option>'."\n";
        !           887:     $Ptr .= '</select></td></tr>'."\n";
        !           888: 
        !           889:     return $Ptr;
        !           890: }
        !           891: 
        !           892: sub ProblemStatisticsButtons {
        !           893:     my ($cache)=@_;
        !           894: 
        !           895:     my $Ptr = '<tr><td></td><td align="left">';
        !           896:     $Ptr .= '<input type=submit name="ProblemStatisticsRecalculate" ';
        !           897:     $Ptr .= 'value="Recalculate Statistics"/>'."\n";
        !           898:     $Ptr .= '&nbsp;&nbsp;&nbsp;';
        !           899:     $Ptr .= '<input type="submit" name="DoDiffGraph" ';
        !           900:     $Ptr .= 'value="DoDiff Graph" />'."\n";
        !           901:     $Ptr .= '&nbsp;&nbsp;&nbsp;';
        !           902:     $Ptr .= '<input type="submit" name="PercentWrongGraph" ';
        !           903:     $Ptr .= 'value="%Wrong Graph" />'."\n";
        !           904:     $Ptr .= '&nbsp;&nbsp;&nbsp;';
        !           905:     $Ptr .= '<input type="submit" name="DisplayCSVFormat" ';
        !           906:     if($cache->{'DisplayFormat'} eq 'Display CSV Format') {
        !           907:         $Ptr .= 'value="Display CSV Format" />'."\n";
        !           908:     } else {
        !           909:         $Ptr .= 'value="Display Table Format" />'."\n";
        !           910:     }
        !           911:     $Ptr .= '</td></tr>';
        !           912: 
        !           913:     return $Ptr;
        !           914: }
        !           915: 
        !           916: sub ProblemStatisticsLegend {
        !           917:     my $Ptr = '';
        !           918:     $Ptr = '<table border="0">';
        !           919:     $Ptr .= '<tr><td>';
        !           920:     $Ptr .= '<b>#Stdnts</b>:</td>';
        !           921:     $Ptr .= '<td>Total Number of Students opened the problem.';
        !           922:     $Ptr .= '</td></tr><tr><td>';
        !           923:     $Ptr .= '<b>Tries</b>:</td>';
        !           924:     $Ptr .= '<td>Total Number of Tries for solving the problem.';
        !           925:     $Ptr .= '</td></tr><tr><td>';
        !           926:     $Ptr .= '<b>Mod</b>:</td>';
        !           927:     $Ptr .= '<td>Maximunm Number of Tries for solving the problem.';
        !           928:     $Ptr .= '</td></tr><tr><td>';
        !           929:     $Ptr .= '<b>Mean</b>:</td>';
        !           930:     $Ptr .= '<td>Average Number of the tries. [ Tries / #Stdnts ]';
        !           931:     $Ptr .= '</td></tr><tr><td>';
        !           932:     $Ptr .= '<b>#YES</b>:</td>';
        !           933:     $Ptr .= '<td>Number of students solved the problem correctly.';
        !           934:     $Ptr .= '</td></tr><tr><td>';
        !           935:     $Ptr .= '<b>#yes</b>:</td>';
        !           936:     $Ptr .= '<td>Number of students solved the problem by override.';
        !           937:     $Ptr .= '</td></tr><tr><td>';
        !           938:     $Ptr .= '<b>%Wrng</b>:</td>';
        !           939:     $Ptr .= '<td>Percentage of students tried to solve the problem ';
        !           940:     $Ptr .= 'but still incorrect. [ 100*((#Stdnts-(#YES+#yes))/#Stdnts) ]';
        !           941:     $Ptr .= '</td></tr><tr><td>';
        !           942: #    Kashy formula
        !           943: #    '<b>  DoDiff </b>: Degree of Difficulty of the problem.<br>'.
        !           944: #    '[ Tries/(#YES+#yes+0.1) ]<br>'.
        !           945:     #Gerd formula
        !           946:     $Ptr .= '<b>DoDiff</b>:</td>';
        !           947:     $Ptr .= '<td>Degree of Difficulty of the problem.  ';
        !           948:     $Ptr .= '[ 1 - ((#YES+#yes) / Tries) ]';
        !           949:     $Ptr .= '</td></tr><tr><td>';
        !           950:     $Ptr .= '<b>S.D.</b>:</td>';
        !           951:     $Ptr .= '<td>Standard Deviation of the tries.  ';
        !           952:     $Ptr .= '[ sqrt(sum((Xi - Mean)^2)) / (#Stdnts-1) ';
        !           953:     $Ptr .= 'where Xi denotes every student\'s tries ]';
        !           954:     $Ptr .= '</td></tr><tr><td>';
        !           955:     $Ptr .= '<b>Skew.</b>:</td>';
        !           956:     $Ptr .= '<td>Skewness of the students tries.';
        !           957:     $Ptr .= '[(sqrt( sum((Xi - Mean)^3) / #Stdnts)) / (S.D.^3)]';
        !           958:     $Ptr .= '</td></tr><tr><td>';
        !           959:     $Ptr .= '<b>Dis.F.</b>:</td>';
        !           960:     $Ptr .= '<td>Discrimination Factor: A Standard for evaluating the ';
        !           961:     $Ptr .= 'problem according to a Criterion<br>';
        !           962:     $Ptr .= '<b>[Applied Criterion in %27 Upper Students - ';
        !           963:     $Ptr .= 'Applied the same Criterion in %27 Lower Students]</b><br>';
        !           964:     $Ptr .= '<b>1st Criterion</b> for Sorting the Students: ';
        !           965:     $Ptr .= '<b>Sum of Partial Credit Awarded / Total Number of Tries</b><br>';
        !           966:     $Ptr .= '<b>2nd Criterion</b> for Sorting the Students: ';
        !           967:     $Ptr .= '<b>Total number of Correct Answers / Total Number of Tries</b>';
        !           968:     $Ptr .= '</td></tr></table>';
        !           969: 
        !           970:     return $Ptr;
        !           971: }
        !           972: 
        !           973: #---- END Problem Statistics Web Page ----------------------------------------
        !           974: 
        !           975: #---- Problem Statistics Graph Web Page --------------------------------------
1.1       albertel  976: 
                    977: sub GetGraphData {
1.27    ! stredwic  978:     my ($whichGraph, $courseID)=@_;
        !           979:     my $Col=0;
        !           980:     my $graphTitle='';
1.1       albertel  981:     my $data='';
                    982:     my $count = 0;
                    983:     my $Max = 0;
1.27    ! stredwic  984:     my $graphData='Graph data does not exist.';
1.1       albertel  985:     my $GraphDB = "/home/httpd/perl/tmp/$ENV{'user.name'}".
1.27    ! stredwic  986:                   "_$ENV{'user.domain'}_$courseID\_graph.db";
        !           987:     if(-e $GraphDB) {
        !           988: 	if(tie(%GraphDat,'GDBM_File',"$GraphDB",&GDBM_READER,0640)) {
        !           989: 	    if($whichGraph eq 'DiffGraph') {
        !           990: 		$graphTitle = 'Degree-of-Difficulty';
1.1       albertel  991: 		$Col = 0;
1.27    ! stredwic  992: 	    } else {
        !           993: 		$graphTitle = 'Wrong-Percentage';
1.1       albertel  994: 		$Col = 1;
                    995: 	    }
                    996: 	    foreach (sort NumericSort keys %GraphDat) { 
                    997: 		my @Temp=split(/\:/,$GraphDat{$_});
                    998:                 my $inf = $Temp[$Col]; 
1.27    ! stredwic  999: 		if($Max < $inf) {
        !          1000:                     $Max = $inf;
        !          1001:                 }
1.1       albertel 1002: 		$data .= $inf.',';
                   1003: 		$count++;
                   1004: 	    }
1.27    ! stredwic 1005: 	    if($Max > 1) { 
1.15      minaeibi 1006: 		$Max += (10 - $Max % 10);
                   1007: 		$Max = int($Max);
1.27    ! stredwic 1008: 	    } else { 
        !          1009:                 $Max = 1;
        !          1010:             }
1.1       albertel 1011:             untie(%GraphDat);
1.27    ! stredwic 1012: 	    my $Course = $ENV{'course.'.$courseID.'.description'};
1.1       albertel 1013: 	    $Course =~ s/\ /"_"/eg;
1.27    ! stredwic 1014: 	    $graphData  = $Course.'&'.'Problems'.'&'.$graphTitle.'&'.$Max.'&';
        !          1015:             $graphData .= $count.'&'.$data;
        !          1016: 	} else {
        !          1017: 	    $graphData = "Unable to tie hash to db file";
        !          1018: 	}
        !          1019:     }
        !          1020: 
        !          1021:     return $graphData;
        !          1022: }
        !          1023: 
        !          1024: #---- END Problem Statistics Graph Web Page ----------------------------------
        !          1025: 
        !          1026: #---- Problem Analysis Web Page ----------------------------------------------
        !          1027: 
        !          1028: sub IntervalOptions {
        !          1029:     my ($cache)=@_;
        !          1030: 
        !          1031:     my $interval = 1;
        !          1032:     for(my $n=1; $n<=7; $n++) {
        !          1033:         if($cache->{'Interval'} == $n) {
        !          1034:             $interval = $n;
        !          1035:         }
        !          1036:     }
        !          1037: 
        !          1038:     my $Ptr = '<br><b>Select number of intervals</b>'."\n".
        !          1039:        	      '<select name="Interval">'."\n";
        !          1040:     for(my $n=1; $n<=7;$ n++) {
        !          1041: 	$Ptr .= '<option';
        !          1042:         if($interval == $n) {
        !          1043:             $Ptr .= ' selected';
        !          1044:         }
        !          1045: 	$Ptr .= '>'.$n."</option>"."\n";
        !          1046:     }
        !          1047:     $Ptr .= '</select>'."\n";
        !          1048: 
        !          1049:     return $Ptr;
        !          1050: }
        !          1051: 
        !          1052: sub OptionResponseTable {
        !          1053:     my ($cache)=@_;
        !          1054:     my $Str = '';
        !          1055:     $Str .= '<br><b> Option Response Problems in this course:</b>'."\n";
        !          1056:     $Str .= '<br><br>'."\n";
        !          1057:     $Str .= "<table border=2><tr><th> \# </th><th> Problem Title </th>";
        !          1058:     $Str .= '<th> Resource </th><th> Analysis  </th></tr>'."\n";
        !          1059: 
        !          1060:     my $number=1;
        !          1061:     foreach (split(':::',$cache->{'OptionResponses'})) {
        !          1062:         my ($uri,$title,$part,$problem)=split('::',$_);
        !          1063:         my $Temp = '<a href="'.$uri.'" target="_blank">'.$title.'</a>';
        !          1064:         $Str .= '<tr>';
        !          1065:         $Str .= '<td> '.$number.' </td>';
        !          1066:         $Str .= '<td bgcolor="'.$color{"green"}.'"> '.$Temp.' </td>';
        !          1067:         $Str .= '<td bgcolor="'.$color{"yellow"}.'"> '.$uri.' </td>';
        !          1068:         $Str .= '<td><input type="submit" name="Analyze:::'.$uri.':::';
        !          1069:         $Str .= $title.':::'.$part.':::'.$problem.'" value="';
        !          1070:         $Str .= 'Analyze" /></td></tr>'."\n";
        !          1071:         $number++;
        !          1072:     }
        !          1073:     $Str .= '</table>'."\n";
        !          1074: 
        !          1075:     return $Str;
        !          1076: }
        !          1077: 
        !          1078: #---- END Problem Analysis Web Page ------------------------------------------
        !          1079: 
        !          1080: #---- Student Assessment Web Page --------------------------------------------
        !          1081: 
        !          1082: sub MapOptions {
        !          1083:     my ($cache, $page)=@_;
        !          1084:     my $Ptr = '<tr>';
        !          1085:     $Ptr .= '<td align="right"><b>Select Map</b></td>'."\n";
        !          1086:     $Ptr .= '<td align="left"><select name="Maps">'."\n";
        !          1087: 
        !          1088:     my $selected = 0;
        !          1089:     foreach my $sequence (split(':',$cache->{'orderedSequences'})) {
        !          1090: 	$Ptr .= '<option';
        !          1091:         if($cache->{$page.'Map'} eq $cache->{$sequence.':title'}) {
        !          1092:             $Ptr .= ' selected';
        !          1093:             $selected = 1;
        !          1094:         }
        !          1095: 	$Ptr .= '>'.$cache->{$sequence.':title'}.'</option>'."\n";	     
        !          1096:     }
        !          1097:     $Ptr .= '<option';
        !          1098:     if(!$selected) {
        !          1099:         $Ptr .= ' selected';
        !          1100:     }
        !          1101:     $Ptr .= '>All Maps</option>'."\n";
        !          1102: 
        !          1103:     $Ptr .= '</select></td></tr>'."\n";
        !          1104: 
        !          1105:     return $Ptr;
        !          1106: }
        !          1107: 
        !          1108: sub StudentOptions {
        !          1109:     my ($students, $selectedName)=@_;
        !          1110: 
        !          1111:     my $Ptr ='<tr>';
        !          1112:     $Ptr .= '<td align="right"><b>Select Student</b></td>'."\n";
        !          1113:     $Ptr .= '<td align="left"><select name="Students">'."\n";
        !          1114: 
        !          1115:     my $selected=0;
        !          1116:     foreach (@$students) {
        !          1117:         my ($name) = split(':',$_);
        !          1118: 	$Ptr .= '<option';
        !          1119: 	if($selectedName eq $name) {
        !          1120:             $Ptr .= ' selected';
        !          1121:             $selected = 1;
        !          1122:         }
        !          1123:         $Ptr .= '>'.$name.'</option>'."\n";	     
        !          1124:     }
        !          1125: 
        !          1126:     $Ptr .= '<option';
        !          1127:     if(!$selected) {
        !          1128:         $Ptr .= ' selected';
        !          1129:     }
        !          1130:     $Ptr .= '>No Student Selected</option>'."\n";
        !          1131: 
        !          1132:     $Ptr .= '</select></td></tr>'."\n";
        !          1133: 
        !          1134:     return $Ptr;
        !          1135: }
        !          1136: 
        !          1137: # ------ Create different Student Report 
        !          1138: sub StudentReport {
        !          1139:     my ($cache, $name)=@_;
        !          1140: 
        !          1141:     my $Str = '';
        !          1142:     if($cache->{$name.':error'} =~ /course/) {
        !          1143:         my ($username)=split(':',$name);
        !          1144:         $Str .= '<b><font color="blue">No course data for student </font>';
        !          1145:         $Str .= '<font color="red">'.$username.'.</font></b><br>';
        !          1146:         return $Str;
        !          1147:     }
        !          1148: 
        !          1149:     $Str .= "<table border=2><tr><th> \# </th><th> Set Title </th>";
        !          1150:     $Str .= '<th> Results </th><th> Tries </th></tr>'."\n";
        !          1151: 
        !          1152:     my $codes;
        !          1153:     my $attempts;
        !          1154:     foreach my $sequence (split(':', $cache->{'orderedSequences'})) {
        !          1155:         if($cache->{'StudentAssessmentMap'} ne 'All Maps'  &&
        !          1156:            $cache->{'StudentAssessmentMap'} ne $cache->{$sequence.':title'}) {
        !          1157:             next;
        !          1158:         }
        !          1159: 
        !          1160:         $Str .= '<tr><td>'.$sequence.'</td>';
        !          1161:         $Str .= '<td>'.$cache->{$sequence.':title'}.'</td>';
        !          1162: 
        !          1163:         $codes = '';
        !          1164:         $attempts = '';
        !          1165:         foreach my $problemID (split(':', $cache->{$sequence.':problems'})) {
        !          1166:             my $problem = $cache->{$problemID.':problem'};
        !          1167:             my $LatestVersion = $cache->{$name.':version:'.$problem};
        !          1168: 
        !          1169:             # Output dashes for all the parts of this problem if there
        !          1170:             # is no version information about the current problem.
        !          1171:             if(!$LatestVersion) {
        !          1172:                 foreach my $part (split(/\:/,$cache->{$sequence.':'.
        !          1173:                                                       $problemID.
        !          1174:                                                       ':parts'})) {
        !          1175: 		    $codes    .= "-,";
        !          1176:                     $attempts .= "0,"; 
        !          1177:                 }
        !          1178:                 next;
        !          1179:             }
        !          1180: 
        !          1181:             my %partData=undef;
        !          1182:             # Initialize part data, display skips correctly
        !          1183:             # Skip refers to when a student made no submissions on that
        !          1184:             # part/problem.
        !          1185:             foreach my $part (split(/\:/,$cache->{$sequence.':'.
        !          1186:                                                   $problemID.
        !          1187:                                                   ':parts'})) {
        !          1188:                 $partData{$part.':tries'}=0;
        !          1189:                 $partData{$part.':code'}='-';
        !          1190:             }
        !          1191: 
        !          1192:             # Looping through all the versions of each part, starting with the
        !          1193:             # oldest version.  Basically, it gets the most recent 
        !          1194:             # set of grade data for each part.
        !          1195: 	    for(my $Version=1; $Version<=$LatestVersion; $Version++) {
        !          1196:                 foreach my $part (split(/\:/,$cache->{$sequence.':'.
        !          1197:                                                       $problemID.
        !          1198:                                                       ':parts'})) {
        !          1199: 
        !          1200:                     if(!defined($cache->{$name.":$Version:$problem".
        !          1201:                                                ":resource.$part.solved"})) {
        !          1202:                         # No grade for this submission, so skip
        !          1203:                         next;
        !          1204:                     }
        !          1205: 
        !          1206:                     my $tries=0;
        !          1207:                     my $code='U';
        !          1208: 
        !          1209:                     $tries = $cache->{$name.":$Version:$problem".
        !          1210:                                       ":resource.$part.tries"};
        !          1211:                     $partData{$part.':tries'}=($tries) ? $tries : 0;
        !          1212: 
        !          1213:                     my $val = $cache->{$name.":$Version:$problem".
        !          1214:                                        ":resource.$part.solved"};
        !          1215:                     if    ($val eq 'correct_by_student')   {$code = 'Y';} 
        !          1216:                     elsif ($val eq 'correct_by_override')  {$code = 'y';}
        !          1217:                     elsif ($val eq 'incorrect_attempted')  {$code = 'N';} 
        !          1218:                     elsif ($val eq 'incorrect_by_override'){$code = 'N';}
        !          1219:                     elsif ($val eq 'excused')              {$code = 'x';}
        !          1220:                     $partData{$part.':code'}=$code;
        !          1221:                 }
        !          1222:             }
        !          1223: 
        !          1224:             # Loop through all the parts for the current problem in the 
        !          1225:             # correct order and prepare the output
        !          1226:             foreach (split(/\:/,$cache->{$sequence.':'.$problemID.
        !          1227:                                          ':parts'})) {
        !          1228:                 $codes    .= $partData{$_.':code'}.',';
        !          1229:                 $attempts .= $partData{$_.':tries'}.','; 
        !          1230:             }
        !          1231:         }
        !          1232:         $codes    =~ s/,$//;
        !          1233:         $attempts =~ s/,$//;
        !          1234:         $Str .= '<td>'.$codes.'</td>';
        !          1235:         $Str .= '<td>'.$attempts.'</td>';
        !          1236:         $Str .= '</tr>'."\n";
        !          1237:     }
        !          1238: 
        !          1239:     $Str .= '</table>'."\n";
        !          1240: 
        !          1241:     return $Str;
        !          1242: }
        !          1243: 
        !          1244: #---- END Student Assessment Web Page ----------------------------------------
        !          1245: 
        !          1246: #---- Menu Web Page ----------------------------------------------------------
        !          1247: 
        !          1248: sub Title {
        !          1249:     my ($downloadTime)=@_;
        !          1250: 
        !          1251:     my $Ptr = '';
        !          1252: 
        !          1253:     $Ptr .= '<html><head><title>LON-CAPA Statistics</title></head>'."\n";
        !          1254:     $Ptr .= '<body bgcolor="#FFFFFF">'."\n";
        !          1255:     $Ptr .= '<script>window.focus(); window.width=500;window.height=500;';
        !          1256:     $Ptr .= '</script>'."\n";
        !          1257:     $Ptr .= '<img align=right src=/adm/lonIcons/lonlogos.gif>'."\n";
        !          1258:     $Ptr .= '<h1> Course : "';
        !          1259:     $Ptr .= $ENV{'course.'.$ENV{'request.course.id'}.'.description'};
        !          1260:     $Ptr .= '"</h1>'."\n";
        !          1261:     $Ptr .= '<h3>'.$downloadTime.'</h3>';
        !          1262: 
        !          1263:     return $Ptr;
        !          1264: }
        !          1265: 
        !          1266: sub CreateMenuForm {
        !          1267:     my ($cache)=@_;
        !          1268:     my $Ptr = '<table border="0">';
        !          1269:     $Ptr .= '<tr><td><input type="submit" name="ProblemStatistics" ';
        !          1270:     $Ptr .= 'value="Problem Stats"/>';
        !          1271:     $Ptr .= '</td></tr>'."\n";
        !          1272: 
        !          1273:     if(defined($cache->{'OptionResponses'})) {
        !          1274:         $Ptr .= '<tr><td><input type="submit" name="ProblemAnalysis" ';
        !          1275:         $Ptr .= 'value="Problem Analysis"/>';
        !          1276:         $Ptr .= '</td></tr>'."\n";
        !          1277:     }
        !          1278: 
        !          1279:     $Ptr .= '<tr><td><input type="submit" name="StudentAssessment" ';
        !          1280:     $Ptr .= 'value="Student Assessment"/>';
        !          1281:     $Ptr .= '</td></tr>'."\n";
        !          1282:     #$Ptr .= '<input type="submit" name="ActivityLog" value="Activity Log"/>';
        !          1283: 
        !          1284:     $Ptr .= '</table>'."\n";
        !          1285: 
        !          1286:     return $Ptr;
        !          1287: }
        !          1288: 
        !          1289: #---- END Menu Web Page ------------------------------------------------------
        !          1290: 
        !          1291: #---- HELPER FUNCTIONS -------------------------------------------------------
        !          1292: 
        !          1293: sub CheckFormElement {
        !          1294:     my ($cache, $ENVName, $cacheName, $default)=@_;
        !          1295: 
        !          1296:     if(defined($ENV{'form.'.$ENVName})) {
        !          1297:         $cache->{$cacheName} = $ENV{'form.'.$ENVName};
        !          1298:     } elsif(!defined($cache->{$cacheName})) {
        !          1299:         $cache->{$cacheName} = $default;
        !          1300:     }
        !          1301: 
        !          1302:     return;
        !          1303: }
        !          1304: 
        !          1305: sub ProcessFormData{
        !          1306:     my ($cacheDB, $isCached)=@_;
        !          1307:     my %cache;
        !          1308: 
        !          1309:     if(tie(%cache,'GDBM_File',$cacheDB,&GDBM_WRCREAT,0640)) {
        !          1310:         # Select page to display
        !          1311:         if(defined($ENV{'form.ProblemStatistics'}) ||
        !          1312:            defined($ENV{'form.ProblemStatisticsRecalculate'}) || 
        !          1313:            defined($ENV{'form.DisplayCSVFormat'})) {
        !          1314:             $cache{'GoToPage'} = 'ProblemStatistics';
        !          1315:             &CheckFormElement(\%cache, 'DisplayCSVFormat',
        !          1316:                               'DisplayFormat', 'Display Table Format');
        !          1317:             &CheckFormElement(\%cache, 'Ascend','ProblemStatisticsAscend',
        !          1318:                               'Ascending');
        !          1319:             &CheckFormElement(\%cache, 'Maps', 'ProblemStatisticsMap', 
        !          1320:                               'All Maps');
        !          1321:         } elsif(defined($ENV{'form.ProblemAnalysis'})) {
        !          1322:             $cache{'GoToPage'} = 'ProblemAnalysis';
        !          1323:             &CheckFormElement(\%cache, 'Interval', 'Interval', '1');
        !          1324:         } elsif(defined($ENV{'form.StudentAssessment'}) ||
        !          1325:                 defined($ENV{'form.CreateStudentAssessment'}) ||
        !          1326:                 defined($ENV{'form.NextStudent'}) ||
        !          1327:                 defined($ENV{'form.PreviousStudent'})) {
        !          1328:             $cache{'GoToPage'} = 'StudentAssessment';
        !          1329:             if(defined($ENV{'form.NextStudent'})) {
        !          1330:                 $cache{'StudentAssessmentMove'} = 'next';
        !          1331:             } elsif(defined($ENV{'form.PreviousStudent'})) {
        !          1332:                 $cache{'StudentAssessmentMove'} = 'previous';
        !          1333:             } else {
        !          1334:                 $cache{'StudentAssessmentMove'} = 'selected';
        !          1335:             }
        !          1336:             &CheckFormElement(\%cache, 'Maps', 'StudentAssessmentMap', 
        !          1337:                               'All Maps');
        !          1338: 
        !          1339:             &CheckFormElement(\%cache, 'Students', 'StudentAssessmentStudent', 
        !          1340:                               'No Student Selected');
        !          1341:         } elsif(defined($ENV{'form.DoDiffGraph'})) {
        !          1342:             $cache{'GoToPage'} = 'DoDiffGraph';
        !          1343:         } elsif(defined($ENV{'form.PercentWrongGraph'})) {
        !          1344:             $cache{'GoToPage'} = 'PercentWrongGraph';
        !          1345:         } elsif(defined($ENV{'form.ActivityLog'})) {
        !          1346:             $cache{'GoToPage'} = 'ActivityLog';
        !          1347:         } else {
        !          1348:             $cache{'GoToPage'} = 'Menu';
        !          1349:         }
        !          1350: 
        !          1351:         &CheckFormElement(\%cache, 'Status', 'Status', 'Active');
        !          1352: 
        !          1353:         foreach (keys(%ENV)) {
        !          1354:             if(/form\.Analyze:::/) {
        !          1355:                 $cache{'GoToPage'} = 'Analyze';
        !          1356:                 my ($uri, $title, $part, $problem);
        !          1357:                 (undef, $uri, $title, $part, $problem)=split(':::', $_);
        !          1358:                 $cache{'AnalyzeURI'}     = $uri;
        !          1359:                 $cache{'AnalyzeTitle'}   = $title;
        !          1360:                 $cache{'AnalyzePart'}    = $part;
        !          1361:                 $cache{'AnalyzeProblem'} = $problem;
        !          1362: 
        !          1363:                 &CheckFormElement(\%cache, 'Interval', 'Interval', '1');
        !          1364:             }
        !          1365:         }
        !          1366:     }
        !          1367: 
        !          1368:     return;
        !          1369: }
        !          1370: 
        !          1371: =pod
        !          1372: 
        !          1373: =item &SortStudents()
        !          1374: 
        !          1375: Determines which students to display and in which order.  Which are 
        !          1376: displayed are determined by their status(active/expired).  The order
        !          1377: is determined by the sort button pressed (default to username).  The
        !          1378: type of sorting is username, lastname, or section.
        !          1379: 
        !          1380: =over 4
        !          1381: 
        !          1382: Input: $students, $CacheData
        !          1383: 
        !          1384: $students: A array pointer to a list of students (username:domain)
        !          1385: 
        !          1386: $CacheData: A pointer to the hash tied to the cached data
        !          1387: 
        !          1388: Output: \@order
        !          1389: 
        !          1390: @order: An ordered list of students (username:domain)
        !          1391: 
        !          1392: =back
        !          1393: 
        !          1394: =cut
        !          1395: 
        !          1396: sub SortStudents {
        !          1397:     my ($students,$cache)=@_;
        !          1398: 
        !          1399:     my @sorted1Students=();
        !          1400:     foreach (@$students) {
        !          1401:         push(@sorted1Students, $_);
        !          1402:     }
        !          1403: #        my ($end,$start)=split(/\:/,$cache->{$_.':date'});
        !          1404: #        my $active=1;
        !          1405: #        my $now=time;
        !          1406: #        my $Status=$cache->{'form.Status'};
        !          1407: #        $Status = ($Status) ? $Status : 'Active';
        !          1408: #        if((($end) && $now > $end) && (($Status eq 'Active'))) { 
        !          1409: #            $active=0; 
        !          1410: #        }
        !          1411: #        if(($Status eq 'Expired') && ($end == 0 || $now < $end)) {
        !          1412: #            $active=0;
        !          1413: #        }
        !          1414: #        if($active) {
        !          1415: #            push(@sorted1Students, $_);
        !          1416: #        }
        !          1417: #    }
        !          1418: 
        !          1419:     my $Pos = $cache->{'form.ChartSort'};
        !          1420:     my %sortData;
        !          1421:     if($Pos eq 'Last Name') {
        !          1422: 	for(my $index=0; $index<scalar @sorted1Students; $index++) {
        !          1423: 	    $sortData{$cache->{$sorted1Students[$index].':fullname'}}=
        !          1424: 		$sorted1Students[$index];
        !          1425: 	}
        !          1426:     } elsif($Pos eq 'Section') {
        !          1427: 	for(my $index=0; $index<scalar @sorted1Students; $index++) {
        !          1428: 	    $sortData{$cache->{$sorted1Students[$index].':section'}.
        !          1429: 		      $sorted1Students[$index]}=$sorted1Students[$index];
1.1       albertel 1430: 	}
1.27    ! stredwic 1431:     } else {
        !          1432: 	# Sort by user name
        !          1433: 	for(my $index=0; $index<scalar @sorted1Students; $index++) {
        !          1434: 	    $sortData{$sorted1Students[$index]}=$sorted1Students[$index];
1.1       albertel 1435: 	}
                   1436:     }
1.27    ! stredwic 1437: 
        !          1438:     my @order = ();
        !          1439:     foreach my $key (sort(keys(%sortData))) {
        !          1440: 	push (@order,$sortData{$key});
        !          1441:     }
        !          1442: 
        !          1443:     return \@order;
        !          1444: }
        !          1445: 
        !          1446: sub PrepareData {
        !          1447:     my ($c, $cacheDB)=@_;
        !          1448: 
        !          1449:     # Test for access to the cache data
        !          1450:     my $isCached=0;
        !          1451:     my $courseID=$ENV{'request.course.id'};
        !          1452:     my $isRecalculate=0;
        !          1453:     if(defined($ENV{'form.ProblemStatisticsRecalculate'}) ||
        !          1454:        defined($ENV{'form.ChartRecalculate'})) {
        !          1455:         $isRecalculate=1;
        !          1456:     }
        !          1457: 
        !          1458:     $isRecalculate=1;
        !          1459: 
        !          1460:     $isCached=&Apache::loncoursedata::TestCacheData($cacheDB, $isRecalculate);
        !          1461:     if($isCached < 0) {
        !          1462:         return "Unable to tie hash to db file.";
        !          1463:     }
        !          1464:     &ProcessFormData($cacheDB, $isCached);
        !          1465: 
        !          1466:     # Download class list information if not using cached data
        !          1467:     my %cache;
        !          1468:     my @students=();
        !          1469:     if(!$isCached) {
        !          1470:         unless(tie(%cache,'GDBM_File',$cacheDB,&GDBM_WRCREAT,0640)) {
        !          1471:             return "Unable to tie hash to db file.";
        !          1472:         }
        !          1473: 
        !          1474:         my $processTopResourceMapReturn=
        !          1475:             &Apache::loncoursedata::ProcessTopResourceMap(\%cache, $c);
        !          1476:         if($processTopResourceMapReturn ne 'OK') {
        !          1477:             untie(%cache);
        !          1478:             return $processTopResourceMapReturn;
        !          1479:         }
        !          1480: 
        !          1481:         if($c->aborted()) {
        !          1482:             untie(%cache);
        !          1483:             return 'aborted'; 
        !          1484:         }
        !          1485: 
        !          1486:         my $classlist=&Apache::loncoursedata::DownloadStudentNamePIDSection(
        !          1487:                                                                    $courseID, 
        !          1488:                                                                    $c);
        !          1489:         my ($checkForError)=keys(%$classlist);
        !          1490:         if($checkForError =~ /^(con_lost|error|no_such_host)/i ||
        !          1491:            defined($classlist->{'error'})) {
        !          1492:             untie(%cache);
        !          1493:             return "Error getting student data.";
        !          1494:         }
        !          1495: 
        !          1496:         if($c->aborted()) {
        !          1497:             untie(%cache);
        !          1498:             return 'aborted'; 
        !          1499:         }
        !          1500: 
        !          1501:         # Active is a temporary solution, remember to change
        !          1502:         @students=&Apache::loncoursedata::ProcessClassList(\%cache, 
        !          1503:                                                            $classlist, 
        !          1504:                                                            $courseID, 
        !          1505:                                                            'Active', $c);
        !          1506: 
        !          1507:         if($c->aborted()) {
        !          1508:             untie(%cache);
        !          1509:             return 'aborted'; 
        !          1510:         }
        !          1511: 
        !          1512:         untie(%cache);
        !          1513:     } else {
        !          1514:         if(!$c->aborted() && tie(%cache,'GDBM_File',$cacheDB,
        !          1515:                                  &GDBM_READER,0640)) {
        !          1516:             @students=split(/:::/,$cache{'NamesOfStudents'});
        !          1517:         } else {
        !          1518:             return 'aborted';
        !          1519:         }
        !          1520:     }
        !          1521: 
        !          1522:     return ('OK', $isCached, \@students);
        !          1523: }
        !          1524: 
        !          1525: # Create progress
        !          1526: sub Create_PrgWin {
        !          1527:     $r->print(<<ENDPOP);
        !          1528:     <script>
        !          1529:     popwin=open('','popwin','width=400,height=100');
        !          1530:     popwin.document.writeln('<html><body bgcolor="#88DDFF">'+
        !          1531:       '<title>LON-CAPA Statistics</title>'+
        !          1532:       '<h4>Computation Progress</h4>'+
        !          1533:       '<form name=popremain>'+
        !          1534:       '<input type=text size=35 name=remaining value=Starting></form>'+
        !          1535:       '</body></html>');
        !          1536:     popwin.document.close();
        !          1537:     </script>
        !          1538: ENDPOP
        !          1539: 
        !          1540:     $r->rflush();
1.1       albertel 1541: }
                   1542: 
1.27    ! stredwic 1543: # update progress
        !          1544: sub Update_PrgWin {
        !          1545:     my ($totalStudents,$index,$name)=@_;
        !          1546:     $r->print('<script>popwin.document.popremain.remaining.value="'.
        !          1547:               'Computing '.$index.'/'.$totalStudents.': '.
        !          1548:               $name.'";</script>');
        !          1549:     $r->rflush();
        !          1550: }
1.1       albertel 1551: 
1.27    ! stredwic 1552: # close Progress Line
        !          1553: sub Close_PrgWin {
        !          1554:     $r->print('<script>popwin.close()</script>');
        !          1555:     $r->rflush(); 
1.25      minaeibi 1556: }
                   1557: 
                   1558: # For loading the colored table for display or un-colored for print
                   1559: sub setbgcolor {
                   1560:     my $PrintTable=shift;
                   1561:     undef %color;
                   1562:     if ($PrintTable){
                   1563: 	$color{"gb"}="#FFFFFF";
                   1564: 	$color{"red"}="#FFFFFF";
                   1565: 	$color{"yellow"}="#FFFFFF";
                   1566: 	$color{"green"}="#FFFFFF";
                   1567: 	$color{"purple"}="#FFFFFF";
                   1568:     } else {
                   1569: 	$color{"gb"}="#DDFFFF";
                   1570: 	$color{"red"}="#FFDDDD";
                   1571: 	$color{"yellow"}="#EEFFCC";
                   1572: 	$color{"green"}="#DDFFDD";
                   1573: 	$color{"purple"}="#FFDDFF";
                   1574:     }
1.27    ! stredwic 1575: 
        !          1576:     return;
1.1       albertel 1577: }
                   1578: 
1.27    ! stredwic 1579: sub initial {
        !          1580:     undef %hash;
        !          1581:     undef %CachData;
        !          1582:     undef %GraphDat;
        !          1583:     undef %ConceptData;
        !          1584:     undef $Pos;
        !          1585:     undef $GData;
        !          1586: }
1.19      minaeibi 1587: 
1.27    ! stredwic 1588: #---- END HELPER FUNCTIONS ---------------------------------------------------
1.1       albertel 1589: 
1.27    ! stredwic 1590: sub BuildProblemStatisticsPage {
        !          1591:     my ($cacheDB, $students)=@_;
1.1       albertel 1592: 
1.27    ! stredwic 1593:     my %cache;
        !          1594:     unless(tie(%cache,'GDBM_File',$cacheDB,&GDBM_READER,0640)) {
        !          1595:         $r->print('<html><body>Unable to tie database.</body></html>');
        !          1596:         return;
        !          1597:     }
        !          1598: 
        !          1599:     my $Ptr = '';
        !          1600:     $Ptr .= '<form name="ProblemStatisticsPage" method="post" ';
        !          1601:     $Ptr .= 'action="/adm/statistics">'."\n";
        !          1602:     $Ptr .= '<table border="0"><tbody>';
        !          1603:     $Ptr .= '<tr><td></td><td align="left"><input type="submit" name="Menu" ';
        !          1604:     $Ptr .= 'value="Return to Menu" /></td></tr>'."\n";
        !          1605:     $r->print($Ptr);
1.22      stredwic 1606: 
1.27    ! stredwic 1607:     $r->print(&MapOptions(\%cache, 'ProblemStatistics'));
        !          1608:     $r->print(&StatusOptions());
        !          1609:     $r->print(&AscendOrderOptions());
        !          1610:     $r->print(&ProblemStatisticsButtons(\%cache));
        !          1611:     $r->print('</table>');
        !          1612: 
        !          1613:     $r->print(&ProblemStatisticsLegend());
        !          1614: 
        !          1615: #    my $discriminantFactor;
        !          1616: #    my $list;
        !          1617: #    foreach (@$students) {
        !          1618: #        ($discriminantFactor, $list) = &ExtractStudentData($_);
1.5       minaeibi 1619: #    }
1.15      minaeibi 1620: 
1.27    ! stredwic 1621: #    my ($upper, $lower) = &Discriminant($discriminantFactor);
        !          1622: #    my %Header = (0,"Homework Sets Order",1,"#Stdnts",2,"Tries",3,"Mod",
        !          1623: #                  4,"Mean",5,"#YES",6,"#yes",7,"%Wrng",8,"DoDiff",
        !          1624: #                  9,"S.D.",10,"Skew.",11,"D.F.1st",12,"D.F.2nd");
        !          1625: #    &BuildStatisticsTable(\%cache, $discriminantFactor, $list, \%Header);
        !          1626: 
        !          1627:     $r->print('</form>');
        !          1628: 
        !          1629:     untie(%cache);
        !          1630: 
        !          1631:     return;
        !          1632: }
        !          1633: 
        !          1634: sub BuildDiffGraph {
        !          1635:     my ($courseID)=@_;
        !          1636: 
        !          1637:     my $graphData = &GetGraphData('DiffGraph', $courseID);
        !          1638:     $r->print('<IMG src="/cgi-bin/graph.gif?'.$graphData.'" />');
1.1       albertel 1639: 
1.27    ! stredwic 1640:     return;
1.15      minaeibi 1641: }
                   1642: 
1.27    ! stredwic 1643: sub BuildWrongGraph {
        !          1644:     my ($courseID)=@_;
1.15      minaeibi 1645: 
1.27    ! stredwic 1646:     my $graphData = &GetGraphData('WrongGraph', $courseID);
        !          1647:     $r->print('<IMG src="/cgi-bin/graph.gif?'.$graphData.'" />');
        !          1648: 
        !          1649:     return;
1.15      minaeibi 1650: }
                   1651: 
1.27    ! stredwic 1652: sub BuildAnalyzePage {
        !          1653:     my ($cacheDB, $students, $courseID)=@_;
1.19      minaeibi 1654: 
1.27    ! stredwic 1655:     my %cache;
        !          1656:     unless(tie(%cache,'GDBM_File',$cacheDB,&GDBM_READER,0640)) {
        !          1657:         $r->print('<html><body>Unable to tie database.</body></html>');
        !          1658:         return;
1.15      minaeibi 1659:     }
1.1       albertel 1660: 
1.27    ! stredwic 1661:     &ShowOpGraph(\%cache, $students, $courseID);
1.1       albertel 1662: 
1.27    ! stredwic 1663:     untie(%cache);
1.26      minaeibi 1664: 
1.27    ! stredwic 1665:     return;
1.1       albertel 1666: }
1.21      minaeibi 1667: 
1.27    ! stredwic 1668: sub BuildProblemAnalysisPage {
        !          1669:     my ($cacheDB)=@_;
1.1       albertel 1670: 
1.27    ! stredwic 1671:     my %cache;
        !          1672:     unless(tie(%cache,'GDBM_File',$cacheDB,&GDBM_READER,0640)) {
        !          1673:         $r->print('<html><body>Unable to tie database.</body></html>');
        !          1674:         return;
1.1       albertel 1675:     }
1.27    ! stredwic 1676: 
        !          1677:     $r->print('<form name="ProblemAnalysisPage" method="post" ');
        !          1678:     $r->print('action="/adm/statistics">'."\n");
        !          1679:     $r->print('<tr><td></td><td align="left"><input type="submit" ');
        !          1680:     $r->print('name="Menu" value="Return to Menu" /></td></tr>'."\n");
        !          1681:     $r->print(&IntervalOptions());
        !          1682:     $r->print(&OptionResponseTable(\%cache));
        !          1683:     $r->print('</form>'."\n");
        !          1684: 
        !          1685:     untie(%cache);
        !          1686: 
        !          1687:     return;
1.1       albertel 1688: }
                   1689: 
1.27    ! stredwic 1690: sub BuildStudentAssessmentPage {
        !          1691:     my ($cacheDB, $students, $courseID)=@_;
1.15      minaeibi 1692: 
1.27    ! stredwic 1693:     my %cache;
1.1       albertel 1694: 
1.27    ! stredwic 1695:     my $Ptr = '';
        !          1696:     $Ptr .= '<form name="StudentAssessmentPage" method="post" ';
        !          1697:     $Ptr .= 'action="/adm/statistics">'."\n";
        !          1698:     $Ptr .= '<table border="0"><tbody>';
        !          1699:     $Ptr .= '<tr><td></td><td align="left"><input type="submit" name="Menu" ';
        !          1700:     $Ptr .= 'value="Return to Menu" /></td></tr>'."\n";
        !          1701:     $r->print($Ptr);
1.5       minaeibi 1702: 
1.27    ! stredwic 1703:     unless(tie(%cache,'GDBM_File',$cacheDB,&GDBM_READER,0640)) {
        !          1704:         $r->print('<html><body>Unable to tie database.</body></html>');
        !          1705:         return;
1.5       minaeibi 1706:     }
                   1707: 
1.27    ! stredwic 1708:     my $selectedName = $cache{'StudentAssessmentStudent'};
        !          1709:     for(my $index=0; $index<(scalar @$students); $index++) {
        !          1710:         my ($username) = split(':', $students->[$index]);
        !          1711:         if($username eq $selectedName) {
        !          1712:             if($cache{'StudentAssessmentMove'} eq 'next') {
        !          1713:                 if($index == ((scalar @$students) - 1)) {
        !          1714:                     ($selectedName) = split(':',$students->[0]);
        !          1715:                 } else {
        !          1716:                     ($selectedName) = split(':',$students->[$index+1]);
        !          1717:                 }
        !          1718:             } elsif($cache{'StudentAssessmentMove'} eq 'previous') {
        !          1719:                 if($index == 0) {
        !          1720:                     ($selectedName) = split(':',
        !          1721:                                            $students->[(scalar @$students)-1]);
        !          1722:                 } else {
        !          1723:                     ($selectedName)=split(':',$students->[$index-1]);
        !          1724:                 }
        !          1725:             }
        !          1726:             last;
        !          1727:         }
1.1       albertel 1728:     }
1.27    ! stredwic 1729: 
        !          1730:     $r->print(&MapOptions(\%cache, 'StudentAssessment'));
        !          1731:     $r->print(&StudentOptions($students, $selectedName));
        !          1732: 
        !          1733:     $Ptr  = '<tr><td></td><td align="left">';
        !          1734:     $Ptr .= '<input type="submit" name="CreateStudentAssessment" ';
        !          1735:     $Ptr .= 'value="Create Student Report" />';
        !          1736:     $Ptr .= '&nbsp&nbsp&nbsp';
        !          1737:     $Ptr .= '<input type="submit" name="PreviousStudent" ';
        !          1738:     $Ptr .= 'value="Previous Student" />';
        !          1739:     $Ptr .= '&nbsp&nbsp&nbsp';
        !          1740:     $Ptr .= '<input type="submit" name="NextStudent" ';
        !          1741:     $Ptr .= 'value="Next Student" />';
        !          1742:     $Ptr .= '&nbsp&nbsp&nbsp';
        !          1743:     $Ptr .= '</td></tr></tbody></table></form>'."\n";
        !          1744:     $r->print($Ptr);
        !          1745: 
        !          1746:     untie(%cache);
        !          1747: 
        !          1748:     if($selectedName eq 'No Student Selected') {
        !          1749: 	$r->print('<h3><font color=blue>WARNING: ');
        !          1750:         $r->print('Please select a student</font></h3>');
        !          1751:         return;
1.1       albertel 1752:     }
                   1753: 
1.27    ! stredwic 1754:     my $name = '';
        !          1755:     foreach (@$students) {
        !          1756:         my ($currentName) = split(':',$_);
        !          1757:         if($currentName eq $selectedName) {
        !          1758:             $name = $_;
        !          1759:             last;
        !          1760:         }
        !          1761:     }
        !          1762:     if($name eq '') {
        !          1763:         $r->print('<h3><font color=blue>ERROR: Unknown student selected.');
        !          1764:         $r->print('</font></h3>');
        !          1765:         return;
        !          1766:     }
1.1       albertel 1767: 
1.27    ! stredwic 1768:     my $courseData = 
        !          1769:         &Apache::loncoursedata::DownloadStudentCourseInformation($name, 
        !          1770:                                                                  $courseID);
        !          1771:     if(tie(%cache,'GDBM_File',$cacheDB,&GDBM_WRCREAT,0640)) {
        !          1772:         &Apache::loncoursedata::ProcessStudentData(\%cache, 
        !          1773:                                                    $courseData, $name);
        !          1774:         untie(%cache);
1.1       albertel 1775:     }
                   1776: 
1.27    ! stredwic 1777:     unless(tie(%cache,'GDBM_File',$cacheDB,&GDBM_READER,0640)) {
        !          1778:         $Ptr .= 'Could not tie database.';
        !          1779:         return $Ptr;
1.1       albertel 1780:     }
1.27    ! stredwic 1781:     $r->print(&StudentReport(\%cache, $name));
        !          1782:     untie(%cache);
1.1       albertel 1783: 
1.27    ! stredwic 1784:     return;
1.1       albertel 1785: }
                   1786: 
1.27    ! stredwic 1787: sub BuildMenu {
        !          1788:     my ($cacheDB)=@_;
        !          1789: 
        !          1790:     my %cache;
        !          1791:     unless(tie(%cache,'GDBM_File',$cacheDB,&GDBM_READER,0640)) {
        !          1792:         $r->print('<html><body>Unable to tie database.</body></html>');
        !          1793:         return;
        !          1794:     }
        !          1795: 
        !          1796:     $r->print('<form name="Menu" method="post" action="/adm/statistics" >');
        !          1797:     $r->print(&CreateMenuForm(\%cache));
        !          1798:     $r->print('</form>'."\n");
        !          1799: 
        !          1800:     untie(%cache);
        !          1801: 
        !          1802:     return;
        !          1803: }
1.1       albertel 1804: 
                   1805: # ================================================================ Main Handler
                   1806: 
                   1807: sub handler {
                   1808:     $r=shift;
1.27    ! stredwic 1809:     &initial();
1.1       albertel 1810: 
1.27    ! stredwic 1811:     unless(&Apache::lonnet::allowed('vgr',$ENV{'request.course.id'})) {
        !          1812:         $ENV{'user.error.msg'}=
        !          1813:         $r->uri.":vgr:0:0:Cannot view grades for complete course";
        !          1814:         return HTTP_NOT_ACCEPTABLE; 
        !          1815:     }
        !          1816: 
        !          1817:     # Set document type for header only
        !          1818:     if($r->header_only) {
        !          1819:         if ($ENV{'browser.mathml'}) {
        !          1820:             $r->content_type('text/xml');
        !          1821:         } else {
        !          1822:             $r->content_type('text/html');
        !          1823:         }
        !          1824:         &Apache::loncommon::no_cache($r);
        !          1825:         $r->send_http_header;
        !          1826:         return OK;
        !          1827:     }
        !          1828: 
        !          1829:     unless($ENV{'request.course.fn'}) {
1.1       albertel 1830: 	my $requrl=$r->uri;
1.27    ! stredwic 1831:         $ENV{'user.error.msg'}="$requrl:bre:0:0:Course not initialized";
        !          1832:         return HTTP_NOT_ACCEPTABLE; 
        !          1833:     }
1.1       albertel 1834: 
1.27    ! stredwic 1835:     $r->content_type('text/html');
        !          1836:     $r->send_http_header;
1.1       albertel 1837: 
1.27    ! stredwic 1838:     my %cache;
        !          1839:     my $courseID=$ENV{'request.course.id'};
        !          1840:     my $cacheDB = "/home/httpd/perl/tmp/$ENV{'user.name'}".
        !          1841:                   "_$ENV{'user.domain'}_$courseID\_statistics.db";
        !          1842:     my $c = $r->connection;
        !          1843: 
        !          1844:     my ($returnValue, $isCached, $students) = &PrepareData($c, $cacheDB);
        !          1845:     if($returnValue ne 'OK') {
        !          1846:         $r->print('<html><body>'.$returnValue."\n".'</body></html>');
        !          1847:         return OK;
        !          1848:     }
        !          1849: 
        !          1850:     my $downloadTime=0;
        !          1851:     my $GoToPage;
        !          1852:     if(tie(%cache,'GDBM_File',$cacheDB,&GDBM_READER,0640)) {
        !          1853:         $students = &SortStudents($students, \%cache);
        !          1854:         if(defined($cache{'time'})) {
        !          1855:             $downloadTime=$cache{'time'};
        !          1856:         } else {
        !          1857:             $downloadTime=localtime();
        !          1858:         }
        !          1859:         if(!defined($cache{'GoToPage'})) {
        !          1860:             $GoToPage = 'Menu';
        !          1861:         } else {
        !          1862:             $GoToPage = $cache{'GoToPage'};
        !          1863:         }
        !          1864:         untie(%cache);
        !          1865:     } else {
        !          1866:         $r->print('<html><body>Unable to tie database.</body></html>');
        !          1867:         return OK;
1.1       albertel 1868:     }
                   1869: 
1.27    ! stredwic 1870:     &setbgcolor(0);
        !          1871:     $r->print(&Title());
        !          1872: 
        !          1873:     if($GoToPage eq 'ActivityLog') {
        !          1874:         &Activity();
        !          1875:     } elsif($GoToPage eq 'ProblemStatistics') {
        !          1876:         &BuildProblemStatisticsPage($cacheDB, $students);
        !          1877:     } elsif($GoToPage eq 'ProblemAnalysis') {
        !          1878:         &BuildProblemAnalysisPage($cacheDB);
        !          1879:     } elsif($GoToPage eq 'StudentAssessment') {
        !          1880:         &BuildStudentAssessmentPage($cacheDB, $students, $courseID);
        !          1881:     } elsif($GoToPage eq 'Analyze') {
        !          1882:         &BuildAnalyzePage($cacheDB, $students, $courseID);
        !          1883:     } elsif($GoToPage eq 'DoDiffGraph') {
        !          1884:         &BuildDiffGraph($courseID);
        !          1885:     } elsif($GoToPage eq 'PercentWrongGraph') {
        !          1886:         &BuildWrongGraph($courseID);
        !          1887:     } else {
        !          1888:         &BuildMenu($cacheDB);
1.1       albertel 1889:     }
1.27    ! stredwic 1890: 
        !          1891:     $r->print("\n".'</body>'."\n".'</html>');
        !          1892:     $r->rflush();
        !          1893: 
        !          1894:     return OK;
1.1       albertel 1895: }
                   1896: 1;
                   1897: __END__

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