Diff for /loncom/interface/statistics/lonstudentassessment.pm between versions 1.55 and 1.78

version 1.55, 2003/06/10 19:19:57 version 1.78, 2003/12/09 17:00:07
Line 52  package Apache::lonstudentassessment; Line 52  package Apache::lonstudentassessment;
 use strict;  use strict;
 use Apache::lonstatistics;  use Apache::lonstatistics;
 use Apache::lonhtmlcommon;  use Apache::lonhtmlcommon;
   use Apache::loncommon();
 use Apache::loncoursedata;  use Apache::loncoursedata;
 use Apache::lonnet; # for logging porpoises  use Apache::lonnet; # for logging porpoises
   use Apache::lonlocal;
 use Spreadsheet::WriteExcel;  use Spreadsheet::WriteExcel;
   use Spreadsheet::WriteExcel::Utility();
   
 #######################################################  #######################################################
 #######################################################  #######################################################
Line 138  Inputs: Line 141  Inputs:
 #######################################################  #######################################################
 sub BuildStudentAssessmentPage {  sub BuildStudentAssessmentPage {
     my ($r,$c)=@_;      my ($r,$c)=@_;
       #
     undef($Statistics);      undef($Statistics);
       undef($show_links);
       undef($output_mode);
       undef($data);
       undef($base);
       undef($datadescription);
       undef($single_student_mode);
       #
       my %Saveable_Parameters = ('Status' => 'scalar',
                                  'chartoutputmode' => 'scalar',
                                  'chartoutputdata' => 'scalar',
                                  'Section' => 'array',
                                  'StudentData' => 'array',
                                  'Maps' => 'array');
       &Apache::loncommon::store_course_settings('chart',\%Saveable_Parameters);
       &Apache::loncommon::restore_course_settings('chart',\%Saveable_Parameters);
       #
       &Apache::lonstatistics::PrepareClasslist();
       #
       $single_student_mode = 0;
     $single_student_mode = 1 if ($ENV{'form.SelectedStudent'});      $single_student_mode = 1 if ($ENV{'form.SelectedStudent'});
       if ($ENV{'form.selectstudent'}) {
           &Apache::lonstatistics::DisplayClasslist($r);
           return;
       }
     #      #
     # 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
Line 149  sub BuildStudentAssessmentPage { Line 176  sub BuildStudentAssessmentPage {
     $r->print('<input type="hidden" name="sort" value="'.      $r->print('<input type="hidden" name="sort" value="'.
               $ENV{'form.sort'}.'" />');                $ENV{'form.sort'}.'" />');
     $r->rflush();      $r->rflush();
       #
     if (! exists($ENV{'form.notfirstrun'}) && ! $single_student_mode) {      if (! exists($ENV{'form.notfirstrun'}) && ! $single_student_mode) {
         return;          return;
     }      }
Line 179  sub BuildStudentAssessmentPage { Line 207  sub BuildStudentAssessmentPage {
         @Students = @Apache::lonstatistics::Students;          @Students = @Apache::lonstatistics::Students;
     }      }
     #      #
       # Perform generic initialization tasks
       #       Since we use lonnet::EXT to retrieve problem weights,
       #       to ensure current data we must clear the caches out.
       #       This makes sure that parameter changes at the student level
       #       are immediately reflected in the chart.
       &Apache::lonnet::clear_EXT_cache_status();
       #
       # Clean out loncoursedata's package data, just to be safe.
       &Apache::loncoursedata::clear_internal_caches();
       #
     # Call the initialize routine selected above      # Call the initialize routine selected above
     $initialize->($r);      $initialize->($r);
     foreach my $student (@Students) {      foreach my $student (@Students) {
Line 281  sub CreateInterface { Line 319  sub CreateInterface {
 #    $Str .= &CreateLegend();  #    $Str .= &CreateLegend();
     $Str .= '<table cellspacing="5">'."\n";      $Str .= '<table cellspacing="5">'."\n";
     $Str .= '<tr>';      $Str .= '<tr>';
     $Str .= '<td align="center"><b>Sections</b></td>';      $Str .= '<td align="center"><b>'.&mt('Sections').'</b></td>';
     $Str .= '<td align="center"><b>Student Data</b></td>';      $Str .= '<td align="center"><b>'.&mt('Student Data</b>').'</td>';
     $Str .= '<td align="center"><b>Enrollment Status</b></td>';      $Str .= '<td align="center"><b>'.&mt('Enrollment Status').'</b></td>';
     $Str .= '<td align="center"><b>Sequences and Folders</b></td>';      $Str .= '<td align="center"><b>'.&mt('Sequences and Folders').'</b></td>';
     $Str .= '<td align="center"><b>Output Format</b></td>';      $Str .= '<td align="center"><b>'.&mt('Output Format').'</b>'.
     $Str .= '<td align="center"><b>Output Data</b></td>';          &Apache::loncommon::help_open_topic("Chart_Output_Formats").
           '</td>';
       $Str .= '<td align="center"><b>'.&mt('Output Data').'</b>'.
           &Apache::loncommon::help_open_topic("Chart_Output_Data").
           '</td>';
     $Str .= '</tr>'."\n";      $Str .= '</tr>'."\n";
     #      #
     $Str .= '<tr><td align="center">'."\n";      $Str .= '<tr><td align="center">'."\n";
Line 313  sub CreateInterface { Line 355  sub CreateInterface {
     $Str .= &CreateAndParseOutputDataSelector();      $Str .= &CreateAndParseOutputDataSelector();
     $Str .= '</td></tr>'."\n";      $Str .= '</td></tr>'."\n";
     $Str .= '</table>'."\n";      $Str .= '</table>'."\n";
     $Str .= '<input type="submit" value="Generate Chart" />';      $Str .= '<input type="submit" name="Generate Chart" value="'.
     $Str .= '&nbsp;'x8;          &mt('Generate Chart').'" />';
       $Str .= '&nbsp;'x5;
       $Str .= '<input type="submit" name="selectstudent" value="'.
           &mt('Select One Student').'" />';
       $Str .= '&nbsp;'x5;
       $Str .= '<input type="submit" name="ClearCache" value="'.
           &mt('Clear Caches').'" />';
       $Str .= '&nbsp;'x5;
       $Str .= '<br />';
     return $Str;      return $Str;
 }  }
   
Line 359  my @OutputOptions = Line 409  my @OutputOptions =
        mode => 'excel',         mode => 'excel',
        show_links => 'no',         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_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_links => 'no',  
 #           },  
      { name  => 'CSV',       { name  => 'CSV',
        value => 'csv',         value => 'csv',
        description => 'Output a comma seperated values file suitable for '.         description => 'Output a comma seperated values file suitable for '.
            'import into a spreadsheet.',             'import into a spreadsheet program.  Using this method as opposed '.
              'to Excel output allows you to organize your data before importing'.
              ' it into a spreadsheet program.',
        mode => 'csv',         mode => 'csv',
        show_links => 'no',         show_links => 'no',
            },             },
Line 389  my @OutputOptions = Line 422  my @OutputOptions =
   
 sub OutputDescriptions {  sub OutputDescriptions {
     my $Str = '';      my $Str = '';
     $Str .= "<h2>Output Modes</h2>\n";      $Str .= "<h2>Output Formats</h2>\n";
     $Str .= "<dl>\n";      $Str .= "<dl>\n";
     foreach my $outputmode (@OutputOptions) {      foreach my $outputmode (@OutputOptions) {
  $Str .="    <dt>".$outputmode->{'name'}."</dt>\n";   $Str .="    <dt>".$outputmode->{'name'}."</dt>\n";
Line 402  sub OutputDescriptions { Line 435  sub OutputDescriptions {
 sub CreateAndParseOutputSelector {  sub CreateAndParseOutputSelector {
     my $Str = '';      my $Str = '';
     my $elementname = 'chartoutputmode';      my $elementname = 'chartoutputmode';
       &Apache::loncommon::get_unprocessed_cgi($ENV{'QUERY_STRING'},
                                               [$elementname]);
     #      #
     # Format for output options is 'mode, restrictions';      # Format for output options is 'mode, restrictions';
     my $selected = 'html, without links';      my $selected = 'html, without links';
Line 428  sub CreateAndParseOutputSelector { Line 463  sub CreateAndParseOutputSelector {
     foreach my $option (@OutputOptions) {      foreach my $option (@OutputOptions) {
         $Str .= "\n".'    <option value="'.$option->{'value'}.'"';          $Str .= "\n".'    <option value="'.$option->{'value'}.'"';
         $Str .= " selected " if ($option->{'value'} eq $selected);          $Str .= " selected " if ($option->{'value'} eq $selected);
         $Str .= ">".$option->{'name'}."<\/option>";          $Str .= ">".&mt($option->{'name'})."<\/option>";
     }      }
     $Str .= "\n</select>";      $Str .= "\n</select>";
     return $Str;      return $Str;
Line 438  sub CreateAndParseOutputSelector { Line 473  sub CreateAndParseOutputSelector {
 ## Data selector stuff  ## Data selector stuff
 ##  ##
 my @OutputDataOptions =  my @OutputDataOptions =
     ( { name  =>'Tries',      (
         base  =>'tries',       { name  => 'Scores Summary',
         value => 'tries',         base  => 'scores',
         shortdesc => 'Number of Tries before success on each Problem Part',         value => 'sum and total',
         longdesc =>'The number of tries before success on each problem part.',         shortdesc => 'Total Score and Maximum Possible for each '.
         },             'Sequence or Folder',
       { name  =>'Parts Correct',         longdesc => 'The score of each student as well as the '.
         base  =>'tries',             ' maximum possible on each Sequence or Folder.',
         value => 'parts correct',         },
         shortdesc => 'Number of Problem Parts completed successfully.',       { name  => 'Scores Per Problem',
         longdesc => 'The Number of Problem Parts completed successfully.',         base  => 'scores',
         },         value => 'scores',
       { name  =>'Parts Correct & Maximums',         shortdesc => 'Score on each Problem Part',
         base  =>'tries',         longdesc =>'The students score on each problem part, computed as'.
         value => 'parts correct total',             'the part weight * part awarded',
         shortdesc => 'Number of Problem Parts completed successfully.',         },
         longdesc => 'The Number of Problem Parts completed successfully and '.  #     { name  => 'Scores Sum',
             'the maximum possible for each student',  #       base  => 'scores',
         },  #       value => 'sum only',
       { name  => 'Scores',  #       shortdesc => 'Sum of Scores on each Problem Part',
         base  => 'scores',  #       longdesc =>'The total of the scores of the student on each problem'.
         value => 'scores',  #           ' part in the sequences or folders selected.',
         shortdesc => 'Score on each Problem Part',  #       },
         longdesc =>'The students score on each problem part, computed as'.  #     { name  => 'Scores Summary Table Only',
             'the part weight * part awarded',  #       base  => 'scores',
         },  #       value => 'final table scores',
       { name  => 'Scores Sum',  #       shortdesc => 'Summary of Scores',
         base  => 'scores',  #       longdesc  => 'The average score on each sequence or folder for the '.
         value => 'sum only',  #           'selected students.',
         shortdesc => 'Sum of Scores on each Problem Part',  #       },
         longdesc =>'The total of the scores of the student on each problem'.       { name  =>'Tries',
             ' part in the sequences or folders selected.',         base  =>'tries',
         },         value => 'tries',
       { name  => 'Scores Sum & Maximums',         shortdesc => 'Number of Tries before success on each Problem Part',
         base  => 'scores',         longdesc =>'The number of tries before success on each problem part.',
         value => 'sum and total',         },
         shortdesc => 'Total Score and Maximum Possible for each '.       { name  =>'Parts Correct',
             'Sequence or Folder',         base  =>'tries',
         longdesc => 'The total of the scores of the student on each problem'.         value => 'parts correct total',
             ' and the maximum possible for that student on each Sequence or '.         shortdesc => 'Number of Problem Parts completed successfully.',
             ' Folder.',         longdesc => 'The Number of Problem Parts completed successfully and '.
         },             'the maximum possible for each student',
       { name  => 'Summary Table (Scores)',         },
         base  => 'scores',  #     { name  =>'Parts Correct',
         value => 'final table scores',  #       base  =>'tries',
         shortdesc => 'Summary of Scores',  #       value => 'parts correct',
         longdesc  => '',  #       shortdesc => 'Number of Problem Parts completed successfully.',
         },  #       longdesc => 'The Number of Problem Parts completed successfully'.
       { name  => 'Summary Table (Parts)',  #           ' on each sequence or folder.',
         base  => 'tries',  #       },
         value => 'final table parts',  #     { name  => 'Parts Summary Table Only',
         shortdesc => 'Summary of Parts Correct',  #       base  => 'tries',
         longdesc  => '',  #       value => 'final table parts',
         }  #       shortdesc => 'Summary of Parts Correct',
       );  #       longdesc  => 'A summary table of the average number of problem parts '.
   #           'students were able to get correct on each sequence.',
   #       },
        );
   
   sub HTMLifyOutputDataDescriptions {
       my $Str = '';
       $Str .= "<h2>Output Data</h2>\n";
       $Str .= "<dl>\n";
       foreach my $option (@OutputDataOptions) {
           $Str .= '    <dt>'.$option->{'name'}.'</dt>';
           $Str .= '<dd>'.$option->{'longdesc'}.'</dd>'."\n";
       }
       $Str .= "</dl>\n";
       return $Str;
   }
   
 sub CreateAndParseOutputDataSelector {  sub CreateAndParseOutputDataSelector {
     my $Str = '';      my $Str = '';
Line 521  sub CreateAndParseOutputDataSelector { Line 571  sub CreateAndParseOutputDataSelector {
     foreach my $option (@OutputDataOptions) {      foreach my $option (@OutputDataOptions) {
         $Str .= "\n".'    <option value="'.$option->{'value'}.'"';          $Str .= "\n".'    <option value="'.$option->{'value'}.'"';
         $Str .= " selected " if ($option->{'value'} eq $data);          $Str .= " selected " if ($option->{'value'} eq $data);
         $Str .= ">".$option->{'name'}."<\/option>";          $Str .= ">".&mt($option->{'name'})."<\/option>";
     }      }
     $Str .= "\n</select>";      $Str .= "\n</select>";
     return $Str;      return $Str;
Line 562  sub html_initialize { Line 612  sub html_initialize {
     $padding = ' 'x3;      $padding = ' 'x3;
     $count = 0;      $count = 0;
     $nodata_count = 0;      $nodata_count = 0;
       undef(%prog_state);
     #      #
     $r->print("<h3>".$ENV{'course.'.$ENV{'request.course.id'}.'.description'}.      $r->print("<h3>".$ENV{'course.'.$ENV{'request.course.id'}.'.description'}.
               "&nbsp;&nbsp;".localtime(time)."</h3>");                "&nbsp;&nbsp;".localtime(time)."</h3>");
Line 786  sub SingleStudentTotal { Line 837  sub SingleStudentTotal {
   
 =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 ($data eq ) {  
 #        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 882  my $cols_output; Line 861  my $cols_output;
 my %prog_state; # progress window state  my %prog_state; # progress window state
 my $request_aborted;  my $request_aborted;
   
   my $total_formula;
   
 sub excel_initialize {  sub excel_initialize {
     my ($r) = @_;      my ($r) = @_;
     #      #
     $request_aborted = undef;      undef ($excel_sheet);
       undef ($excel_workbook);
       undef ($filename);
       undef ($rows_output);
       undef ($cols_output);
       undef (%prog_state);
       undef ($request_aborted);
       undef ($total_formula);
       #
     my $total_columns = scalar(&get_student_fields_to_show());      my $total_columns = scalar(&get_student_fields_to_show());
     foreach my $seq (&Apache::lonstatistics::Sequences_with_Assess()) {      foreach my $seq (&Apache::lonstatistics::Sequences_with_Assess()) {
         # Add 2 because we need a 'sum' and 'total' column for each          # Add 2 because we need a 'sum' and 'total' column for each
Line 966  END Line 955  END
     #      #
     # Add a worksheet      # Add a worksheet
     my $sheetname = $ENV{'course.'.$ENV{'request.course.id'}.'.description'};      my $sheetname = $ENV{'course.'.$ENV{'request.course.id'}.'.description'};
     if (length($sheetname) > 31) {      $sheetname = &Apache::loncommon::clean_excel_name($sheetname);
         $sheetname = substr($sheetname,0,31);  
     }  
     $excel_sheet = $excel_workbook->addworksheet($sheetname);      $excel_sheet = $excel_workbook->addworksheet($sheetname);
     #      #
     # Put the course description in the header      # Put the course description in the header
Line 1018  END Line 1005  END
     }      }
     #      #
     # Add the remaining column headers      # Add the remaining column headers
       my $total_formula_string = '=0';
     foreach my $seq (&Apache::lonstatistics::Sequences_with_Assess()) {      foreach my $seq (&Apache::lonstatistics::Sequences_with_Assess()) {
         $excel_sheet->write($rows_output+$row_offset,          $excel_sheet->write($rows_output+$row_offset,
                             $cols_output,$seq->{'title'});                              $cols_output,$seq->{'title'});
         if ($data eq 'tries' || $data eq 'scores') {          if ($data eq 'tries' || $data eq 'scores') {
               # Determine starting cell
               $seq->{'Excel:startcell'}=
                   &Spreadsheet::WriteExcel::Utility::xl_rowcol_to_cell
                   ($rows_output,$cols_output);
               $seq->{'Excel:startcol'}=$cols_output;
               # Put the names of the problems and parts into the sheet
             foreach my $res (@{$seq->{'contents'}}) {              foreach my $res (@{$seq->{'contents'}}) {
                 next if ($res->{'type'} ne 'assessment');                  next if ($res->{'type'} ne 'assessment');
                 if (scalar(@{$res->{'parts'}}) > 1) {                  if (scalar(@{$res->{'parts'}}) > 1) {
Line 1036  END Line 1030  END
                                         $res->{'title'});                                          $res->{'title'});
                 }                  }
             }              }
               # Determine ending cell
               $seq->{'Excel:endcell'} = 
                   &Spreadsheet::WriteExcel::Utility::xl_rowcol_to_cell
                                                ($rows_output,$cols_output-1);
               $seq->{'Excel:endcol'}=$cols_output-1;
               # Determine cell the score is held in
               $seq->{'Excel:scorecell'} = 
                   &Spreadsheet::WriteExcel::Utility::xl_rowcol_to_cell
                                                ($rows_output,$cols_output);
               $seq->{'Excel:scorecol'}=$cols_output;
             $excel_sheet->write($rows_output,$cols_output++,'score');              $excel_sheet->write($rows_output,$cols_output++,'score');
               # Create the formula for summing up this sequence
               $seq->{'Excel:sum'}= $excel_sheet->store_formula
                                           ('=SUM('.$seq->{'Excel:startcell'}.
                                                ':'.$seq->{'Excel:endcell'}.')');
               #
               $total_formula_string.='+'.
                   &Spreadsheet::WriteExcel::Utility::xl_rowcol_to_cell
                                           ($rows_output,$cols_output-1);
             $excel_sheet->write($rows_output,$cols_output++,'maximum');              $excel_sheet->write($rows_output,$cols_output++,'maximum');
         } elsif ($data eq 'sum and total' || $data eq 'parts correct total') {          } elsif ($data eq 'sum and total') {
             $excel_sheet->write($rows_output+1,$cols_output,'score');              $excel_sheet->write($rows_output+1,$cols_output,'score');
               $total_formula_string.='+'.
                   &Spreadsheet::WriteExcel::Utility::xl_rowcol_to_cell
                                           ($rows_output+1,$cols_output);
               $excel_sheet->write($rows_output+1,$cols_output+1,'maximum');
               $cols_output += 2;
           } elsif ($data eq 'parts correct total') {
               $excel_sheet->write($rows_output+1,$cols_output,'parts correct');
               $total_formula_string.='+'.
                   &Spreadsheet::WriteExcel::Utility::xl_rowcol_to_cell
                                           ($rows_output+1,$cols_output);
             $excel_sheet->write($rows_output+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++;
         }          }
     }      }
       $excel_sheet->write($rows_output,$cols_output,'Grand Total');
       $total_formula = $excel_sheet->store_formula($total_formula_string);
     #      #
     # Bookkeeping      # Bookkeeping
     if ($data eq 'sum and total' || $data eq 'parts correct total') {      if ($data eq 'sum and total' || $data eq 'parts correct total') {
Line 1066  END Line 1090  END
     }      }
     #      #
     # Add the maximums for each sequence or assessment      # Add the maximums for each sequence or assessment
       my %total_cell_translation;
     foreach my $seq (&Apache::lonstatistics::Sequences_with_Assess()) {      foreach my $seq (&Apache::lonstatistics::Sequences_with_Assess()) {
           $total_cell_translation{$seq->{'Excel:scorecell'}} = 
               &Spreadsheet::WriteExcel::Utility::xl_rowcol_to_cell
                           ($rows_output,$seq->{'Excel:scorecol'});
         my $weight;          my $weight;
         my $max = 0;          my $max = 0;
         foreach my $resource (@{$seq->{'contents'}}) {          foreach my $resource (@{$seq->{'contents'}}) {
Line 1092  END Line 1120  END
         if (! ($data eq 'sum only' || $data eq 'parts correct')) {          if (! ($data eq 'sum only' || $data eq 'parts correct')) {
             $excel_sheet->write($rows_output,$cols_output++,'');              $excel_sheet->write($rows_output,$cols_output++,'');
         }          }
         $excel_sheet->write($rows_output,$cols_output++,$max);          my %replaceCells;
     }          $replaceCells{$seq->{'Excel:startcell'}} = 
               &Spreadsheet::WriteExcel::Utility::xl_rowcol_to_cell
                                      ($rows_output,$seq->{'Excel:startcol'});
           $replaceCells{$seq->{'Excel:endcell'}} = 
               &Spreadsheet::WriteExcel::Utility::xl_rowcol_to_cell
                                      ($rows_output,$seq->{'Excel:endcol'});
           $excel_sheet->repeat_formula($rows_output,$cols_output++,
                                        $seq->{'Excel:sum'},undef,
                                        %replaceCells);
       }
       $excel_sheet->repeat_formula($rows_output,$cols_output++,
                                    $total_formula,undef,
                                    %total_cell_translation);
     $rows_output++;      $rows_output++;
     #      #
     # Let the user know what we are doing      # Let the user know what we are doing
Line 1109  END Line 1149  END
         ($r,'Excel File Compilation Status',          ($r,'Excel File Compilation Status',
          'Excel File Compilation Progress', $studentcount);           'Excel File Compilation Progress', $studentcount);
     #      #
       &Apache::lonhtmlcommon::Update_PrgWin($r,\%prog_state,
                                             'Processing first student');
     return;      return;
 }  }
   
Line 1135  sub excel_outputstudent { Line 1177  sub excel_outputstudent {
     }      }
     #      #
     # Write out sequence scores and totals data      # Write out sequence scores and totals data
       my %total_cell_translation;
     foreach my $seq (&Apache::lonstatistics::Sequences_with_Assess()) {      foreach my $seq (&Apache::lonstatistics::Sequences_with_Assess()) {
           # Keep track of cells to translate in total cell
           $total_cell_translation{$seq->{'Excel:scorecell'}} = 
               &Spreadsheet::WriteExcel::Utility::xl_rowcol_to_cell
                           ($rows_output,$seq->{'Excel:scorecol'});
           #
         my ($performance,$performance_length,$score,$seq_max,$rawdata);          my ($performance,$performance_length,$score,$seq_max,$rawdata);
         if ($base eq 'tries') {          if ($base eq 'tries') {
             ($performance,$performance_length,$score,$seq_max,$rawdata) =              ($performance,$performance_length,$score,$seq_max,$rawdata) =
Line 1150  sub excel_outputstudent { Line 1198  sub excel_outputstudent {
             foreach my $value (@$rawdata) {              foreach my $value (@$rawdata) {
                 $excel_sheet->write($rows_output,$cols_output++,$value);                  $excel_sheet->write($rows_output,$cols_output++,$value);
             }              }
             $excel_sheet->write($rows_output,$cols_output++,$score);              # Write a formula for the sum of this sequence
               my %replaceCells;
               $replaceCells{$seq->{'Excel:startcell'}} = 
                   &Spreadsheet::WriteExcel::Utility::xl_rowcol_to_cell
                               ($rows_output,$seq->{'Excel:startcol'});
               $replaceCells{$seq->{'Excel:endcell'}} = 
                   &Spreadsheet::WriteExcel::Utility::xl_rowcol_to_cell
                               ($rows_output,$seq->{'Excel:endcol'});
               # The undef is for the format
               $excel_sheet->repeat_formula($rows_output,$cols_output++,
                                            $seq->{'Excel:sum'},undef,
                                            %replaceCells);
               #
             $excel_sheet->write($rows_output,$cols_output++,$seq_max);              $excel_sheet->write($rows_output,$cols_output++,$seq_max);
         } elsif ($data eq 'sum and total' || $data eq 'sum only' ||           } elsif ($data eq 'sum and total' || $data eq 'sum only' || 
             $data eq 'parts correct' || $data eq 'parts correct total') {              $data eq 'parts correct' || $data eq 'parts correct total') {
Line 1161  sub excel_outputstudent { Line 1221  sub excel_outputstudent {
         }          }
     }      }
     #      #
       $excel_sheet->repeat_formula($rows_output,$cols_output++,
                                    $total_formula,undef,
                                    %total_cell_translation);
   
       #
     # Bookkeeping      # Bookkeeping
     $rows_output++;       $rows_output++; 
     $cols_output=0;      $cols_output=0;
Line 1220  sub csv_initialize{ Line 1285  sub csv_initialize{
     my ($r) = @_;      my ($r) = @_;
     #       # 
     # Clean up      # Clean up
     $filename = undef;      undef($outputfile);
     $outputfile = undef;      undef($filename);
       undef($request_aborted);
     undef(%prog_state);      undef(%prog_state);
     #      #
     # Deal with unimplemented requests      # Deal with unimplemented requests
Line 1425  sub StudentTriesOnSequence { Line 1491  sub StudentTriesOnSequence {
             $performance_length++;              $performance_length++;
             my $symbol = ' '; # default to space              my $symbol = ' '; # default to space
             #              #
               my $awarded = 0;
               if (exists($resource_data->{'resource.'.$partnum.'.awarded'})) {
                   $awarded = $resource_data->{'resource.'.$partnum.'.awarded'};
                   $awarded = 0 if (! $awarded);
               }
               #
               my $status = '';
             if (exists($resource_data->{'resource.'.$partnum.'.solved'})) {              if (exists($resource_data->{'resource.'.$partnum.'.solved'})) {
                 my $status = $resource_data->{'resource.'.$partnum.'.solved'};                  $status = $resource_data->{'resource.'.$partnum.'.solved'};
                 if ($status eq 'correct_by_override') {              }
                     $symbol = '+';              #
                     $sum++;              my $tries = 0;
                 } elsif ($status eq 'incorrect_by_override') {              if(exists($resource_data->{'resource.'.$partnum.'.tries'})) {
                     $symbol = '-';                  $tries = $resource_data->{'resource.'.$partnum.'.tries'};
                 } elsif ($status eq 'ungraded_attempted') {              }
                     $symbol = '#';              #
                 } elsif ($status eq 'incorrect_attempted')  {              if ($awarded > 0) {
                     $symbol = '.';                  # The student has gotten the problem correct to some degree
                 } elsif ($status eq 'excused') {                  if ($status eq 'excused') {
                     $symbol = 'x';                      $symbol = 'x';
                     $max--;                      $max--;
                 } elsif ($status eq 'correct_by_student' &&                  } elsif ($status eq 'correct_by_override') {
                     exists($resource_data->{'resource.'.$partnum.'.tries'})){                      $symbol = '+';
                     $tries = $resource_data->{'resource.'.$partnum.'.tries'};                      $sum++;
                   } elsif ($tries > 0) {
                     if ($tries > 9) {                      if ($tries > 9) {
                         $symbol = '*';                          $symbol = '*';
                     } elsif ($tries > 0) {  
                         $symbol = $tries;  
                     } else {                      } else {
                         $symbol = ' ';                          $symbol = $tries;
                     }                      }
                     $sum++;                      $sum++;
                 } elsif (exists($resource_data->{'resource.'.  
                                                      $partnum.'.tries'})){  
                     $symbol = '.';  
                 } else {                  } else {
                     $symbol = ' ';                      $symbol = '+';
                       $sum++;
                 }                  }
             } else {              } else {
                 # Unsolved.  Did they try?                  # The student has the problem incorrect or it is ungraded
                 if (exists($resource_data->{'resource.'.$partnum.'.tries'})){                  if ($status eq 'excused') {
                       $symbol = 'x';
                       $max--;
                   } elsif ($status eq 'incorrect_by_override') {
                       $symbol = '-';
                   } elsif ($status eq 'ungraded_attempted') {
                       $symbol = '#';
                   } elsif ($status eq 'incorrect_attempted' ||
                            $tries > 0)  {
                     $symbol = '.';                      $symbol = '.';
                 } else {                  } else {
                     $symbol = ' ';                      # Problem is wrong and has not been attempted.
                       $symbol=' ';
                 }                  }
             }              }
             #              #
Line 1478  sub StudentTriesOnSequence { Line 1557  sub StudentTriesOnSequence {
                 $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'}.
                             '&domain='.$student->{'domain'}.                              '&userdom='.$student->{'domain'}.
                                 '&command=submission">'.$symbol.'</a>';                                  '&command=submission">'.$symbol.'</a>';
             }              }
             $value .= $symbol;              $value .= $symbol;
Line 1546  sub StudentPerformanceOnSequence { Line 1625  sub StudentPerformanceOnSequence {
             my $awarded = 0;              my $awarded = 0;
             if (exists($resource_data->{'resource.'.$part.'.awarded'})) {              if (exists($resource_data->{'resource.'.$part.'.awarded'})) {
                 $awarded = $resource_data->{'resource.'.$part.'.awarded'};                  $awarded = $resource_data->{'resource.'.$part.'.awarded'};
                   $awarded = 0 if (! $awarded);
             }              }
             #              #
             $partscore = $weight*$awarded;              $partscore = $weight*$awarded;
             $score += $partscore;              $score += $partscore;
             $symbol = $weight;               $symbol = $partscore; 
               if (abs($symbol - sprintf("%.0f",$symbol)) < 0.001) {
                   $symbol = sprintf("%.0f",$symbol);
               }
             if (length($symbol) > 1) {              if (length($symbol) > 1) {
                 $symbol = '*';                  $symbol = '*';
             }              }
Line 1569  sub StudentPerformanceOnSequence { Line 1652  sub StudentPerformanceOnSequence {
                 }                  }
             }              }
             #              #
               if (! defined($partscore)) {
                   $partscore = $symbol;
               }
               push (@ScoreData,$partscore);
               #
             if ( ($links eq 'yes' && $symbol ne ' ') || ($links eq 'all')) {              if ( ($links eq 'yes' && $symbol ne ' ') || ($links eq 'all')) {
                 $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'}.
                     '&domain='.$student->{'domain'}.                      '&userdom='.$student->{'domain'}.
                     '&command=submission">'.$symbol.'</a>';                      '&command=submission">'.$symbol.'</a>';
             }              }
             if (! defined($partscore)) {              $Str .= $symbol;
                 $partscore = $symbol;  
             }  
             push (@ScoreData,$partscore);  
         }          }
         $Str .= $symbol;  
     }      }
     return ($Str,$performance_length,$score,$max,\@ScoreData);      return ($Str,$performance_length,$score,$max,\@ScoreData);
 }  }

Removed from v.1.55  
changed lines
  Added in v.1.78


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