Diff for /loncom/interface/spreadsheet/studentcalc.pm between versions 1.27 and 1.39

version 1.27, 2004/12/08 00:56:00 version 1.39, 2006/05/01 06:17:16
Line 63  use Apache::lonlocal; Line 63  use Apache::lonlocal;
 @Apache::studentcalc::ISA = ('Apache::Spreadsheet');  @Apache::studentcalc::ISA = ('Apache::Spreadsheet');
   
 my @Sequences = ();  my @Sequences = ();
   my $navmap;
 my %Exportrows = ();  my %Exportrows = ();
   
 my $current_course;  my $current_course;
   
 sub initialize {  sub initialize {
     &Apache::assesscalc::initialize();  
     &initialize_sequence_cache();      &initialize_sequence_cache();
       &Apache::assesscalc::initialize($navmap);
 }  }
   
 sub initialize_package {  sub initialize_package {
     $current_course = $ENV{'request.course.id'};      $current_course = $env{'request.course.id'};
     &initialize_sequence_cache();      &initialize_sequence_cache();
     &load_cached_export_rows();      &load_cached_export_rows();
 }  }
   
 sub ensure_correct_sequence_data {  sub ensure_correct_sequence_data {
     if ($current_course ne $ENV{'request.course.id'}) {      if ($current_course ne $env{'request.course.id'}) {
         &initialize_sequence_cache();          &initialize_sequence_cache();
         $current_course = $ENV{'request.course.id'};          $current_course = $env{'request.course.id'};
     }      }
     return;      return;
 }  }
Line 90  sub initialize_sequence_cache { Line 91  sub initialize_sequence_cache {
     #      #
     # Set up the sequences and assessments      # Set up the sequences and assessments
     undef(@Sequences);      undef(@Sequences);
     my ($top,$sequences,$assessments) =       undef($navmap);
         &Apache::loncoursedata::get_sequence_assessment_data();      $navmap = Apache::lonnavmaps::navmap->new();
     if (! defined($top) || ! ref($top)) {      if (!defined($navmap)) {
         # There has been an error, better report it          &Apache::lonnet::logthis('student spreadsheet:Can not open Coursemap');
         &Apache::lonnet::logthis('top is undefined (studentcalc.pm)');      }
         return;      my @all_sequences = $navmap->retrieveResources(undef,
                                                  sub { shift->is_map(); },1,0,1);
       for my $sequence ($navmap->getById('0.0'), @all_sequences) {
    if ($navmap->hasResource($sequence,sub { shift->is_problem(); }, 0)){
               push(@Sequences,$sequence);
       &get_resources($sequence);
           }
     }      }
     @Sequences = @{$sequences} if (ref($sequences) eq 'ARRAY');  }
   
   my %res_memoize;
   sub get_resources {
       my ($seq) = @_;
       if (exists($res_memoize{$seq->symb()})) {
    return @{$res_memoize{$seq->symb()}};
       }
       return () if (! defined($navmap) || ! ref($navmap));
       my @resources = $navmap->retrieveResources($seq,
                                                  sub { shift->is_problem(); },
                                                  0,0,0);
       $res_memoize{$seq->symb()}=\@resources;
       return @resources;
 }  }
   
 sub clear_package {  sub clear_package {
     undef(@Sequences);      undef(@Sequences);
     undef(%Exportrows);      undef(%Exportrows);
       undef(%res_memoize);
       undef($navmap);
     &Apache::assesscalc::clear_package();      &Apache::assesscalc::clear_package();
 }  }
   
