[LON-CAPA-cvs] cvs: loncom /interface/statistics lonstudentassessment.pm

matthew lon-capa-cvs@mail.lon-capa.org
Mon, 03 Mar 2003 22:54:05 -0000


This is a MIME encoded message

--matthew1046732045
Content-Type: text/plain

matthew		Mon Mar  3 17:54:05 2003 EDT

  Modified files:              
    /loncom/interface/statistics	lonstudentassessment.pm 
  Log:
  Implemented Excel output.  Should be pretty much done.  Two output modes.
  One gives score and max possible for each sequence for each student.
  Second gives only scores for each sequence for each student, saving columns.
  Beginning to change output selector.
  
  
--matthew1046732045
Content-Type: text/plain
Content-Disposition: attachment; filename="matthew-20030303175405.txt"

Index: loncom/interface/statistics/lonstudentassessment.pm
diff -u loncom/interface/statistics/lonstudentassessment.pm:1.31 loncom/interface/statistics/lonstudentassessment.pm:1.32
--- loncom/interface/statistics/lonstudentassessment.pm:1.31	Mon Mar  3 14:28:29 2003
+++ loncom/interface/statistics/lonstudentassessment.pm	Mon Mar  3 17:54:05 2003
@@ -1,6 +1,6 @@
 # The LearningOnline Network with CAPA
 #
-# $Id: lonstudentassessment.pm,v 1.31 2003/03/03 19:28:29 matthew Exp $
+# $Id: lonstudentassessment.pm,v 1.32 2003/03/03 22:54:05 matthew Exp $
 #
 # Copyright Michigan State University Board of Trustees
 #
@@ -83,7 +83,7 @@
 
 =item $output_mode 'html', 'excel', or 'csv' for output mode
 
-=item $show 'all' or 'totals' determines how much data is output
+=item $show 'all', 'totals', or 'scores' determines how much data is output
 
 =cut
 
@@ -270,14 +270,41 @@
 
 #######################################################
 #######################################################
+my @OutputOptions = 
+    ({ name  => 'HTML, with links',
+       value => 'html, with links',
+       description => ''},
+     { name  => 'HTML, without links',
+       value => 'html, without links',
+       description => ''},
+     { name  => 'HTML, totals',
+       value => 'html, totals',
+       description => ''},
+     { name  => 'HTML, scores only',
+       value => 'html, scores only',
+       description => ''},
+     { name  => 'Excel, totals',
+       value => 'excel, totals',
+       description => ''},
+     { name  => 'Excel, scores only',
+       value => 'excel, scores only',
+       description => ''},
+     { name  => 'CSV, totals',
+       value => 'csv, totals',
+       description => ''},
+     { name  => 'CSV, scores only',
+       value => 'csv, scores only',
+       description => ''},
+     { name  => 'CSV, everything',
+       value => 'csv, everything',
+       description => ''}
+     );
+
 sub CreateAndParseOutputSelector {
     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')) {
@@ -303,18 +330,20 @@
     } else {
         $show_links = 'no';
     }
