Diff for /loncom/interface/statistics/lonstudentassessment.pm between versions 1.30 and 1.31

version 1.30, 2003/02/28 21:19:00 version 1.31, 2003/03/03 19:28:29
Line 54  use Apache::lonstatistics; Line 54  use Apache::lonstatistics;
 use Apache::lonhtmlcommon;  use Apache::lonhtmlcommon;
 use Apache::loncoursedata;  use Apache::loncoursedata;
 use Apache::lonnet; # for logging porpoises  use Apache::lonnet; # for logging porpoises
 use GDBM_File;  use Spreadsheet::WriteExcel;
   
   #######################################################
   #######################################################
   =pod
   
   =item Package Variables
   
   =over 4
   
   =item $Statistics Hash ref to store student data.  Indexed by symb,
         contains hashes with keys 'score' and 'max'.
   
   =cut
   
   #######################################################
   #######################################################
   
 my $Statistics;  my $Statistics;
   
Line 63  my $Statistics; Line 79  my $Statistics;
   
 =pod  =pod
   
 =item &BuildStudentAssessmentPage()  =item $show_links 'yes' or 'no' for linking to student performance data
   
 Inputs:   =item $output_mode 'html', 'excel', or 'csv' for output mode
   
 =over 4  =item $show 'all' or 'totals' determines how much data is output
   
 =item $cacheDB The name of the cache file used to store student data  =cut
   
 =item $students Array ref containing the name(s) of the students   #######################################################
 selected for display  #######################################################
   my $show_links;
   my $output_mode;
   my $show;
   
 =item $courseID The ID of the course  #######################################################
   #######################################################
   # End of package variable declarations
   
 =item $formName The name of the html form - 'Statistics'  =pod
   
 =item $headings Array ref of headings to show  =back
   
 =item $spacing A string of spaces  =cut
   
 =item $studentInformation Array ref of possible headings for student info  #######################################################
 ('fullname','section',...)  #######################################################
   
   =pod
   
   =item &BuildStudentAssessmentPage()
   
   Inputs: 
   
   =over 4
   
 =item $r Apache Request  =item $r Apache Request
   
Line 98  selected for display Line 127  selected for display
 sub BuildStudentAssessmentPage {  sub BuildStudentAssessmentPage {
     my ($r,$c)=@_;      my ($r,$c)=@_;
     undef($Statistics);      undef($Statistics);
       
     #      #
       # Print out the HTML headers for the interface
       #    This also parses the output mode selector
       #    This step must always be done.
     $r->print(&CreateInterface());      $r->print(&CreateInterface());
       $r->print('<input type="hidden" name="notfirstrun" value="true" />');
     $r->rflush();      $r->rflush();
       if (! exists($ENV{'form.notfirstrun'})) {
           $r->print(<<ENDMSG);
   <p>
   <font size="+1">
   Please make your selections in the boxes above and hit 
   the button marked &quot;Update&nbsp;Display&quot;.
   </font>
   </p>
   ENDMSG
           return;
       }
       #
       #
       my $initialize     = \&html_initialize;
       my $output_student = \&html_outputstudent;
       my $finish         = \&html_finish;
       #
       if ($output_mode eq 'excel') {
           $initialize     = \&excel_initialize;
           $output_student = \&excel_outputstudent;
           $finish         = \&excel_finish;
       } elsif ($output_mode eq 'csv') {
           $initialize     = \&csv_initialize;
           $output_student = \&csv_outputstudent;
           $finish         = \&csv_finish;
       }
     #      #
     $r->print(&CreateTableHeadings());  
     if($c->aborted()) {  return ; }      if($c->aborted()) {  return ; }
           #
     my $Count = 0;      # Call the initialize routine selected above
     $r->print('<pre>'."\n");      $initialize->($r);
     foreach my $student (@Apache::lonstatistics::Students) {      foreach my $student (@Apache::lonstatistics::Students) {
         if($c->aborted()) { return ; }          if($c->aborted()) { 
         $r->print(&ChartOutputStudent($student));              $finish->($r);
         # output it              return ; 
   
         $Count++;  
         if($Count % 5 == 0) {  
             $r->print("</pre>\n<pre>");  
         }          }
           # Call the output_student routine selected above
         $r->rflush();          $output_student->($r,$student);
     }      }
     $r->print('</pre>'."\n");       # Call the "finish" routine selected above
     my $Str;      $finish->($r);
       #
     return;      return;
 }  }
   
 #######################################################  #######################################################
 #######################################################  #######################################################
   
   sub get_student_fields_to_show {
       my @to_show = @Apache::lonstatistics::SelectedStudentData;
       foreach (@to_show) {
           if ($_ eq 'all') {
               @to_show = @Apache::lonstatistics::StudentDataOrder;
               last;
           }
       }
       return @to_show;
   }
   
   sub get_sequences_to_show {
       my @Sequences;
       foreach my $map_symb (@Apache::lonstatistics::SelectedMaps) {
           foreach my $sequence (@Apache::lonstatistics::Sequences) {
               next if ($sequence->{'symb'} ne $map_symb && $map_symb ne 'all');
               next if ($sequence->{'num_assess'} < 1);
               push (@Sequences,$sequence);
           }
       }
       return @Sequences;
   }
   
   
   #######################################################
   #######################################################
   
 =pod  =pod
   
 =item &CreateInterface()  =item &CreateInterface()