Line 123  sub get_html_title { Line 145  sub get_html_title {
     my $self = shift;      my $self = shift;
     my ($name,$desc,$time) = $self->get_title();      my ($name,$desc,$time) = $self->get_title();
     my $title = '<h1>'.$name;      my $title = '<h1>'.$name;
     if ($ENV{'user.name'} ne $self->{'name'} &&       if ($env{'user.name'} ne $self->{'name'} && 
         $ENV{'user.domain'} ne $self->{'domain'}) {          $env{'user.domain'} ne $self->{'domain'}) {
         $title .= ' '.&Apache::loncommon::aboutmewrapper          $title .= ' '.&Apache::loncommon::aboutmewrapper
                                     ($self->{'name'}.'@'.$self->{'domain'},                                      ($self->{'name'}.'@'.$self->{'domain'},
                                      $self->{'name'},$self->{'domain'});                                       $self->{'name'},$self->{'domain'});
Line 143  sub parent_link { Line 165  sub parent_link {
 sub convenience_links {  sub convenience_links {
     my $self = shift;      my $self = shift;
     my ($resource) = @_;      my ($resource) = @_;
     my $result=&Apache::loncommon::submlink('<img src="/adm/lonMisc/subm_button.gif" border="0" />',$self->{'name'},$self->{'domain'},$resource->{'symb'},'LONcatInfo');      my $result=&Apache::loncommon::submlink('<img src="/adm/lonMisc/subm_button.gif" border="0" />',$self->{'name'},$self->{'domain'},$resource->symb,'LONcatInfo');
     $result .= &Apache::loncommon::pgrdlink('<img src="/adm/lonMisc/pgrd_button.gif" border="0" />',$self->{'name'},$self->{'domain'},$resource->{'symb'},'LONcatInfo');      $result .= &Apache::loncommon::pgrdlink('<img src="/adm/lonMisc/pgrd_button.gif" border="0" />',$self->{'name'},$self->{'domain'},$resource->symb,'LONcatInfo');
     $result .= &Apache::loncommon::pprmlink('<img src="/adm/lonMisc/pprm_button.gif" border="0" />',$self->{'name'},$self->{'domain'},$resource->{'symb'},'LONcatInfo');      $result .= &Apache::loncommon::pprmlink('<img src="/adm/lonMisc/pprm_button.gif" border="0" />',$self->{'name'},$self->{'domain'},$resource->symb,'LONcatInfo');
     return $result;      return $result;
 }  }
   
Line 159  sub outsheet_html { Line 181  sub outsheet_html {
     ####################################      ####################################
     my @AssessFileNames = $self->othersheets('assesscalc');      my @AssessFileNames = $self->othersheets('assesscalc');
     my $editing_is_allowed = &Apache::lonnet::allowed('mgr',      my $editing_is_allowed = &Apache::lonnet::allowed('mgr',
                                                 $ENV{'request.course.id'});                                                  $env{'request.course.id'});
     ####################################      ####################################
     # Report any calculation errors    #      # Report any calculation errors    #
     ####################################      ####################################
Line 207  END Line 229  END
         $r->print($tableheader);          $r->print($tableheader);
         #          #
         # Print out template row          # Print out template row
         if (exists($ENV{'request.role.adv'}) && $ENV{'request.role.adv'}) {          if (exists($env{'request.role.adv'}) && $env{'request.role.adv'}) {
             $r->print('<tr><td>Template</td><td>&nbsp;</td>'.              $r->print('<tr><td>Template</td><td>&nbsp;</td>'.
                       $self->html_template_row($num_uneditable,                        $self->html_template_row($num_uneditable,
                                                $importcolor)."</tr>\n");                                                 $importcolor)."</tr>\n");
Line 220  END Line 242  END
     $r->print("</table>\n");      $r->print("</table>\n");
     #      #
     # Prepare to output rows      # Prepare to output rows
     if (exists($ENV{'request.role.adv'}) && $ENV{'request.role.adv'}) {      if (exists($env{'request.role.adv'}) && $env{'request.role.adv'}) {
         $tableheader =<<"END";          $tableheader =<<"END";
 </p><p>  </p><p>
 <table border="2">  <table border="2">
Line 248  END Line 270  END
         &initialize_sequence_cache();          &initialize_sequence_cache();
     }      }
     foreach my $Sequence (@Sequences) {      foreach my $Sequence (@Sequences) {
  next if ($Sequence->{'num_assess'} < 1);   $r->print("<h3>".$Sequence->compTitle."</h3>\n");
  $r->print("<h3>".$Sequence->{'title'}."</h3>\n");  
           my @resources = &get_resources($Sequence);
           my $first_rownum =
               $self->get_row_number_from_key($resources[0]->symb);
           my $last_rownum = 
               $self->get_row_number_from_key($resources[-1]->symb);
           $r->print(&assess_file_selector([$first_rownum, $last_rownum],
                                           undef, \@AssessFileNames));
   
   $r->print($tableheader);    $r->print($tableheader);
  foreach my $resource (@{$Sequence->{'contents'}}) {   foreach my $resource (@resources) {
     next if ($resource->{'type'} ne 'assessment');      my $rownum = $self->get_row_number_from_key($resource->symb);
     my $rownum = $self->get_row_number_from_key($resource->{'symb'});  
             my $assess_filename = $self->{'row_source'}->{$rownum};              my $assess_filename = $self->{'row_source'}->{$rownum};
             my $row_output = '<tr>';              my $row_output = '<tr>';
             if ($editing_is_allowed) {              if ($editing_is_allowed) {
Line 263  END Line 292  END
                     '<a href="/adm/assesscalc?sname='.$self->{'name'}.                      '<a href="/adm/assesscalc?sname='.$self->{'name'}.
                     '&sdomain='.$self->{'domain'}.                      '&sdomain='.$self->{'domain'}.
                     '&filename='.$assess_filename.                      '&filename='.$assess_filename.
                     '&usymb='.&Apache::lonnet::escape($resource->{'symb'}).                      '&usymb='.&Apache::lonnet::escape($resource->symb).
                     '">'.$resource->{'title'}.'</a><br />';                      '">'.$resource->compTitle.'</a><br />';
                 $row_output .= &assess_file_selector($rownum,                  $row_output .= &assess_file_selector($rownum,
                                                      $assess_filename,                                                       $assess_filename,
                                                      \@AssessFileNames).                                                       \@AssessFileNames).
                                                          '</td>';                                                           '</td>';
             } else {              } else {
                 $row_output .= '<td><a href="'.$resource->{'src'}.'?symb='.                  $row_output .= '<td><a href="'.$resource->src.'?symb='.
                     &Apache::lonnet::escape($resource->{'symb'}).                      &Apache::lonnet::escape($resource->symb).
                     '">Go&nbsp;To</a>';                      '">Go&nbsp;To</a>';
                 $row_output .= '</td><td>'.$resource->{'title'}.'</td>';                  $row_output .= '</td><td>'.$resource->compTitle.'</td>';
             }              }
             if ($self->blackout() && $self->{'blackout_rows'}->{$rownum}>0) {              if ($self->blackout() && $self->{'blackout_rows'}->{$rownum}>0) {
                 $row_output .=                   $row_output .= 
Line 307  sub assess_file_selector { Line 336  sub assess_file_selector {
     if (!defined($AssessFiles) || ! @$AssessFiles) {      if (!defined($AssessFiles) || ! @$AssessFiles) {
         return '';          return '';
     }      }
     return '' if (! &Apache::lonnet::allowed('mgr',$ENV{'request.course.id'}));      return '' if (! &Apache::lonnet::allowed('mgr',$env{'request.course.id'}));
     my $element_name = 'FileSelect_'.$row;      my $element_name;
       my $source_row = $row;
       if (ref($row)) {
           my ($first_rownum, $last_rownum) = @$row;
           $element_name = "FileSelect_${first_rownum}_${last_rownum}";
           $source_row = "${first_rownum}:${last_rownum}";
       } else {
           $element_name = 'FileSelect_'.$row;
       }
     my $load_dialog = '<select size="1" name="'.$element_name.'" '.      my $load_dialog = '<select size="1" name="'.$element_name.'" '.
         'onchange="'.          'onchange="'.
         "document.sheet.cell.value='source_$row';".          "document.sheet.cell.value='source_${source_row}';".
         "document.sheet.newformula.value=document.sheet.$element_name\.value;".          "document.sheet.newformula.value=document.sheet.$element_name\.value;".
         'document.sheet.submit()" '.'>'."\n";          'document.sheet.submit()" '.'>'."\n";
       if (ref($row)) {
           $load_dialog .= '    <option name="" value="">' .
               &mt("Select spreadsheet for entire sequence")
               . "</option>\n";
       }
     foreach my $file (@{$AssessFiles}) {      foreach my $file (@{$AssessFiles}) {
         $load_dialog .= '    <option name="'.$file.'"';          $load_dialog .= '    <option name="'.$file.'"';
         $load_dialog .= ' selected' if ($default eq $file);          $load_dialog .= ' selected' if ($default eq $file);
Line 326  sub assess_file_selector { Line 368  sub assess_file_selector {
 sub modify_cell {  sub modify_cell {
     my $self = shift;      my $self = shift;
     my ($cell,$formula) = @_;      my ($cell,$formula) = @_;
     if ($cell =~ /^source_(\d+)$/) {  
         # Need to make sure $formula is a valid filename....      my $set_row = sub {
         my $row = $1;          my $row = shift;
         $cell = 'A'.$row;          my $formula = shift;
           my $cell = 'A' . $row;
         $self->{'row_source'}->{$row} = $formula;          $self->{'row_source'}->{$row} = $formula;
         my $original_source = $self->formula($cell);          my $original_source = $self->formula($cell);
         if ($original_source =~ /__&&&__/) {          if ($original_source =~ /__&&&__/) {
             ($original_source,undef) = split('__&&&__',$original_source);              ($original_source,undef) = split('__&&&__',$original_source);
         }          }
         $formula = $original_source.'__&&&__'.$formula;          $formula = $original_source.'__&&&__'.$formula;
           $self->set_formula($cell,$formula);
       };
   
       if ($cell =~ /^source_(\d+):(\d+)$/) {
           my $first_row = $1;
           my $last_row = $2;
           for my $row ($first_row..$last_row) {
               $set_row->($row, $formula);
           }
       } elsif ($cell =~ /^source_(\d+)$/) {
           # Need to make sure $formula is a valid filename....
           my $row = $1;
           $set_row->($row, $formula);
     } elsif ($cell =~ /([A-z])\-/) {      } elsif ($cell =~ /([A-z])\-/) {
         $cell = 'template_'.$1;          $cell = 'template_'.$1;
           $self->set_formula($cell,$formula);
     } elsif ($cell !~ /^([A-z](\d+)|template_[A-z])$/) {      } elsif ($cell !~ /^([A-z](\d+)|template_[A-z])$/) {
         return;          return;
     }      }
     $self->set_formula($cell,$formula);  
     $self->rebuild_stats();      $self->rebuild_stats();
     return;      return;
 }  }
Line 361  sub csv_rows { Line 417  sub csv_rows {
         &initialize_sequence_cache();          &initialize_sequence_cache();
     }      }
     foreach my $Sequence (@Sequences) {      foreach my $Sequence (@Sequences) {
  next if ($Sequence->{'num_assess'} < 1);   foreach my $resource (&get_resources($Sequence)) {
  foreach my $resource (@{$Sequence->{'contents'}}) {      my $rownum = $self->get_row_number_from_key($resource->symb);
     my $rownum = $self->get_row_number_from_key($resource->{'symb'});              my @assessdata = ($Sequence->compTitle,
             my @assessdata = ($Sequence->{'title'},                                $resource->compTitle);
                               $resource->{'title'});  
             $self->csv_output_row($filehandle,$rownum,@assessdata);              $self->csv_output_row($filehandle,$rownum,@assessdata);
         }          }
     }      }
Line 376  sub excel_rows { Line 431  sub excel_rows {
     # writes the meat of the spreadsheet to an excel worksheet.  Called      # writes the meat of the spreadsheet to an excel worksheet.  Called
     # by Spreadsheet::outsheet_excel;      # by Spreadsheet::outsheet_excel;
     my $self = shift;      my $self = shift;
     my ($connection,$worksheet,$cols_output,$rows_output) = @_;      my ($connection,$worksheet,$cols_output,$rows_output,$format) = @_;
     #      #
     # Write a header row      # Write a header row
     $cols_output = 0;      $cols_output = 0;
     foreach my $value ('Container','Assessment title') {      foreach my $value ('Container','Assessment title') {
         $worksheet->write($rows_output,$cols_output++,&mt($value));          $worksheet->write($rows_output,$cols_output++,&mt($value),$format->{'h4'});
     }      }
     $rows_output++;          $rows_output++;    
     #      #
Line 390  sub excel_rows { Line 445  sub excel_rows {
         &initialize_sequence_cache();          &initialize_sequence_cache();
     }      }
     foreach my $Sequence (@Sequences) {      foreach my $Sequence (@Sequences) {
  next if ($Sequence->{'num_assess'} < 1);   foreach my $resource (&get_resources($Sequence)) {
  foreach my $resource (@{$Sequence->{'contents'}}) {      my $rownum = $self->get_row_number_from_key($resource->symb);
     my $rownum = $self->get_row_number_from_key($resource->{'symb'});              my @assessdata = ($Sequence->compTitle,
             my @assessdata = ($Sequence->{'title'},                                $resource->compTitle);
                               $resource->{'title'});  
             $self->excel_output_row($worksheet,$rownum,$rows_output++,              $self->excel_output_row($worksheet,$rownum,$rows_output++,
                                     @assessdata);                                      @assessdata);
         }          }
Line 414  sub get_rows_in_sequence { Line 468  sub get_rows_in_sequence {
     my $self = shift();      my $self = shift();
     my ($sequence) = @_;      my ($sequence) = @_;
     my @Rows;      my @Rows;
     foreach my $resource (@{$sequence->{'contents'}}) {      my @resources = &get_resources($sequence);
         if ($resource->{'type'} eq 'assessment') {      foreach my $resource (@resources) {
             my $rownum = $self->get_row_number_from_key($resource->{'symb'});          my $rownum = $self->get_row_number_from_key($resource->symb);
             push (@Rows,$rownum);          push (@Rows,$rownum);
         }  
     }      }
     return @Rows;      return @Rows;
 }  }
Line 441  sub put_sequence_data_in_safe_space { Line 494  sub put_sequence_data_in_safe_space {
         # 1. duplicate titles - they get the total for the titles          # 1. duplicate titles - they get the total for the titles
         # 2. control characters in titles - use q{} around the string to          # 2. control characters in titles - use q{} around the string to
         #    deal with it.            #    deal with it.  
         my $title = &HTML::Entities::decode($seq->{'title'});          my $title = &HTML::Entities::decode($seq->title());
         $title =~ s/&\#058;/:/g;          $title =~ s/&\#058;/:/g;
         if (@Rows) {          if (@Rows) {
             $data .= 'push(@{$Sequence_Rows{"'.quotemeta($title).'"}},'.              $data .= 'push(@{$Sequence_Rows{"'.quotemeta($title).'"}},'.
Line 487  END Line 540  END
 sub compute {  sub compute {
     my $self = shift;      my $self = shift;
     my ($r) = @_;      my ($r) = @_;
     my $connection = $r->connection();  
     if ($connection->aborted()) { $self->cleanup; return; }  
     if (! defined($current_course) ||      if (! defined($current_course) ||
         $current_course ne $ENV{'request.course.id'} ||          $current_course ne $env{'request.course.id'} ||
         ! @Sequences ) {          ! @Sequences ) {
         $current_course = $ENV{'request.course.id'};          $current_course = $env{'request.course.id'};
         &clear_package();          &clear_package();
         &initialize_sequence_cache();          &initialize_sequence_cache();
     }      }
     $self->initialize_safe_space();      $self->initialize_safe_space();
     &Apache::assesscalc::initialize_package($self->{'name'},$self->{'domain'});      &Apache::assesscalc::initialize_package($self->{'name'},$self->{'domain'},
                                               $navmap);
     my %f = $self->formulas();      my %f = $self->formulas();
     #      #
     # Process the formulas list -       # Process the formulas list - 
     #   the formula for the A column of a row is symb__&&__filename      #   the formula for the A column of a row is symb__&&__filename
     my %c = $self->constants();      my %c = $self->constants();
     foreach my $seq (@Sequences) {      foreach my $seq (@Sequences) {
         next if ($seq->{'num_assess'}<1);          foreach my $resource (&get_resources($seq)) {
         foreach my $resource (@{$seq->{'contents'}}) {              my $rownum = $self->get_row_number_from_key($resource->symb);
             if ($connection->aborted()) { $self->cleanup(); return; }  
             next if ($resource->{'type'} ne 'assessment');  
             my $rownum = $self->get_row_number_from_key($resource->{'symb'});  
             my $cell = 'A'.$rownum;              my $cell = 'A'.$rownum;
             my $assess_filename = 'Default';              my $assess_filename = 'Default';
             if (exists($self->{'row_source'}->{$rownum})) {              if (exists($self->{'row_source'}->{$rownum})) {
Line 516  sub compute { Line 565  sub compute {
             } else {              } else {
                 $self->{'row_source'}->{$rownum} = $assess_filename;                  $self->{'row_source'}->{$rownum} = $assess_filename;
             }              }
             $f{$cell} = $resource->{'symb'}.'__&&&__'.$assess_filename;              $f{$cell} = $resource->symb.'__&&&__'.$assess_filename;
             if ($connection->aborted()) { $self->cleanup(); return; }  
             my $assessSheet;              my $assessSheet;
                 $assessSheet = Apache::assesscalc->new($self->{'name'},                  $assessSheet = Apache::assesscalc->new($self->{'name'},
                                                        $self->{'domain'},                                                         $self->{'domain'},
                                                        $assess_filename,                                                         $assess_filename,
                                                        $resource->{'symb'});                                                         $resource->symb,
          $self->{'section'},
                                                          $self->{'groups'});
             my @exportdata = $assessSheet->export_data($r);              my @exportdata = $assessSheet->export_data($r);
             #              #
             if ($assessSheet->badcalc()) {              if ($assessSheet->badcalc()) {
Line 531  sub compute { Line 581  sub compute {
                 $assessSheet->get_title(),$rownum,$assessSheet->calcerror()));                  $assessSheet->get_title(),$rownum,$assessSheet->calcerror()));
             }              }
             #              #
             if ($connection->aborted()) { $self->cleanup(); return; }  
             if ($assessSheet->blackout()) {              if ($assessSheet->blackout()) {
                 $self->blackout(1);                  $self->blackout(1);
                 $self->{'blackout_rows'}->{$rownum} = 1;                  $self->{'blackout_rows'}->{$rownum} = 1;
Line 574  sub compute { Line 623  sub compute {
   
 sub set_row_sources {  sub set_row_sources {
     my $self = shift;      my $self = shift;
       $self->check_formulas_loaded();
     while (my ($cell,$value) = each(%{$self->{'formulas'}})) {      while (my ($cell,$value) = each(%{$self->{'formulas'}})) {
         next if ($cell !~ /^A(\d+)$/ || $1 < 1);          next if ($cell !~ /^A(\d+)$/ || $1 < 1);
         my $row = $1;          my $row = $1;
Line 586  sub set_row_sources { Line 636  sub set_row_sources {
   
 sub set_row_numbers {  sub set_row_numbers {
     my $self = shift;      my $self = shift;
       $self->check_formulas_loaded();
     while (my ($cell,$formula) = each(%{$self->{'formulas'}})) {      while (my ($cell,$formula) = each(%{$self->{'formulas'}})) {
         next if ($cell !~ /^A(\d+)/);          next if ($cell !~ /^A(\d+)/);
         my $row = $1;          my $row = $1;
Line 624  These rows are saved in the courses dire Line 675  These rows are saved in the courses dire
 sub load_cached_export_rows {  sub load_cached_export_rows {
     undef(%Exportrows);      undef(%Exportrows);
     my @tmp = &Apache::lonnet::dump('nohist_calculatedsheets',      my @tmp = &Apache::lonnet::dump('nohist_calculatedsheets',
      $ENV{'course.'.$ENV{'request.course.id'}.'.domain'},       $env{'course.'.$env{'request.course.id'}.'.domain'},
      $ENV{'course.'.$ENV{'request.course.id'}.'.num'},undef);       $env{'course.'.$env{'request.course.id'}.'.num'},undef);
     my %Selected_Assess_Sheet;      my %Selected_Assess_Sheet;
     if ($tmp[0] =~ /^error/) {      if ($tmp[0] =~ /^error/) {
         &Apache::lonnet::logthis('unable to read cached student export rows '.          &Apache::lonnet::logthis('unable to read cached student export rows '.
                                  'for course '.$ENV{'request.course.id'});                                   'for course '.$env{'request.course.id'});
         return;          return;
     }      }
     my %tmp = @tmp;      my %tmp = @tmp;

Removed from v.1.27  
changed lines
  Added in v.1.39


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