-    if ($restriction eq 'totals only') {
+    if ($restriction eq 'totals') {
         $show = 'totals';
+    } elsif ($restriction eq 'scores only') {
+        $show = 'scores';
     } 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>";
+    foreach my $option (@OutputOptions) {
+        $Str .= "\n".'    <option value="'.$option->{'value'}.'"';
+        $Str .= " selected " if ($option->{'value'} eq $selected);
+        $Str .= ">".$option->{'name'}."<\/option>";
     }
     $Str .= "\n</select>";
     return $Str;
@@ -412,6 +441,9 @@
         if ($show eq 'totals') {
             $performance = ' 'x(length($seq_max)-length($score)).$ratio;
             $performance .= ' 'x($seq->{'width'}-length($performance));
+        } elsif ($show eq 'scores') {
+            $performance = $score;
+            $performance .= ' 'x($seq->{'width'}-length($performance));
         } else {
             # Pad with extra spaces
             $performance .= ' 'x($seq->{'width'}-$seq_max-
@@ -475,42 +507,173 @@
 {
 
 my $excel_sheet;
+my $excel_workbook;
+
+my $filename;
+my $rows_output;
+my $cols_output;
+
+my $num_students;
+my $start_time;
 
 sub excel_initialize {
     my ($r) = @_;
     #
-    $r->print("<h1>Not implemented yet</h1>");
-    return;
-    my $filename = '/prtspool/'.
+    $filename = '/prtspool/'.
         $ENV{'user.name'}.'_'.$ENV{'user.domain'}.'_'.
             time.'_'.rand(1000000000).'.xls';
-    $excel_sheet = Spreadsheet::WriteExcel->new('/home/httpd'.$filename);
-    if (! defined($excel_sheet)) {
+    #
+    $excel_workbook = undef;
+    $excel_sheet = undef;
+    #
+    $rows_output = 0;
+    $cols_output = 0;
+    #
+    $num_students = 0;
+    $start_time   = time;
+    #
+    # Create sheet
+    $excel_workbook = Spreadsheet::WriteExcel->new('/home/httpd'.$filename);
+    #
+    # Check for errors
+    if (! defined($excel_workbook)) {
         $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;
+        return ;
     }
     #
     # 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);
+    $excel_workbook->set_tempdir($Apache::lonnet::tmpdir);
+    #
+    # Add a worksheet
+    $excel_sheet = $excel_workbook->addworksheet
+        ($ENV{'course.'.$ENV{'request.course.id'}.'.description'});
+    #
+    # Add the student headers
+    foreach my $field (&get_student_fields_to_show()) {
+        $excel_sheet->write(1,$cols_output++,$field);
+    }
+    #
+    # Add the Sequence Headers
+    foreach my $seq (&get_sequences_to_show) {
+        $excel_sheet->write(0,$cols_output,$seq->{'title'});
+        if ($show eq 'totals') {
+            $excel_sheet->write(1,$cols_output,'score');
+            $excel_sheet->write(1,$cols_output+1,'maximum');
+            $cols_output += 2;
+        } else {
+            $cols_output++;
+        }
+    }
+    #
+    # Bookkeeping
+    if ($show eq 'totals') {
+        $rows_output = 2;
+    } else {
+        $rows_output = 1;
+    }
+    #
+    # Let the user know what we are doing
+    my $studentcount = scalar(@Apache::lonstatistics::Students); 
+    $r->print("<h1>Compiling Excel spreadsheet for ".
+              $studentcount.' student');
+    $r->print('s') if ($studentcount > 1);
+    $r->print("</h1>\n");
+    $r->rflush();
     #
-    # Determine the name to give the worksheet
-#    $excel_sheet->addworksheet();
-
     return;
 }
 
 sub excel_outputstudent {
     my ($r,$student) = @_;
+    return if (! defined($excel_sheet));
+    $cols_output=0;
+    #
+    # Write out student data
+    my @to_show = &get_student_fields_to_show();
+    foreach my $field (@to_show) {
+        $excel_sheet->write($rows_output,$cols_output++,$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;
+    }
+    #
+    # Write out sequence scores and totals data
+    foreach my $seq (&get_sequences_to_show) {
+        my ($performance,$score,$seq_max) =
+            &StudentPerformanceOnSequence($student,\%StudentsData,
+                                          $seq,'no');
+        if ($show eq 'totals' || $show eq 'scores') {
+            $excel_sheet->write($rows_output,$cols_output++,$score);
+        }
+        if ($show eq 'totals') {
+            $excel_sheet->write($rows_output,$cols_output++,$seq_max);
+        }
+    }
+    #
+    # Bookkeeping
+    $rows_output++; 
+    $cols_output=0;
+    #
+    # Time estimate
+    $num_students++;
+    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;
 }
 
 sub excel_finish {
     my ($r) = @_;
+    return if (! defined($excel_sheet));
+    #
+    # Write the excel file
+    $excel_workbook->close();
+    my $c = $r->connection();
+    #
+    return if($c->aborted());
+    #
+    # Tell the user where to get their excel file
+    $r->print('<br /><br />'.
+              '<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();
+    return;
 }
 
 }
@@ -575,8 +738,7 @@
 #######################################################
 #######################################################
 sub StudentPerformanceOnSequence {
-    my ($student,$studentdata,$seq,$links,$totalonly) = @_;
-    $totalonly = 0 if (! defined($totalonly));
+    my ($student,$studentdata,$seq,$links) = @_;
     $links = 'no' if (! defined($links));
     my $Str = '';
     my ($sum,$max) = (0,0);

--matthew1046732045--