Line 152  sub CreateInterface { Line 233  sub CreateInterface {
     $Str .= '<td align="center"><b>Sections</b></td>';      $Str .= '<td align="center"><b>Sections</b></td>';
     $Str .= '<td align="center"><b>Student Data</b></td>';      $Str .= '<td align="center"><b>Student Data</b></td>';
     $Str .= '<td align="center"><b>Sequences and Folders</b></td>';      $Str .= '<td align="center"><b>Sequences and Folders</b></td>';
       $Str .= '<td align="center"><b>Output Format</b></td>';
     $Str .= '</tr>'."\n";      $Str .= '</tr>'."\n";
     #      #
     $Str .= '<tr><td align="center">'."\n";      $Str .= '<tr><td align="center">'."\n";
Line 170  sub CreateInterface { Line 252  sub CreateInterface {
     $Str .= '</td><td>'."\n";      $Str .= '</td><td>'."\n";
     $Str .= &Apache::lonstatistics::MapSelect('Maps','multiple,all',5,      $Str .= &Apache::lonstatistics::MapSelect('Maps','multiple,all',5,
                                               $only_seq_with_assessments);                                                $only_seq_with_assessments);
       $Str .= '</td><td>'."\n";
       $Str .= &CreateAndParseOutputSelector();
     $Str .= '</td></tr>'."\n";      $Str .= '</td></tr>'."\n";
     $Str .= '</table>'."\n";      $Str .= '</table>'."\n";
     return $Str;      return $Str;
 }  }
   
   
 #######################################################  #######################################################
 #######################################################  #######################################################
   
 =pod  =pod
   
 =item Table Output Routines  =item &CreateAndParseOutputSelector()
   
 =over 4  
   
 =cut  =cut
   
 #######################################################  #######################################################
 #######################################################  #######################################################
 {  sub CreateAndParseOutputSelector {
     my $padding;      my $Str = '';
       my $elementname = 'outputmode';
       #
       # Format for output options is 'mode, restrictions';
       my @Options = ('html, with links','html, without links',
                      'html, totals only','excel, totals only',
                      'csv, totals only','csv, everything');
       my $selected = 'html, with links';
       if (exists($ENV{'form.'.$elementname})) {
           if (ref($ENV{'form.'.$elementname} eq 'ARRAY')) {
               $selected = $ENV{'form.'.$elementname}->[0];
           } else {
               $selected = $ENV{'form.'.$elementname};
           }
       }
       #
       # Set package variables describing output mode
       $show_links  = 'no';
       $output_mode = 'html';
       $show        = 'all';
       my ($mode,$restriction) = split(',',$selected);
       $restriction =~ s/^\s*//;
       if ($mode =~ /^(html|excel|csv)$/) {
           $output_mode = $mode;
       } else {
           $output_mode = 'html';
       }
       if ($restriction eq 'with links') {
           $show_links = 'yes';
       } else {
           $show_links = 'no';
       }
       if ($restriction eq 'totals only') {
           $show = 'totals';
       } else {
           $show = 'everything';
       }
       #
       # Build the form element
       $Str = qq/<select size="5" name="$elementname">/;
       foreach my $option (@Options) {
           $Str .= qq/\n    <option value="$option"/;
           $Str .= " selected " if ($option eq $selected);
           $Str .= ">$option<\/option>";
       }
       $Str .= "\n</select>";
       return $Str;
   }
   
 #######################################################  #######################################################
 #######################################################  #######################################################
   
 =pod  =pod
   
 =item &CreateTableHeadings()  =head2 HTML output routines
   
 Create HTML for the columns of student data to show.  =item &html_initialize($r)
 Called by &BuildStudentAssessmentPage().  Calls  
 &Apache::lonhtmlcommon::CreateHeadings().  
   
 Inputs:  Create labels for the columns of student data to show.
   
 =over 4  =item &html_outputstudent($r,$student)
   
 =item $cache The ubiquitous cache  Return a line of the chart for a student.
   
 =item $spacing A string of spaces  
   
 =item $infoKeys Array ref to names of keys to display from the cache   
 which describe students  
   
 =item $infoHeadings Array ref to headings of columns for student info  
   
 =item $sequenceKeys Array ref of names of keys to use to retrieve sequence  
 data from the cache  
   
 =item $sequenceHeadings Array ref of names of sequences used for output.  
   
 =back  
   
 Returns: A string containing the HTML of the table headings.  =item &html_finish($r)
   
 =cut  =cut
   
 #######################################################  #######################################################
 #######################################################  #######################################################
 sub CreateTableHeadings {  {
       my $padding;
       my $count;
   
   sub html_initialize {
       my ($r) = @_;
     #      #
     $padding = ' 'x3;      $padding = ' 'x3;
       $count = 1;
     #      #
     my $Str = '<pre>';      my $Str = "<pre>\n";
     # First, the @StudentData fields need to be listed      # First, the @StudentData fields need to be listed
     my @to_show = @Apache::lonstatistics::SelectedStudentData;      my @to_show = &get_student_fields_to_show();
     foreach (@to_show) {  
         if ($_ eq 'all') {  
             @to_show = @Apache::lonstatistics::StudentDataOrder;  
             last;  
         }  
     }  
     foreach my $field (@to_show) {      foreach my $field (@to_show) {
         my $title=$Apache::lonstatistics::StudentData{$field}->{'title'};          my $title=$Apache::lonstatistics::StudentData{$field}->{'title'};
         my $base =$Apache::lonstatistics::StudentData{$field}->{'base_width'};          my $base =$Apache::lonstatistics::StudentData{$field}->{'base_width'};
Line 249  sub CreateTableHeadings { Line 361  sub CreateTableHeadings {
         $Str .= $title.' 'x($width-$base).$padding;          $Str .= $title.' 'x($width-$base).$padding;
     }      }
     # Now the selected sequences need to be listed      # Now the selected sequences need to be listed
     foreach my $map_symb (@Apache::lonstatistics::SelectedMaps) {      foreach my $sequence (&get_sequences_to_show) {
         foreach my $sequence (@Apache::lonstatistics::Sequences) {          my $title = $sequence->{'title'};
             next if ($sequence->{'symb'} ne $map_symb && $map_symb ne 'all');          my $base  = $sequence->{'base_width'};
             next if ($sequence->{'num_assess'} < 1);          my $width = $sequence->{'width'};
             my $title = $sequence->{'title'};          $Str .= $title.' 'x($width-$base).$padding;
             my $base  = $sequence->{'base_width'};  
             my $width = $sequence->{'width'};  
             $Str .= $title.' 'x($width-$base).$padding;  
         }  
     }      }
     $Str .= 'total';      $Str .= "total (of shown problems)</pre>\n";
     $Str .= "</pre>\n";      $Str .= "<pre>";
     return $Str;      $r->print($Str);
       $r->rflush();
       return;
 }  }
   
 #######################################################  sub html_outputstudent {
 #######################################################      my ($r,$student) = @_;
   
 =pod  
   
 =item &ChartOutputStudent($student)  
   
 Return a line of the chart for a student.  
   
 =cut  
   
 #######################################################  
 #######################################################  
 sub ChartOutputStudent {  
     my $student = shift;  
     my $Str = '';      my $Str = '';
     # First, the @StudentData fields need to be listed      # First, the @StudentData fields need to be listed
     my @to_show = @Apache::lonstatistics::SelectedStudentData;      my @to_show = &get_student_fields_to_show();
     foreach (@to_show) {  
         if ($_ eq 'all') {  
             @to_show = @Apache::lonstatistics::StudentDataOrder;  
             last;  
         }  
     }  
     foreach my $field (@to_show) {      foreach my $field (@to_show) {
         my $title=$student->{$field};          my $title=$student->{$field};
         my $base =scalar(my @Tmp = split(//,$title));          my $base = length($title);
         my $width=$Apache::lonstatistics::StudentData{$field}->{'width'};          my $width=$Apache::lonstatistics::StudentData{$field}->{'width'};
         $Str .= $title.' 'x($width-$base).$padding;          $Str .= $title.' 'x($width-$base).$padding;
     }      }
Line 304  sub ChartOutputStudent { Line 395  sub ChartOutputStudent {
     }      }
     if (scalar(@tmp) < 1) {      if (scalar(@tmp) < 1) {
         $Str .= '<font color="blue">No Course Data</font>'."\n";          $Str .= '<font color="blue">No Course Data</font>'."\n";
         return $Str;          $r->print($Str);
           $r->rflush();
           return;
     }      }
     #      #
     # By sequence build up the data      # By sequence build up the data
     my $studentstats;      my $studentstats;
     foreach my $map_symb (@Apache::lonstatistics::SelectedMaps) {      my $PerformanceStr = '';
         foreach my $seq (@Apache::lonstatistics::Sequences) {      foreach my $seq (&get_sequences_to_show) {
             next if ($map_symb ne $seq->{'symb'} && $map_symb ne 'all');          my ($performance,$score,$seq_max) =
             next if ($seq->{'num_assess'} < 1);              &StudentPerformanceOnSequence($student,\%StudentsData,
             my ($performance,$score,$seq_max) =                                            $seq,$show_links);
                 &StudentPerformanceOnSequence($student,\%StudentsData,          my $ratio = $score.'/'.$seq_max;
                                               $seq,'linkify');          #
             $Str .= $performance.$padding;          if ($show eq 'totals') {
             $studentstats->{$seq->{'symb'}}->{'score'}= $score;              $performance = ' 'x(length($seq_max)-length($score)).$ratio;
             $studentstats->{$seq->{'symb'}}->{'max'}  = $seq_max;              $performance .= ' 'x($seq->{'width'}-length($performance));
           } else {
               # Pad with extra spaces
               $performance .= ' 'x($seq->{'width'}-$seq_max-
                                    length($ratio)
                                    ).$ratio;
         }          }
           #
           $Str .= $performance.$padding;
           #
           $studentstats->{$seq->{'symb'}}->{'score'}= $score;
           $studentstats->{$seq->{'symb'}}->{'max'}  = $seq_max;
     }      }
     #      #
     # Total it up and store the statistics info.      # Total it up and store the statistics info.
Line 330  sub ChartOutputStudent { Line 433  sub ChartOutputStudent {
         $score += $seq_stats->{'score'};          $score += $seq_stats->{'score'};
         $max   += $seq_stats->{'max'};          $max   += $seq_stats->{'max'};
     }      }
     my $scorelength = scalar(my @tmp1 = split(//,$score));      $Str .= ' '.' 'x(length($max)-length($score)).$score.'/'.$max;
     my $maxlength   = scalar(my @tmp2 = split(//,$max));  
     $Str .= ' '.' 'x($maxlength-$scorelength).$score.'/'.$max;  
     $Str .= " \n";      $Str .= " \n";
     return $Str;      $r->print($Str);
       #
       $count++;
       if($count % 5 == 0) {
           $r->print("</pre><pre>");
       }
       #
       $r->rflush();
       return;
 }      }    
   
   sub html_finish {
       my ($r) = @_;
       $r->print("</pre>\n"); 
       $r->rflush();
       return;
   }
   
   }
   
 #######################################################  #######################################################
 #######################################################  #######################################################
   
 =pod  =pod
   
 =back  =head2 EXCEL subroutines
   
   =item &excel_initialize($r)
   
   =item &excel_outputstudent($r,$student)
   
   =item &excel_finish($r)
   
   =cut
   
   #######################################################
   #######################################################
   {
   
   my $excel_sheet;
   
   sub excel_initialize {
       my ($r) = @_;
       #
       $r->print("<h1>Not implemented yet</h1>");
       return;
       my $filename = '/prtspool/'.
           $ENV{'user.name'}.'_'.$ENV{'user.domain'}.'_'.
               time.'_'.rand(1000000000).'.xls';
       $excel_sheet = Spreadsheet::WriteExcel->new('/home/httpd'.$filename);
       if (! defined($excel_sheet)) {
           $r->log_error("Error creating excel spreadsheet $filename: $!");
           $r->print("Problems creating new Excel file.  ".
                     "This error has been logged.  ".
                     "Please alert your LON-CAPA administrator");
           return 0;
       }
       #
       # The excel spreadsheet stores temporary data in files, then put them
       # together.  If needed we should be able to disable this (memory only).
       # The temporary directory must be specified before calling 'addworksheet'.
       # File::Temp is used to determine the temporary directory.
       $excel_sheet->set_tempdir($Apache::lonnet::tmpdir);
       #
       # Determine the name to give the worksheet
   #    $excel_sheet->addworksheet();
   
       return;
   }
   
   sub excel_outputstudent {
       my ($r,$student) = @_;
   }
   
   sub excel_finish {
       my ($r) = @_;
   }
   
   }
   #######################################################
   #######################################################
   
   =pod
   
   =head2 CSV output routines
   
   =item &csv_initialize($r)
   
   =item &csv_outputstudent($r,$student)
   
   =item &csv_finish($r)
   
 =cut  =cut
   
 #######################################################  #######################################################
 #######################################################  #######################################################
   {
   
   sub csv_initialize{
       my ($r) = @_;
       $r->print("<h1>Not implemented yet</h1>");
       return;
   }
   
   sub csv_outputstudent {
       my ($r,$student) = @_;
   }
   
   sub csv_finish {
       my ($r) = @_;
   }
   
 }  }
   
Line 377  Inputs: Line 575  Inputs:
 #######################################################  #######################################################
 #######################################################  #######################################################
 sub StudentPerformanceOnSequence {  sub StudentPerformanceOnSequence {
     my ($student,$studentdata,$seq,$links) = @_;      my ($student,$studentdata,$seq,$links,$totalonly) = @_;
       $totalonly = 0 if (! defined($totalonly));
       $links = 'no' if (! defined($links));
     my $Str = '';      my $Str = '';
     my $output_width = 0;  
     my ($sum,$max) = (0,0);      my ($sum,$max) = (0,0);
     foreach my $resource (@{$seq->{'contents'}}) {      foreach my $resource (@{$seq->{'contents'}}) {
         next if ($resource->{'type'} ne 'assessment');          next if ($resource->{'type'} ne 'assessment');
Line 426  sub StudentPerformanceOnSequence { Line 625  sub StudentPerformanceOnSequence {
                 }                  }
             }              }
             #              #
             $output_width++;              if ($links eq 'yes' && $symbol ne ' ') {
             if (defined($links) && $symbol ne ' ') {  
                 $symbol = '<a href="/adm/grades'.                  $symbol = '<a href="/adm/grades'.
                     '?symb='.&Apache::lonnet::escape($resource->{'symb'}).                      '?symb='.&Apache::lonnet::escape($resource->{'symb'}).
                         '&student='.$student->{'username'}.                          '&student='.$student->{'username'}.
Line 438  sub StudentPerformanceOnSequence { Line 636  sub StudentPerformanceOnSequence {
         }          }
         $Str .= $value;          $Str .= $value;
     }      }
     # Put on the totals  
     my $ratio = $sum.'/'.$max;  
     my $ratio_length = scalar(my @tmp1 = split(//,$ratio));  
     # Pad with extra spaces  
     my $width = $seq->{'width'};  
     $Str .= ' 'x($width-$output_width-$ratio_length).$ratio;  
     #  
     return ($Str,$sum,$max);      return ($Str,$sum,$max);
 }  }
   

Removed from v.1.30  
changed lines
  Added in v.1.31


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