--- loncom/interface/Attic/lonchart.pm 2002/07/01 21:12:06 1.49 +++ loncom/interface/Attic/lonchart.pm 2002/07/03 14:11:14 1.54 @@ -1,7 +1,7 @@ # The LearningOnline Network with CAPA # (Publication Handler # -# $Id: lonchart.pm,v 1.49 2002/07/01 21:12:06 stredwic Exp $ +# $Id: lonchart.pm,v 1.54 2002/07/03 14:11:14 stredwic Exp $ # # Copyright Michigan State University Board of Trustees # @@ -46,6 +46,10 @@ # ### +=pod + +=cut + package Apache::lonchart; use strict; @@ -55,15 +59,15 @@ use Apache::loncommon(); use HTML::TokeParser; use GDBM_File; -my $jr; +#my $jr; # ----- FORMAT PRINT DATA ---------------------------------------------- sub FormatStudentInformation { - my ($cache,$name,$studentInformation,$reselected,$spacePadding)=@_; - my $Str='
';
+    my ($cache,$name,$studentInformation,$spacePadding)=@_;
+    my $Str='';
 
     for(my $index=0; $index<(scalar @$studentInformation); $index++) {
-        if(!&ShouldShowColumn($reselected, 'heading', $index)) {
+        if(!&ShouldShowColumn($cache, 'heading'.$index)) {
             next;
         }
 	my $data=$cache->{$name.':'.$studentInformation->[$index]};
@@ -80,7 +84,7 @@ sub FormatStudentInformation {
 }
 
 sub FormatStudentData {
-    my ($reselected,$name,$coid,$studentInformation,$spacePadding,$ChartDB)=@_;
+    my ($name,$coid,$studentInformation,$spacePadding,$ChartDB)=@_;
     my ($sname,$sdom) = split(/\:/,$name);
     my $Str;
     my %CacheData;
@@ -91,26 +95,19 @@ sub FormatStudentData {
     # Handle Student information ------------------------------------------
     # Handle user data
     $Str=&FormatStudentInformation(\%CacheData, $name, $studentInformation, 
-                                   $reselected, $spacePadding);
+                                   $spacePadding);
 
     # Handle errors
     if($CacheData{$name.':error'} =~ /environment/) {
+        $Str .= '
'; untie(%CacheData); - $Str .= '
'; return $Str; -# my $errorMessage = $CacheData{$name.':error'}; -# return ''.$sname.''.$sdom. -# ''.$errorMessage.''; } if($CacheData{$name.':error'} =~ /course/) { + $Str .= '
'; untie(%CacheData); - $Str .= ''; - return $Str; -# my $errorMessage = 'May have no course data or '. -# $CacheData{$name.':error'}; -# return ''.$sname.''.$sdom. -# ''.$errorMessage.''; + return $Str; } # Handle problem data ------------------------------------------------ @@ -120,7 +117,7 @@ sub FormatStudentData { my $problemsSolved = 0; my $numberOfParts = 0; foreach my $sequence (split(/\:/,$CacheData{'orderedSequences'})) { - if(!&ShouldShowColumn($reselected, 'sequence', $sequence)) { + if(!&ShouldShowColumn(\%CacheData, 'sequence'.$sequence)) { next; } @@ -215,22 +212,25 @@ sub FormatStudentData { $Str .= $spacePadding; } - $Str .= ''.$problemsSolved. - ' / '.$totalProblems.''; + my $outputProblemsSolved = sprintf( "%4d", $problemsSolved ); + my $outputTotalProblems = sprintf( "%4d", $totalProblems ); + $Str .= ''.$outputProblemsSolved. + ' / '.$outputTotalProblems.'
'; untie(%CacheData); return $Str; } sub CreateTableHeadings { - my ($CacheData,$studentInformation,$headings,$reselected,$spacePadding)=@_; - my $Str='
';
+    my ($CacheData,$studentInformation,$headings,$spacePadding)=@_;
+    my $Str='';
 
     for(my $index=0; $index<(scalar @$headings); $index++) {
-        if(!&ShouldShowColumn($reselected, 'heading', $index)) {
+        if(!&ShouldShowColumn($CacheData, 'heading'.$index)) {
             next;
         }
 
+        $Str .= '
';
 	my $data=$$headings[$index];
 	$Str .= $data;
 
@@ -239,13 +239,15 @@ sub CreateTableHeadings {
 	$Str .= (' 'x($CacheData->{$$studentInformation[$index].'Length'}-
                       $length));
 	$Str .= $spacePadding;
+        $Str .= '
'; } foreach my $sequence (split(/\:/,$CacheData->{'orderedSequences'})) { - if(!&ShouldShowColumn($reselected, 'sequence', $sequence)) { + if(!&ShouldShowColumn($CacheData, 'sequence'.$sequence)) { next; } + $Str .= '
';
         my $name = $CacheData->{$sequence.':title'};
 	$Str .= $name;
 	my @titleLength=split(//,$CacheData->{$sequence.':title'});
@@ -253,25 +255,26 @@ sub CreateTableHeadings {
                      (scalar @titleLength);
 	$Str .= (' 'x$leftover);
 	$Str .= $spacePadding;
+        $Str .= '
'; } - $Str .= 'Total Solved/Total Problems'; - $Str .= '
'; + $Str .= '
Total Solved/Total Problems
'; + $Str .= ''; return $Str; } sub CreateColumnSelectionBox { - my ($CacheData,$studentInformation,$headings,$reselected,$spacePadding)=@_; + my ($CacheData,$studentInformation,$headings,$spacePadding)=@_; my $missing=0; - my $notThere='

Select column to view:

'; + my $notThere='Select column to view:'; my $name; - $notThere .= '   '; + $notThere .= ''; $notThere .= '

'; + $notThere .= ''; } else { - $notThere=''; + $notThere=''; } - return $notThere; + return $notThere.''; } sub CreateColumnSelectors { - my ($CacheData,$studentInformation,$headings,$reselected,$spacePadding)=@_; + my ($CacheData,$studentInformation,$headings,$spacePadding)=@_; my $found=0; my ($name, $length, $position); - my $present='
';
+
+    my $present='
Note: Uncheck the boxes above a column to ';
+    $present .= 'remove that column from the display.
'."\n"; + + $present .= ''; + $present .= ''; for(my $index=0; $index<(scalar @$headings); $index++) { - if(!&ShouldShowColumn($reselected, 'heading', $index)) { + if(!&ShouldShowColumn($CacheData, 'heading'.$index)) { next; } - $name = $headings->[$index]; - $length=$CacheData->{$$studentInformation[$index].'Length'}; - $position=int($length/2); - $present .= (' 'x($position)); + $present .= ''; $found++; } foreach my $sequence (split(/\:/,$CacheData->{'orderedSequences'})) { - if(!&ShouldShowColumn($reselected, 'sequence', $sequence)) { + if(!&ShouldShowColumn($CacheData, 'sequence'.$sequence)) { next; } - $name = $CacheData->{$sequence.':title'}; - $length=$CacheData->{$sequence.':columnWidth'}; - $position=int($length/2); - $present .= (' 'x($position)); + $present .= ''; $found++; } - if($found) { - $present .= ''; - $present = $present; - } else { + if(!$found) { $present = ''; } - return $present.''."\n";; + return $present.''."\n";; } sub CreateForm { + my ($CacheData)=@_; my $OpSel1=''; my $OpSel2=''; my $OpSel3=''; - my $Status = $ENV{'form.status'}; + my $Status = $CacheData->{'form.status'}; if ( $Status eq 'Any' ) { $OpSel3='selected'; } elsif ($Status eq 'Expired' ) { $OpSel2 = 'selected'; } else { $OpSel1 = 'selected'; } - my $Ptr = ''."\n"; - $Ptr .= ''; - $Ptr .= "\n"; + my $Ptr .= ''."\n"; + $Ptr .= '
'; $present .= ''; - $position+=2; - $present .= (' 'x($length-$position)); - $present .= $spacePadding; + $present .= 'name="heading'.$index.'" />'; + $present .= ''; $present .= ''; - $position+=2; - $present .= (' 'x($length-$position)); - $present .= $spacePadding; + $present .= 'name="sequence'.$sequence.'" />'; + $present .= '
'; + $Ptr .= ''; return $Ptr; } sub CreateLegend { - my $Str = '

'.$ENV{'course.'.$ENV{'request.course.id'}.'.description'}. - '

'.localtime(). - "

1..9: correct by student in 1..9 tries\n".
+    my $Str = "

".
+              "1..9: correct by student in 1..9 tries\n".
               "   *: correct by student in more than 9 tries\n".
 	      "   +: correct by override\n".
               "   -: incorrect by override\n".
 	      "   .: incorrect attempted\n".
 	      "   #: ungraded attempted\n".
               "    : not attempted\n".
-	      "   x: excused

"; + " x: excused". + "

"; return $Str; } @@ -404,6 +407,8 @@ sub StartDocument { $Str .= ''; $Str .= ''; $Str .= '

Assessment Chart

'; + $Str .= '

'.$ENV{'course.'.$ENV{'request.course.id'}.'.description'}; + $Str .= '

'; return $Str; } @@ -513,6 +518,17 @@ sub ProcessTopResourceMap { push(@finishResource, $lastResourceID); $currentSequence=$hash{'map_pc_'.$hash{'src_'.$currentResourceID}}; + + # Mark sequence as containing problems. If it doesn't, then + # it will be removed when processing for this sequence is + # complete. This allows the problems in a sequence + # to be outputed before problems in the subsequences + if(!defined($CacheData{'orderedSequences'})) { + $CacheData{'orderedSequences'}=$currentSequence; + } else { + $CacheData{'orderedSequences'}.=':'.$currentSequence; + } + $lastResourceID=$hash{'map_finish_'. $hash{'src_'.$currentResourceID}}; $currentResourceID=$hash{'map_start_'. @@ -574,12 +590,6 @@ sub ProcessTopResourceMap { if(defined($CacheData{$currentSequence.':problems'})) { # Capture sequence information here - if(!defined($CacheData{'orderedSequences'})) { - $CacheData{'orderedSequences'}=$currentSequence; - } else { - $CacheData{'orderedSequences'}.=':'.$currentSequence; - } - $CacheData{$currentSequence.':title'}= $hash{'title_'.$currentResourceID}; @@ -605,13 +615,16 @@ sub ProcessTopResourceMap { $CacheData{$currentSequence.':columnWidth'}= (scalar @titleLength); } - } + } else { + $CacheData{'orderedSequences'}=~s/$currentSequence//; + $CacheData{'orderedSequences'}=~s/::/:/g; + $CacheData{'orderedSequences'}=~s/^:|:$//g; + } $currentSequence=pop(@sequences); if($currentSequence eq $topLevelSequenceNumber) { last; } - #else } # MOVE!!! @@ -722,7 +735,7 @@ sub ProcessStudentInformation { } # Get student's section number - my $sec=&ProcessSection($section, $courseID, $ENV{'form.status'}); + my $sec=&ProcessSection($section, $courseID, $CacheData->{'form.status'}); if($sec != -1) { $CacheData->{$name.':section'}=$sec; } else { @@ -755,6 +768,8 @@ sub ProcessClassList { $name,$courseID,$c); } + # Time of download + $CacheData{'time'}=localtime(); untie(%CacheData); } @@ -840,7 +855,7 @@ sub SortStudents { my ($end,$start)=split(/\:/,$CacheData->{$_.':date'}); my $active=1; my $now=time; - my $Status=$ENV{'form.status'}; + my $Status=$CacheData->{'form.status'}; $Status = ($Status) ? $Status : 'Active'; if((($end) && $now > $end) && (($Status eq 'Active'))) { $active=0; @@ -853,7 +868,7 @@ sub SortStudents { } } - my $Pos = $ENV{'form.sort'}; + my $Pos = $CacheData->{'form.sort'}; my %sortData; if($Pos eq 'Last Name') { for(my $index=0; $index= 3) { + if($tieTries >= 10) { return -1; } @@ -939,28 +954,94 @@ sub ExtractStudentData { } sub ShouldShowColumn { - my ($reselected,$type,$value)=@_; + my ($cache,$test)=@_; - if($ENV{'form.sort'} eq 'Recalculate Chart') { + if($cache->{'form.reset'} eq 'true') { return 1; } - if(defined($ENV{'form.'.$type.$value})) { + my $headings=$cache->{'form.headings'}; + my $sequences=$cache->{'form.sequences'}; + if($headings eq 'ALLHEADINGS' || $sequences eq 'ALLSEQUENCES' || + $headings=~/$test/ || $sequences=~/$test/) { return 1; } - return &CheckForStringInArray($reselected, $type.$value); +# my $reselected=$cache->{'form.reselect'}; +# if($reselected=~/$test/) { +# return 1; +# } + + return 0; } -sub CheckForStringInArray { - my ($inputArray,$checkString)=@_; - foreach (@$inputArray) { -# $jr->print('a:'.$_.' b:'.$checkString.'
'); - if($_ eq $checkString) { - return 1; +sub ProcessFormData { + my ($ChartDB)=@_; + my %CacheData; + + if(tie(%CacheData,'GDBM_File',$ChartDB,&GDBM_WRCREAT,0640)) { + if(defined($ENV{'form.sort'})) { + $CacheData{'form.sort'}=$ENV{'form.sort'}; + } elsif(!defined($CacheData{'form.sort'})) { + $CacheData{'form.sort'}='username'; + } + + # Ignore $ENV{'form.refresh'} + # Ignore $ENV{'form.recalculate'} + + if(defined($ENV{'form.status'})) { + $CacheData{'form.status'}=$ENV{'form.status'}; + } elsif(!defined($CacheData{'form.status'})) { + $CacheData{'form.status'}='Active'; + } + + my @headings=(); + my @sequences=(); + my $found=0; + foreach (keys(%ENV)) { + if(/form\.heading/) { + $found++; + push(@headings, $_); + } elsif(/form\.sequence/) { + $found++; + push(@sequences, $_); + } elsif(/form\./) { + $found++; + } } + + if($found) { + $CacheData{'form.headings'}=join(":::",@headings); + $CacheData{'form.sequences'}=join(":::",@sequences); + } + + if(defined($ENV{'form.reselect'})) { + my @reselected = (ref($ENV{'form.reselect'}) ? + @{$ENV{'form.reselect'}} + : ($ENV{'form.reselect'})); + foreach (@reselected) { + if(/heading/) { + $CacheData{'form.headings'}.=":::".$_; + } elsif(/sequence/) { + $CacheData{'form.sequences'}.=":::".$_; + } + } + } + + if(defined($ENV{'form.reset'})) { + $CacheData{'form.reset'}='true'; + $CacheData{'form.status'}='Active'; + $CacheData{'form.sort'}='username'; + $CacheData{'form.headings'}='ALLHEADINGS'; + $CacheData{'form.sequences'}='ALLSEQUENCES'; + } else { + $CacheData{'form.reset'}='false'; + } + + untie(%CacheData); } - return 0; + + return; } # ----- END HELPER FUNCTIONS -------------------------------------------- @@ -980,10 +1061,6 @@ sub BuildChart { my $cid=$ENV{'request.course.id'}; my $ChartDB = "/home/httpd/perl/tmp/$ENV{'user.name'}". "_$ENV{'user.domain'}_$cid\_chart.db"; - # $ENV{'form.domains'} can be either a scalar or an array reference. - # We need an array. - my @reselected = (ref($ENV{'form.reselect'}) ? @{$ENV{'form.reselect'}} - : ($ENV{'form.reselect'})); $isCached=&TestCacheData($ChartDB); if($isCached < 0) { @@ -991,6 +1068,7 @@ sub BuildChart { $r->rflush(); return; } + &ProcessFormData($ChartDB); # Download class list information if not using cached data my %CacheData; @@ -1027,28 +1105,29 @@ sub BuildChart { # Sort students and print out table desciptive data if(tie(%CacheData,'GDBM_File',$ChartDB,&GDBM_READER,0640)) { if(!$c->aborted()) { @students=&SortStudents(\@students,\%CacheData); } - if(!$c->aborted()) { $r->print(&CreateLegend()); } + my $downloadTime=0; + if(defined($CacheData{'time'})) { $downloadTime=$CacheData{'time'}; } + else { $downloadTime=localtime(); } + if(!$c->aborted()) { $r->print('

'.$downloadTime.'

'); } + if(!$c->aborted()) { $r->print('

'.(scalar @students). + ' students

'); } if(!$c->aborted()) { $r->rflush(); } - if(!$c->aborted()) { $r->print(&CreateForm()); } + if(!$c->aborted()) { $r->print(&CreateLegend()); } + if(!$c->aborted()) { $r->print(&CreateForm(\%CacheData)); } if(!$c->aborted()) { $r->print(&CreateColumnSelectionBox( \%CacheData, \@studentInformation, \@headings, - \@reselected, $spacePadding)); } - if(!$c->aborted()) { $r->print('

'.(scalar @students). - ' students

'); } if(!$c->aborted()) { $r->print(&CreateColumnSelectors( \%CacheData, \@studentInformation, \@headings, - \@reselected, $spacePadding)); } if(!$c->aborted()) { $r->print(&CreateTableHeadings( \%CacheData, \@studentInformation, \@headings, - \@reselected, $spacePadding)); } if(!$c->aborted()) { $r->rflush(); } untie(%CacheData); @@ -1059,31 +1138,31 @@ sub BuildChart { my @updateStudentList = (); my $courseData; + $r->print('
');
     foreach (@students) {
         if($c->aborted()) {
-            if(!$isCached && 
-               tie(%CacheData,'GDBM_File',$ChartDB,&GDBM_WRCREAT,0640)) {
-                $CacheData{'NamesOfStudents'}=join(":::", @updateStudentList);
-#		    $CacheData{'NamesOfStudents'}=
-#		            &Apache::lonnet::arrayref2str(\@updateStudentList);
-                untie(%CacheData);
-            }
             last;
         }
 
         if(!$isCached) {
             $courseData=&DownloadStudentCourseInformation($_, $cid);
-            if($c->aborted()) { next; }
+            if($c->aborted()) { last; }
             push(@updateStudentList, $_);
             &ExtractStudentData($courseData, $_, $ChartDB);
         }
-        $r->print(&FormatStudentData(\@reselected, $_, $cid, 
-                                     \@studentInformation,
+        $r->print(&FormatStudentData($_, $cid, \@studentInformation,
                                      $spacePadding, $ChartDB));
         $r->rflush();
     }
 
-    $r->print('');
+    if(!$isCached && tie(%CacheData,'GDBM_File',$ChartDB,&GDBM_WRCREAT,0640)) {
+        $CacheData{'NamesOfStudents'}=join(":::", @updateStudentList);
+#		    $CacheData{'NamesOfStudents'}=
+#		            &Apache::lonnet::arrayref2str(\@updateStudentList);
+        untie(%CacheData);
+    }
+
+    $r->print('
'); $r->rflush(); return; @@ -1093,7 +1172,7 @@ sub BuildChart { sub handler { my $r=shift; - $jr=$r; +# $jr=$r; unless(&Apache::lonnet::allowed('vgr',$ENV{'request.course.id'})) { $ENV{'user.error.msg'}= $r->uri.":vgr:0:0:Cannot view grades for complete course";
'; + $Ptr .= ''; + $Ptr .= ''. ' '."\n"; + $Ptr .= '