Diff for /loncom/interface/statistics/lonstudentassessment.pm between versions 1.33 and 1.52

version 1.33, 2003/03/04 14:21:36 version 1.52, 2003/06/05 19:21:22
Line 85  my $Statistics; Line 85  my $Statistics;
   
 =item $show 'all', 'totals', or 'scores' determines how much data is output  =item $show 'all', 'totals', or 'scores' determines how much data is output
   
   =item $single_student_mode evaluates to true if we are showing only one
   student.
   
 =cut  =cut
   
 #######################################################  #######################################################
Line 92  my $Statistics; Line 95  my $Statistics;
 my $show_links;  my $show_links;
 my $output_mode;  my $output_mode;
 my $show;  my $show;
   my $single_student_mode;
   
 #######################################################  #######################################################
 #######################################################  #######################################################
Line 127  Inputs: Line 131  Inputs:
 sub BuildStudentAssessmentPage {  sub BuildStudentAssessmentPage {
     my ($r,$c)=@_;      my ($r,$c)=@_;
     undef($Statistics);      undef($Statistics);
       $single_student_mode = 1 if ($ENV{'form.SelectedStudent'});
     #      #
     # Print out the HTML headers for the interface      # Print out the HTML headers for the interface
     #    This also parses the output mode selector      #    This also parses the output mode selector
     #    This step must always be done.      #    This step must always be done.
     $r->print(&CreateInterface());      $r->print(&CreateInterface());
     $r->print('<input type="hidden" name="notfirstrun" value="true" />');      $r->print('<input type="hidden" name="notfirstrun" value="true" />');
       $r->print('<input type="hidden" name="sort" value="'.
                 $ENV{'form.sort'}.'" />');
     $r->rflush();      $r->rflush();
     if (! exists($ENV{'form.notfirstrun'})) {      if (! exists($ENV{'form.notfirstrun'}) && ! $single_student_mode) {
         $r->print(<<ENDMSG);          $r->print(<<ENDMSG);
 <p>  <p>
 <font size="+1">  <font size="+2">
 Please make your selections in the boxes above and hit   Please make your selections in the boxes above and hit 
 the button marked &quot;Update&nbsp;Display&quot;.  the button marked &quot;Update&nbsp;Display&quot;.
 </font>  </font>
Line 156  ENDMSG Line 163  ENDMSG
         $initialize     = \&excel_initialize;          $initialize     = \&excel_initialize;
         $output_student = \&excel_outputstudent;          $output_student = \&excel_outputstudent;
         $finish         = \&excel_finish;          $finish         = \&excel_finish;
   #    } elsif ($output_mode eq 'multi-sheet excel') {
   #        $initialize     = \&multi_sheet_excel_initialize;
   #        $output_student = \&multi_sheet_excel_outputstudent;
   #        $finish         = \&multi_sheet_excel_finish;
     } elsif ($output_mode eq 'csv') {      } elsif ($output_mode eq 'csv') {
         $initialize     = \&csv_initialize;          $initialize     = \&csv_initialize;
         $output_student = \&csv_outputstudent;          $output_student = \&csv_outputstudent;
Line 164  ENDMSG Line 175  ENDMSG
     #      #
     if($c->aborted()) {  return ; }      if($c->aborted()) {  return ; }
     #      #
       # Determine which students we want to look at
       my @Students;
       if ($single_student_mode) {
           @Students = (&Apache::lonstatistics::current_student());
           $r->print(&next_and_previous_buttons());
           $r->rflush();
       } else {
           @Students = @Apache::lonstatistics::Students;
       }
       #
     # Call the initialize routine selected above      # Call the initialize routine selected above
     $initialize->($r);      $initialize->($r);
     foreach my $student (@Apache::lonstatistics::Students) {      foreach my $student (@Students) {
         if($c->aborted()) {           if($c->aborted()) { 
             $finish->($r);              $finish->($r);
             return ;               return ; 
Line 182  ENDMSG Line 203  ENDMSG
   
 #######################################################  #######################################################
 #######################################################  #######################################################
   sub next_and_previous_buttons {
       my $Str = '';
       $Str .= '<input type="hidden" name="SelectedStudent" value="'.
           $ENV{'form.SelectedStudent'}.'" />';
       #
       # Build the previous student link
       my $previous = &Apache::lonstatistics::previous_student();
       my $previousbutton = '';
       if (defined($previous)) {
           my $sname = $previous->{'username'}.':'.$previous->{'domain'};
           $previousbutton .= '<input type="button" value="'.
               'Previous Student ('.
               $previous->{'username'}.'@'.$previous->{'domain'}.')'.
               '" onclick="document.Statistics.SelectedStudent.value='.
               "'".$sname."'".';'.
               'document.Statistics.submit();" />';
       } else {
           $previousbutton .= '<input type="button" value="'.
               'Previous student (none)'.'" />';
       }
       #
       # Build the next student link
       my $next = &Apache::lonstatistics::next_student();
       my $nextbutton = '';
       if (defined($next)) {
           my $sname = $next->{'username'}.':'.$next->{'domain'};
           $nextbutton .= '<input type="button" value="'.
               'Next Student ('.
               $next->{'username'}.'@'.$next->{'domain'}.')'.
               '" onclick="document.Statistics.SelectedStudent.value='.
               "'".$sname."'".';'.
               'document.Statistics.submit();" />';
       } else {
           $nextbutton .= '<input type="button" value="'.
               'Next student (none)'.'" />';
       }
       #
       # Build the 'all students' button
       my $all = '';
       $all .= '<input type="button" value="All Students" '.
               '" onclick="document.Statistics.SelectedStudent.value='.
               "''".';'.'document.Statistics.submit();" />';
       $Str .= $previousbutton.('&nbsp;'x5).$all.('&nbsp;'x5).$nextbutton;
       return $Str;
   }
   
   #######################################################
   #######################################################
   
 sub get_student_fields_to_show {  sub get_student_fields_to_show {
     my @to_show = @Apache::lonstatistics::SelectedStudentData;      my @to_show = @Apache::lonstatistics::SelectedStudentData;
Line 194  sub get_student_fields_to_show { Line 263  sub get_student_fields_to_show {
     return @to_show;      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;  
 }  
   
   
 #######################################################  #######################################################
 #######################################################  #######################################################
   
Line 233  sub CreateInterface { Line 289  sub CreateInterface {
     $Str .= '<tr>';      $Str .= '<tr>';
     $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>Enrollment Status</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 .= '<td align="center"><b>Output Format</b></td>';
     $Str .= '</tr>'."\n";      $Str .= '</tr>'."\n";
Line 251  sub CreateInterface { Line 308  sub CreateInterface {
     $Str .= &Apache::lonstatistics::StudentDataSelect('StudentData','multiple',      $Str .= &Apache::lonstatistics::StudentDataSelect('StudentData','multiple',
                                                       5,undef);                                                        5,undef);
     $Str .= '</td><td>'."\n";      $Str .= '</td><td>'."\n";
       $Str .= &Apache::lonhtmlcommon::StatusOptions(undef,undef,5);
       $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 .= '</td><td>'."\n";
Line 275  my @OutputOptions = Line 334  my @OutputOptions =
     ({ name  => 'HTML, with links',      ({ name  => 'HTML, with links',
        value => 'html, with links',         value => 'html, with links',
        description => 'Output HTML with each symbol linked to the problem '.         description => 'Output HTML with each symbol linked to the problem '.
    'which generated it.'},     'which generated it.',
          mode => 'html',
          show => 'all',
          show_links => 'yes',
          },
        { name  => 'HTML, with all links',
          value => 'html, with all links',
          description => 'Output HTML with each symbol linked to the problem '.
      'which generated it.  '.
              'This includes links for unattempted problems.',
          mode => 'html',
          show => 'all',
          show_links => 'all',
          },
      { name  => 'HTML, without links',       { name  => 'HTML, without links',
        value => 'html, without links',         value => 'html, without links',
        description => 'Output HTML.  By not including links, the size of the'.         description => 'Output HTML.  By not including links, the size of the'.
    ' web page is greatly reduced.  If your browser crashes on the '.     ' web page is greatly reduced.  If your browser crashes on the '.
    'full display, try this.'},     'full display, try this.',
          mode => 'html',
          show => 'all',
          show_links => 'no',
              },
      { name  => 'HTML, scores only',       { name  => 'HTML, scores only',
        value => 'html, scores only',         value => 'html, scores only',
        description => 'Output HTML, only showing the total number of correct'.         description => 'Output HTML, only showing the total number of correct'.
    ' problems (or problem parts) and not the maximum possible for '.     ' problems (or problem parts) and not the maximum possible for '.
    'each student'},     'each student',
          mode => 'html',
          show => 'scores',
          show_links => 'no',
              },
      { name  => 'HTML, totals',       { name  => 'HTML, totals',
        value => 'html, totals',         value => 'html, totals',
        description => 'Output HTML, but only the summary statistics for each'.         description => 'Output HTML, but only the summary statistics for each'.
    ' sequence selected.'},     ' sequence selected for each student.',
          mode => 'html',
          show => 'totals',
          show_links => 'no',
          },
        { name  => 'HTML, summary table only',
          value => 'html summary table only',
          description => 'Output HTML, but only the final summary table for '.
              'all students across all sequences.',
          mode => 'html',
          show => 'final table',
          show_links => 'no',
          },
      { name  => 'Excel, scores only',       { name  => 'Excel, scores only',
        value => 'excel, scores only',         value => 'excel, scores only',
        description => 'Output an Excel file (compatable with Excel 95), '.         description => 'Output an Excel file (compatable with Excel 95), '.
    'with a single column for each sequence showing the students '.     'with a single column for each sequence showing the students '.
    'score.'},     'score.',
 #     { name  => 'Excel, everything',         mode => 'excel',
 #       value => 'excel, everything',         show => 'scores',
 #       description => 'Output an Excel file (compatable with Excel 95), '.         show_links => 'no',
 #   'with a seperate worksheet for each sequence you have selected '.             },
 #           'the data for each problem part '.  
 #           '(number of tries, status, points awarded) '.  
 #           'will be listed.'},  
      { name  => 'Excel, totals',       { name  => 'Excel, totals',
        value => 'excel, totals',         value => 'excel, totals',
        description => 'Output an Excel file (compatable with Excel 95), '.         description => 'Output an Excel file (compatable with Excel 95), '.
    'with two columns for each sequence, the students score on the '.     'with two columns for each sequence, the students score on the '.
    'sequence and the students maximum possible on the sequence'},     'sequence and the students maximum possible on the sequence',
          mode => 'excel',
          show => 'totals',
          show_links => 'no',
              },
   #     { name  => 'multi-sheet Excel',
   #       value => 'multi-sheet excel',
   #       description => 'Output an Excel file (compatable with Excel 95), '.
   #   'with a seperate worksheet for each sequence you have selected '.
   #           'the data for each problem part '.
   #           '(number of tries, status, points awarded) will be listed.',
   #       mode => 'multi-sheet excel',
   #       show => 'totals',
   #       show_links => 'no',
   #           },
   #     { name  => 'multi-sheet Excel, by section',
   #       value => 'multi-sheet excel, by section',
   #       description => 'Output an Excel file (compatable with Excel 95), '.
   #   'with a seperate worksheet for each sequence you have selected '.
   #           'the data for each problem part '.
   #           '(number of tries, status, points awarded) will be listed.  '.
   #           'There will be one Excel workbook for each section selected.',
   #       mode => 'multi-sheet excel',
   #       show => 'by section',
   #       show_links => 'no',
   #           },
      { name  => 'CSV, everything',       { name  => 'CSV, everything',
        value => 'csv, everything',         value => 'csv, everything',
        description => ''},         description => '',
          mode => 'csv',
          show => 'all',
          show_links => 'no',
              },
      { name  => 'CSV, scores only',       { name  => 'CSV, scores only',
        value => 'csv, scores only',         value => 'csv, scores only',
        description => ''},         description => '',
          mode => 'csv',
          show => 'scores',
          show_links => 'no',
              },
      { name  => 'CSV, totals',       { name  => 'CSV, totals',
        value => 'csv, totals',         value => 'csv, totals',
        description => ''},         description => '',
          mode => 'csv',
          show => 'totals',
          show_links => 'no',
              },
      );       );
   
 sub OutputDescriptions {  sub OutputDescriptions {
Line 332  sub OutputDescriptions { Line 458  sub OutputDescriptions {
   
 sub CreateAndParseOutputSelector {  sub CreateAndParseOutputSelector {
     my $Str = '';      my $Str = '';
     my $elementname = 'outputmode';      my $elementname = 'chartoutputmode';
     #      #
     # Format for output options is 'mode, restrictions';      # Format for output options is 'mode, restrictions';
     my $selected = 'html, with links';      my $selected = 'html, without links';
     if (exists($ENV{'form.'.$elementname})) {      if (exists($ENV{'form.'.$elementname})) {
         if (ref($ENV{'form.'.$elementname} eq 'ARRAY')) {          if (ref($ENV{'form.'.$elementname} eq 'ARRAY')) {
             $selected = $ENV{'form.'.$elementname}->[0];              $selected = $ENV{'form.'.$elementname}->[0];
Line 348  sub CreateAndParseOutputSelector { Line 474  sub CreateAndParseOutputSelector {
     $show_links  = 'no';      $show_links  = 'no';
     $output_mode = 'html';      $output_mode = 'html';
     $show        = 'all';      $show        = 'all';
     my ($mode,$restriction) = split(',',$selected);      foreach my $option (@OutputOptions) {
     $restriction =~ s/^\s*//;          next if ($option->{'value'} ne $selected);
     if ($mode =~ /^(html|excel|csv)$/) {          $output_mode = $option->{'mode'};
         $output_mode = $mode;          $show        = $option->{'show'};
     } else {          $show_links  = $option->{'show_links'};
         $output_mode = 'html';  
     }  
     if ($restriction eq 'with links') {  
         $show_links = 'yes';  
     } else {  
         $show_links = 'no';  
     }  
     if ($restriction eq 'totals') {  
         $show = 'totals';  
     } elsif ($restriction eq 'scores only') {  
         $show = 'scores';  
     } else {  
         $show = 'everything';  
     }      }
   
     #      #
     # Build the form element      # Build the form element
     $Str = qq/<select size="5" name="$elementname">/;      $Str = qq/<select size="5" name="$elementname">/;
Line 404  Return a line of the chart for a student Line 518  Return a line of the chart for a student
     my $padding;      my $padding;
     my $count;      my $count;
   
       my $nodata_count; # The number of students for which there is no data
       my %prog_state;   # progress state used by loncommon PrgWin routines
   
 sub html_initialize {  sub html_initialize {
     my ($r) = @_;      my ($r) = @_;
     #      #
     $padding = ' 'x3;      $padding = ' 'x3;
     $count = 1;      $count = 0;
       $nodata_count = 0;
       #
       $r->print("<h3>".$ENV{'course.'.$ENV{'request.course.id'}.'.description'}.
                 "&nbsp;&nbsp;".localtime(time)."</h3>");
   
     #      #
       # Set up progress window for 'final table' display only
       if ($show eq 'final table') {
           my $studentcount = scalar(@Apache::lonstatistics::Students); 
           %prog_state=&Apache::lonhtmlcommon::Create_PrgWin
               ($r,'Summary Table Status',
                'Summary Table Compilation Progress', $studentcount);
       }
     my $Str = "<pre>\n";      my $Str = "<pre>\n";
     # First, the @StudentData fields need to be listed      # First, the @StudentData fields need to be listed
     my @to_show = &get_student_fields_to_show();      my @to_show = &get_student_fields_to_show();
Line 420  sub html_initialize { Line 549  sub html_initialize {
         $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 $sequence (&get_sequences_to_show) {      foreach my $sequence (&Apache::lonstatistics::Sequences_with_Assess()){
         my $title = $sequence->{'title'};          my $title = $sequence->{'title'};
         my $base  = $sequence->{'base_width'};          my $base  = $sequence->{'base_width'};
         my $width = $sequence->{'width'};          my $width = $sequence->{'width'};
Line 428  sub html_initialize { Line 557  sub html_initialize {
     }      }
     $Str .= "total (of shown problems)</pre>\n";      $Str .= "total (of shown problems)</pre>\n";
     $Str .= "<pre>";      $Str .= "<pre>";
       #
       # Check for suppression of output
       if ($show eq 'final table') {
           $Str = '';
       }
     $r->print($Str);      $r->print($Str);
     $r->rflush();      $r->rflush();
     return;      return;
Line 436  sub html_initialize { Line 570  sub html_initialize {
 sub html_outputstudent {  sub html_outputstudent {
     my ($r,$student) = @_;      my ($r,$student) = @_;
     my $Str = '';      my $Str = '';
       #
       if($count++ % 5 == 0 && $count > 0) {
           $r->print("</pre><pre>");
       }
     # First, the @StudentData fields need to be listed      # First, the @StudentData fields need to be listed
     my @to_show = &get_student_fields_to_show();      my @to_show = &get_student_fields_to_show();
     foreach my $field (@to_show) {      foreach my $field (@to_show) {
Line 453  sub html_outputstudent { Line 591  sub html_outputstudent {
         %StudentsData = @tmp;          %StudentsData = @tmp;
     }      }
     if (scalar(@tmp) < 1) {      if (scalar(@tmp) < 1) {
           $nodata_count++;
           return if ($show eq 'final table');
         $Str .= '<font color="blue">No Course Data</font>'."\n";          $Str .= '<font color="blue">No Course Data</font>'."\n";
         $r->print($Str);          $r->print($Str);
         $r->rflush();          $r->rflush();
Line 462  sub html_outputstudent { Line 602  sub html_outputstudent {
     # By sequence build up the data      # By sequence build up the data
     my $studentstats;      my $studentstats;
     my $PerformanceStr = '';      my $PerformanceStr = '';
     foreach my $seq (&get_sequences_to_show) {      foreach my $seq (&Apache::lonstatistics::Sequences_with_Assess()) {
         my ($performance,$score,$seq_max) =          my ($performance,$performance_length,$score,$seq_max) =
             &StudentPerformanceOnSequence($student,\%StudentsData,              &StudentPerformanceOnSequence($student,\%StudentsData,
                                           $seq,$show_links);                                            $seq,$show_links);
         my $ratio = $score.'/'.$seq_max;          my $ratio = $score.'/'.$seq_max;
Line 476  sub html_outputstudent { Line 616  sub html_outputstudent {
             $performance .= ' 'x($seq->{'width'}-length($performance));              $performance .= ' 'x($seq->{'width'}-length($performance));
         } else {          } else {
             # Pad with extra spaces              # Pad with extra spaces
             $performance .= ' 'x($seq->{'width'}-$seq_max-              $performance .= ' 'x($seq->{'width'}-$performance_length-
                                  length($ratio)                                   length($ratio)
                                  ).$ratio;                                   ).$ratio;
         }          }
Line 497  sub html_outputstudent { Line 637  sub html_outputstudent {
     }      }
     $Str .= ' '.' 'x(length($max)-length($score)).$score.'/'.$max;      $Str .= ' '.' 'x(length($max)-length($score)).$score.'/'.$max;
     $Str .= " \n";      $Str .= " \n";
     $r->print($Str);  
     #      #
     $count++;      # Check for suppressed output and update the progress window if so...
     if($count % 5 == 0) {      if ($show eq 'final table') {
         $r->print("</pre><pre>");          $Str = '';
           &Apache::lonhtmlcommon::Increment_PrgWin($r,\%prog_state,
                                                    'last student');
     }      }
     #      #
       $r->print($Str);
       #
     $r->rflush();      $r->rflush();
     return;      return;
 }      }    
   
 sub html_finish {  sub html_finish {
     my ($r) = @_;      my ($r) = @_;
     $r->print("</pre>\n");       #
       # Check for suppressed output and close the progress window if so
       if ($show eq 'final table') {
           &Apache::lonhtmlcommon::Close_PrgWin($r,\%prog_state);
       } else {
           $r->print("</pre>\n"); 
       }
       if ($single_student_mode) {
           $r->print(&SingleStudentTotal());
       } else {
           $r->print(&StudentAverageTotal());
       }
     $r->rflush();      $r->rflush();
     return;      return;
 }  }
   
   sub StudentAverageTotal {
       my $Str = "<h3>Summary Tables</h3>\n";
       my $num_students = scalar(@Apache::lonstatistics::Students);
       my $total_ave = 0;
       my $total_max = 0;
       $Str .= '<table border=2 cellspacing="1">'."\n";
       $Str .= "<tr><th>Title</th><th>Average</th><th>Maximum</th></tr>\n";
       foreach my $seq (&Apache::lonstatistics::Sequences_with_Assess()) {
           my $ave;
           if ($num_students > $nodata_count) {
               $ave = int(100*($Statistics->{$seq->{'symb'}}->{'score'}/
                               ($num_students-$nodata_count)))/100;
           } else {
               $ave = 0;
           }
           $total_ave += $ave;
           my $max = $seq->{'num_assess_parts'};
           $total_max += $max;
           if ($ave == 0) {
               $ave = "0.00";
           }
           $ave .= '&nbsp;';
           $max .= '&nbsp;&nbsp;&nbsp;';
           $Str .= '<tr><td>'.$seq->{'title'}.'</td>'.
               '<td align="right">'.$ave.'</td>'.
                   '<td align="right">'.$max.'</td></tr>'."\n";
       }
       $total_ave = int(100*$total_ave)/100; # only two digit
       $Str .= "</table>\n";
       $Str .= '<table border=2 cellspacing="1">'."\n";
       $Str .= '<tr><th>Number of Students</th><th>Average</th>'.
           "<th>Maximum</th></tr>\n";
       $Str .= '<tr><td>'.($num_students-$nodata_count).'</td>'.
           '<td>'.$total_ave.'</td><td>'.$total_max.'</td>';
       $Str .= "</table>\n";
       return $Str;
   }
   
   sub SingleStudentTotal {
       my $student = &Apache::lonstatistics::current_student();
       my $Str = "<h3>Summary table for ".$student->{'fullname'}." ".
           $student->{'username'}.'@'.$student->{'domain'}."</h3>\n";
       $Str .= '<table border=2 cellspacing="1">'."\n";
       $Str .= 
           "<tr><th>Sequence or Folder</th><th>Score</th><th>Maximum</th></tr>\n";
       my $total = 0;
       my $total_max = 0;
       foreach my $seq (&Apache::lonstatistics::Sequences_with_Assess()) {
           my $value = $Statistics->{$seq->{'symb'}}->{'score'};
           my $max = $Statistics->{$seq->{'symb'}}->{'max'};
           $Str .= '<tr><td>'.$seq->{'title'}.'</td>'.
               '<td align="right">'.$value.'</td>'.
                   '<td align="right">'.$max.'</td></tr>'."\n";
           $total += $value;
           $total_max +=$max;
       }
       $Str .= '<tr><td><b>Total</b></td>'.
           '<td align="right">'.$total.'</td>'.
           '<td align="right">'.$total_max."</td></tr>\n";
       $Str .= "</table>\n";
       return $Str;
   }
   
 }  }
   
 #######################################################  #######################################################
Line 522  sub html_finish { Line 739  sub html_finish {
   
 =pod  =pod
   
   =head2 Multi-Sheet EXCEL subroutines
   
   =item &multi_sheet_excel_initialize($r)
   
   =item &multi_sheet_excel_outputstudent($r,$student)
   
   =item &multi_sheet_excel_finish($r)
   
   =cut
   
   #######################################################
   #######################################################
   {
   
   sub multi_sheet_excel_initialize {
       my ($r)=@_;
       $r->print("<h1>Not yet implemented</h1>");
       # 
       # Estimate the size of the file.  We would like to have < 5 megs of data.
       my $max_size = 5000000;
       my $num_students  = scalar(@Apache::lonstatistics::Students);
       my $num_sequences = 0;
       my $num_data_per_part  = 2; # 'status' and 'numtries'
       my $fields_per_student = scalar(&get_student_fields_to_show());
       my $bytes_per_field    = 20; # Back of the envelope calculation
       foreach my $seq (&Apache::lonstatistics::Sequences_with_Assess()) {
           $num_sequences++ if ($seq->{'num_assess'} > 0);
           $fields_per_student += $num_data_per_part * $seq->{'num_assess_parts'};
       }
       my $size_estimate = $fields_per_student*$num_students*$bytes_per_field;
       #
       # Compute number of workbooks
       my $num_workbooks = 1;
       if ($size_estimate > $max_size) { # try to stay under 5 megs
           $num_workbooks += int($size_estimate / $max_size);
       }
       if ($show eq 'by section') {
           if (@Apache::lonstatistics::SelectedSections > 1 && 
               $Apache::lonstatistics::SelectedSections[0] ne 'all') {
               $num_workbooks = scalar(@Apache::lonstatistics::SelectedSections);
           } else {
               # @Apache::lonstatistics::Sections contains 'all' as well.
               $num_workbooks = scalar(@Apache::lonstatistics::Sections) - 1;
           }
       }
       
       $r->print("Maximum allowed size: ".$max_size." bytes<br />");
       $r->print("Number of students: ".$num_students."<br />");
       $r->print("Number of fields per student: ".$fields_per_student."<br />");
       $r->print("Total number of fields: ".($fields_per_student*$num_students).
                 "<br />");
       $r->print("Bytes per field: ".$bytes_per_field." (estimated)"."<br />");
       $r->print("Estimated size: ".$size_estimate." bytes<br />");
       $r->print("Number of workbooks: ".$num_workbooks."<br />");
       $r->rflush();
       return;
   }
   
   sub multi_sheet_excel_outputstudent {
       my ($r,$student) = @_;
   }
   
   sub multi_sheet_excel_finish {
       my ($r) = @_;
   }
   
   }
   #######################################################
   #######################################################
   
   =pod
   
 =head2 EXCEL subroutines  =head2 EXCEL subroutines
   
 =item &excel_initialize($r)  =item &excel_initialize($r)
Line 543  my $filename; Line 832  my $filename;
 my $rows_output;  my $rows_output;
 my $cols_output;  my $cols_output;
   
 my $num_students;  my %prog_state; # progress window state
 my $start_time;  
   
 sub excel_initialize {  sub excel_initialize {
     my ($r) = @_;      my ($r) = @_;
Line 559  sub excel_initialize { Line 847  sub excel_initialize {
     $rows_output = 0;      $rows_output = 0;
     $cols_output = 0;      $cols_output = 0;
     #      #
     $num_students = 0;  
     $start_time   = time;  
     #  
     # Create sheet      # Create sheet
     $excel_workbook = Spreadsheet::WriteExcel->new('/home/httpd'.$filename);      $excel_workbook = Spreadsheet::WriteExcel->new('/home/httpd'.$filename);
     #      #
Line 587  sub excel_initialize { Line 872  sub excel_initialize {
     }      }
     $excel_sheet = $excel_workbook->addworksheet($sheetname);      $excel_sheet = $excel_workbook->addworksheet($sheetname);
     #      #
       # Put the course description in the header
       $excel_sheet->write($rows_output,$cols_output++,
                      $ENV{'course.'.$ENV{'request.course.id'}.'.description'});
       $cols_output += 3;
       #
       # Put a description of the sections listed
       my $sectionstring = '';
       my @Sections = @Apache::lonstatistics::SelectedSections;
       if (scalar(@Sections) > 1) {
           if (scalar(@Sections) > 2) {
               my $last = pop(@Sections);
               $sectionstring = "Sections ".join(', ',@Sections).', and '.$last;
           } else {
               $sectionstring = "Sections ".join(' and ',@Sections);
           }
       } else {
           if ($Sections[0] eq 'all') {
               $sectionstring = "All sections";
           } else {
               $sectionstring = "Section ".$Sections[0];
           }
       }
       $excel_sheet->write($rows_output,$cols_output++,$sectionstring);
       $cols_output += scalar(@Sections);
       #
       # Put the date in there too
       $excel_sheet->write($rows_output,$cols_output++,
                           'Compiled on '.localtime(time));
       #
       $rows_output++;
       #
     # Add the student headers      # Add the student headers
       $cols_output = 0;
     foreach my $field (&get_student_fields_to_show()) {      foreach my $field (&get_student_fields_to_show()) {
         $excel_sheet->write(1,$cols_output++,$field);          $excel_sheet->write($rows_output,$cols_output++,$field);
     }      }
     #      #
     # Add the Sequence Headers      # Add the Sequence Headers
     foreach my $seq (&get_sequences_to_show) {      foreach my $seq (&Apache::lonstatistics::Sequences_with_Assess()) {
         $excel_sheet->write(0,$cols_output,$seq->{'title'});          $excel_sheet->write($rows_output,$cols_output,$seq->{'title'});
         if ($show eq 'totals') {          if ($show eq 'totals') {
             $excel_sheet->write(1,$cols_output,'score');              $excel_sheet->write($rows_output+1,$cols_output,'score');
             $excel_sheet->write(1,$cols_output+1,'maximum');              $excel_sheet->write($rows_output+1,$cols_output+1,'maximum');
             $cols_output += 2;              $cols_output += 2;
         } else {          } else {
             $cols_output++;              $cols_output++;
Line 606  sub excel_initialize { Line 923  sub excel_initialize {
     #      #
     # Bookkeeping      # Bookkeeping
     if ($show eq 'totals') {      if ($show eq 'totals') {
         $rows_output = 2;          $rows_output += 2;
     } else {      } else {
         $rows_output = 1;          $rows_output += 1;
       }
       #
       # Output a row for MAX
       if ($show ne 'totals') {
           $cols_output = 0;
           foreach my $field (&get_student_fields_to_show()) {
               if ($field eq 'username' || $field eq 'fullname' || 
                   $field eq 'id') {
                   $excel_sheet->write($rows_output,$cols_output++,'Maximum');
               } else {
                   $excel_sheet->write($rows_output,$cols_output++,'');
               }
           }
           #
           # Add the Sequence Headers
           foreach my $seq (&Apache::lonstatistics::Sequences_with_Assess()) {
               $excel_sheet->write($rows_output,$cols_output++,
                                   $seq->{'num_assess_parts'});
           }
           $rows_output++;
     }      }
     #      #
     # Let the user know what we are doing      # Let the user know what we are doing
Line 619  sub excel_initialize { Line 956  sub excel_initialize {
     $r->print("</h1>\n");      $r->print("</h1>\n");
     $r->rflush();      $r->rflush();
     #      #
       # Initialize progress window
       %prog_state=&Apache::lonhtmlcommon::Create_PrgWin
           ($r,'Excel File Compilation Status',
            'Excel File Compilation Progress', $studentcount);
       #
     return;      return;
 }  }
   
Line 644  sub excel_outputstudent { Line 986  sub excel_outputstudent {
     }      }
     #      #
     # Write out sequence scores and totals data      # Write out sequence scores and totals data
     foreach my $seq (&get_sequences_to_show) {      foreach my $seq (&Apache::lonstatistics::Sequences_with_Assess()) {
         my ($performance,$score,$seq_max) =          my ($performance,$performance_length,$score,$seq_max) =
             &StudentPerformanceOnSequence($student,\%StudentsData,              &StudentPerformanceOnSequence($student,\%StudentsData,
                                           $seq,'no');                                            $seq,'no');
         if ($show eq 'totals' || $show eq 'scores') {          if ($show eq 'totals' || $show eq 'scores') {
Line 660  sub excel_outputstudent { Line 1002  sub excel_outputstudent {
     $rows_output++;       $rows_output++; 
     $cols_output=0;      $cols_output=0;
     #      #
     # Time estimate      # Update the progress window
     $num_students++;      &Apache::lonhtmlcommon::Increment_PrgWin($r,\%prog_state,'last student');
     if ($num_students % 10 == 0) {  
         my $time_est = (time - $start_time)/$num_students *   
             (scalar(@Apache::lonstatistics::Students)-$num_students);  
         $time_est = int($time_est);  
         if (int ($time_est/60) > 0) {  
             my $min = int($time_est/60);  
             my $sec = $time_est % 60;  
             $time_est = $min.' minutes';  
             if ($sec > 1) {  
                 $time_est.= ', '.$sec.' seconds';  
             } elsif ($sec > 0) {  
                 $time_est.= ', '.$sec.' second';  
             }  
         } else {  
             $time_est .= ' seconds';  
         }  
         $r->print($num_students.' out of '.  
                   (scalar(@Apache::lonstatistics::Students)).  
                   " students processed.  ".  
                   $time_est." remain.  <br />\n");  
         $r->rflush();  
     }  
     return;      return;
 }  }
   
Line 697  sub excel_finish { Line 1017  sub excel_finish {
     #      #
     return if($c->aborted());      return if($c->aborted());
     #      #
       # Close the progress window
       &Apache::lonhtmlcommon::Close_PrgWin($r,\%prog_state);
       #
     # Tell the user where to get their excel file      # Tell the user where to get their excel file
     $r->print('<br /><br />'.      $r->print('<br />'.
               '<a href="'.$filename.'">Your Excel spreadsheet.</a>'."\n");                '<a href="'.$filename.'">Your Excel spreadsheet.</a>'."\n");
     my $total_time = time - $start_time;  
     if (int ($total_time / 60) > 0) {  
         $total_time = int($total_time/60).' minutes, '.($total_time % 60);  
     }  
     $r->print('<br />'.$total_time.' seconds total');  
     $r->rflush();      $r->rflush();
     return;      return;
 }  }
Line 729  sub excel_finish { Line 1047  sub excel_finish {
 #######################################################  #######################################################
 {  {
   
   my $outputfile;
   my $filename;
   
   my %prog_state; # progress window state
   
 sub csv_initialize{  sub csv_initialize{
     my ($r) = @_;      my ($r) = @_;
     $r->print("<h1>Not implemented yet</h1>");      # 
       # Clean up
       $filename = undef;
       $outputfile = undef;
       undef(%prog_state);
       #
       # Open a file
       $filename = '/prtspool/'.
           $ENV{'user.name'}.'_'.$ENV{'user.domain'}.'_'.
               time.'_'.rand(1000000000).'.csv';
       unless ($outputfile = Apache::File->new('>/home/httpd'.$filename)) {
           $r->log_error("Couldn't open $filename for output $!");
           $r->print("Problems occured in writing the csv file.  ".
                     "This error has been logged.  ".
                     "Please alert your LON-CAPA administrator.");
           $outputfile = undef;
       }
       #
       # Datestamp
       my $description = $ENV{'course.'.$ENV{'request.course.id'}.'.description'};
       print $outputfile '"'.&Apache::loncommon::csv_translate($description).'",'.
           '"'.&Apache::loncommon::csv_translate(scalar(localtime(time))).'"'.
               "\n";
   
       #
       # Print out the headings
       my $Str = '';
       my $Str2 = undef;
       foreach my $field (&get_student_fields_to_show()) {
           if ($show eq 'scores') {
               $Str .= '"'.&Apache::loncommon::csv_translate($field).'",';
           } elsif ($show eq 'totals') {
               $Str .= '"",'; # first row empty on the student fields
               $Str2 .= '"'.&Apache::loncommon::csv_translate($field).'",';
           } elsif ($show eq 'all') {
               $Str .= '"'.&Apache::loncommon::csv_translate($field).'",';
           }
       }
       foreach my $seq (&Apache::lonstatistics::Sequences_with_Assess()) {
           if ($show eq 'scores') {
               $Str .= '"'.&Apache::loncommon::csv_translate($seq->{'title'}).
                   '",';
           } elsif ($show eq 'totals') {
               $Str  .= '"'.&Apache::loncommon::csv_translate($seq->{'title'}).
                   '","",';
               $Str2 .= '"score","total possible",';
           } elsif ($show eq 'all') {
               $Str  .= '"'.&Apache::loncommon::csv_translate($seq->{'title'}).
                   '",';
               $Str .= '"",'x($seq->{'num_assess_parts'}-1);
               $Str .= '"score","total possible",';
           }
       }
       chop($Str);
       $Str .= "\n";
       print $outputfile $Str;
       if (defined($Str2)) {
           chop($Str2);
           $Str2 .= "\n";
           print $outputfile $Str2;
       }
       #
       # Initialize progress window
       my $studentcount = scalar(@Apache::lonstatistics::Students);
       %prog_state=&Apache::lonhtmlcommon::Create_PrgWin
           ($r,'CSV File Compilation Status',
            'CSV File Compilation Progress', $studentcount);
     return;      return;
 }  }
   
 sub csv_outputstudent {  sub csv_outputstudent {
     my ($r,$student) = @_;      my ($r,$student) = @_;
       return if (! defined($outputfile));
       my $Str = '';
       #
       # Output student fields
       my @to_show = &get_student_fields_to_show();
       foreach my $field (@to_show) {
           $Str .= '"'.&Apache::loncommon::csv_translate($student->{$field}).'",';
       }
       #
       # Get student assessment data
       my %StudentsData;
       my @tmp = &Apache::loncoursedata::get_current_state($student->{'username'},
                                                           $student->{'domain'},
                                                           undef,
                                                      $ENV{'request.course.id'});
       if ((scalar @tmp > 0) && ($tmp[0] !~ /^error:/)) {
           %StudentsData = @tmp;
       }
       #
       # Output performance data
       foreach my $seq (&Apache::lonstatistics::Sequences_with_Assess()) {
           my ($performance,$performance_length,$score,$seq_max) =
               &StudentPerformanceOnSequence($student,\%StudentsData,
                                             $seq,'no');
           if ($show eq 'scores') {
               $Str .= '"'.$score.'",';
           } elsif ($show eq 'totals') {
               $Str  .= '"'.$score.'","'.$seq_max.'",';
           } elsif ($show eq 'all') {
               $Str .= '"'.join('","',(split(//,$performance),$score,$seq_max)).
                   '",';
           }
       }
       chop($Str);
       $Str .= "\n";
       print $outputfile $Str;
       #
       # Update the progress window
       &Apache::lonhtmlcommon::Increment_PrgWin($r,\%prog_state,'last student');
       return;
 }  }
   
 sub csv_finish {  sub csv_finish {
     my ($r) = @_;      my ($r) = @_;
       return if (! defined($outputfile));
       close($outputfile);
       #
       my $c = $r->connection();
       return if ($c->aborted());
       #
       # Close the progress window
       &Apache::lonhtmlcommon::Close_PrgWin($r,\%prog_state);
       #
       # Tell the user where to get their csv file
       $r->print('<br />'.
                 '<a href="'.$filename.'">Your csv file.</a>'."\n");
       $r->rflush();
       return;
       
 }  }
   
 }  }
Line 775  sub StudentPerformanceOnSequence { Line 1219  sub StudentPerformanceOnSequence {
     $links = 'no' if (! defined($links));      $links = 'no' if (! defined($links));
     my $Str = '';      my $Str = '';
     my ($sum,$max) = (0,0);      my ($sum,$max) = (0,0);
       my $performance_length = 0;
     foreach my $resource (@{$seq->{'contents'}}) {      foreach my $resource (@{$seq->{'contents'}}) {
         next if ($resource->{'type'} ne 'assessment');          next if ($resource->{'type'} ne 'assessment');
         my $resource_data = $studentdata->{$resource->{'symb'}};          my $resource_data = $studentdata->{$resource->{'symb'}};
         my $value = '';          my $value = '';
         foreach my $partnum (@{$resource->{'parts'}}) {          foreach my $partnum (@{$resource->{'parts'}}) {
             $max++;              $max++;
               $performance_length++;
             my $symbol = ' '; # default to space              my $symbol = ' '; # default to space
             #              #
             if (exists($resource_data->{'resource.'.$partnum.'.solved'})) {              if (exists($resource_data->{'resource.'.$partnum.'.solved'})) {
Line 808  sub StudentPerformanceOnSequence { Line 1254  sub StudentPerformanceOnSequence {
                         $symbol = ' ';                          $symbol = ' ';
                     }                      }
                     $sum++;                      $sum++;
                   } elsif (exists($resource_data->{'resource.'.
                                                        $partnum.'.tries'})){
                       $symbol = '.';
                 } else {                  } else {
                     $symbol = ' ';                      $symbol = ' ';
                 }                  }
Line 819  sub StudentPerformanceOnSequence { Line 1268  sub StudentPerformanceOnSequence {
                     $symbol = ' ';                      $symbol = ' ';
                 }                  }
             }              }
   #            if ($symbol ne ' ') {
   #                $attempted_sum++;
   #            }
             #              #
             if ($links eq 'yes' && $symbol ne ' ') {              if ( ($links eq 'yes' && $symbol ne ' ') ||
                    ($links eq 'all')) {
                   if (length($symbol) > 1) {
                       &Apache::lonnet::logthis('length of symbol "'.$symbol.'" > 1');
                   }
                 $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 831  sub StudentPerformanceOnSequence { Line 1287  sub StudentPerformanceOnSequence {
         }          }
         $Str .= $value;          $Str .= $value;
     }      }
     return ($Str,$sum,$max);      if ($seq->{'randompick'}) {
 }          $max = $seq->{'randompick'};
   
 #######################################################  
 #######################################################  
 sub StudentAverageTotal {  
     my ($cache, $students, $sequenceKeys)=@_;  
     my $Str = "\n<b>Summary Tables:</b>\n";  
     my %Correct = ();  
     my $ProblemsSolved = 0;  
     my $TotalProblems = 0;  
     my $StudentCount = 0;  
   
     foreach my $name (@$students) {  
         $StudentCount++;  
         foreach my $sequence (@$sequenceKeys) {  
             $Correct{$sequence} +=  
        $cache->{$name.':'.$sequence.':problemsCorrect'};  
         }  
  $ProblemsSolved += $cache->{$name.':problemsSolved'};  
         $TotalProblems += $cache->{$name.':totalProblems'};  
     }  
     if ($StudentCount) {   
         $ProblemsSolved = sprintf( "%.2f",   
                              $ProblemsSolved/$StudentCount);  
         $TotalProblems /= $StudentCount;  
     } else {  
         $ProblemsSolved = 0;  
         $TotalProblems  = 0;  
     }  
   
     $Str .= '<table border=2 cellspacing="1">'."\n";  
     $Str .= '<tr><td><b>Students Count</b></td><td><b>'.  
             $StudentCount.'</b></td></tr>'."\n";  
     $Str .= '<tr><td><b>Total Problems</b></td><td><b>'.  
             $TotalProblems.'</b></td></tr>'."\n";  
     $Str .= '<tr><td><b>Average Correct</b></td><td><b>'.  
             $ProblemsSolved.'</b></td></tr>'."\n";  
     $Str .= '</table>'."\n";  
   
     $Str .= '<table border=2 cellspacing="1">'."\n";  
     $Str .= '<tr><th>Title</th><th>Total Problems</th>'.  
             '<th>Average Correct</th></tr>'."\n";  
     foreach my $S(@$sequenceKeys) {  
         my $title=$cache->{$S.':title'};  
  #$Str .= $cache->{$S.':problems'};  
  #my @problems=split(':', $cache->{$S.':problems'});  
  #my $pCount=scalar @problems;  
  my $pCount=MaxSeqPr($cache,@$students[0],$S);  
         my $crr;  
  if ($StudentCount) {  
             $crr=sprintf( "%.2f", $Correct{$S}/$StudentCount );  
         } else {  
             $crr="0.00";  
         }  
         $Str .= '<tr><td>'.$title.  
                 '</td><td align=center>'.$pCount.  
                 '</td><td align=center>'.$crr.  
                 '</td></tr>'."\n";  
     }      }
       return ($Str,$performance_length,$sum,$max);
     $Str .= '</table>'."\n";  
   
     return $Str;  
 }  }
   
 #######################################################  #######################################################

Removed from v.1.33  
changed lines
  Added in v.1.52


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