File:  [LON-CAPA] / loncom / interface / spreadsheet / assesscalc.pm
Revision 1.5: download - view: text, annotated - select for diffs
Thu May 22 21:16:35 2003 UTC (21 years, 1 month ago) by matthew
Branches: MAIN
CVS tags: HEAD
Added 'blackout' support.  A blackout occurs when an assessment has a part
flagged with 'problemstatus' equal to 'no'.  This prevents the display of
the students performance on the part until the answerdate has passed.

Spreadsheet.pm contains &blackout, which returns the blackout status of
the current spreadsheet.

assesscalc.pm contains code which
    a) causes the computation of the spreadsheet to determine the
       blackout status
    b) forces the recomputation of the spreadsheet if the user is a student.
  Obviously (b) is less than ideal and a new approach should be found.

studentcalc.pm's outsheet_html subroutine now supresses the display of the
export (aka 'summary') row, as well as the rows of any assessments which
are under blackout.

    1: #
    2: # $Id: assesscalc.pm,v 1.5 2003/05/22 21:16:35 matthew Exp $
    3: #
    4: # Copyright Michigan State University Board of Trustees
    5: #
    6: # This file is part of the LearningOnline Network with CAPA (LON-CAPA).
    7: #
    8: # LON-CAPA is free software; you can redistribute it and/or modify
    9: # it under the terms of the GNU General Public License as published by
   10: # the Free Software Foundation; either version 2 of the License, or
   11: # (at your option) any later version.
   12: #
   13: # LON-CAPA is distributed in the hope that it will be useful,
   14: # but WITHOUT ANY WARRANTY; without even the implied warranty of
   15: # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   16: # GNU General Public License for more details.
   17: #
   18: # You should have received a copy of the GNU General Public License
   19: # along with LON-CAPA; if not, write to the Free Software
   20: # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
   21: #
   22: # /home/httpd/html/adm/gpl.txt
   23: #
   24: # http://www.lon-capa.org/
   25: #
   26: # The LearningOnline Network with CAPA
   27: # Spreadsheet/Grades Display Handler
   28: #
   29: # POD required stuff:
   30: 
   31: =head1 NAME
   32: 
   33: assesscalc
   34: 
   35: =head1 SYNOPSIS
   36: 
   37: =head1 DESCRIPTION
   38: 
   39: =cut
   40: 
   41: ###################################################
   42: ###                 AssessSheet                 ###
   43: ###################################################
   44: package Apache::assesscalc;
   45: 
   46: use strict;
   47: use Apache::Constants qw(:common :http);
   48: use Apache::lonnet;
   49: use Apache::loncommon;
   50: use Apache::Spreadsheet;
   51: use HTML::Entities();
   52: use Spreadsheet::WriteExcel;
   53: use GDBM_File;
   54: use Time::HiRes;
   55: 
   56: @Apache::assesscalc::ISA = ('Apache::Spreadsheet');
   57: 
   58: ########################################################
   59: ########################################################
   60: 
   61: =pod
   62: 
   63: =head2 Package Variables
   64: 
   65: =over 4
   66: 
   67: =item %Exportrows
   68: 
   69: =item $current_name
   70: 
   71: =item $current_domain
   72: 
   73: =item $current_course
   74: 
   75: =item %parmhash
   76: 
   77: =item %nice_parameter_name
   78: 
   79: =item %useropt
   80: 
   81: =item %courseopt
   82: 
   83: =back 
   84: 
   85: =cut
   86: 
   87: ########################################################
   88: ########################################################
   89: 
   90: my %Exportrows;
   91: 
   92: my $current_name;
   93: my $current_domain;
   94: my $current_course;
   95: 
   96: my %parmhash;
   97: my %nice_parameter_name;
   98: 
   99: my %useropt;
  100: my %courseopt;
  101: 
  102: ########################################################
  103: ########################################################
  104: 
  105: =pod
  106: 
  107: =head2 Package Subroutines
  108: 
  109: =item &clear_package()
  110: 
  111: Reset all package variables.  
  112: 
  113: =cut
  114: 
  115: ########################################################
  116: ########################################################
  117: sub clear_package {
  118:     undef(%Exportrows);
  119:     undef($current_name);
  120:     undef($current_domain);
  121:     undef($current_course);
  122:     undef(%useropt);
  123:     undef(%courseopt);
  124: }
  125: 
  126: ########################################################
  127: ########################################################
  128: 
  129: =pod
  130: 
  131: =item &initialize_package()
  132: 
  133: =cut
  134: 
  135: ########################################################
  136: ########################################################
  137: sub initialize_package {
  138:     my ($sname,$sdomain) = @_;
  139:     $current_course = $ENV{'request.course.id'};
  140:     $current_name   = $sname;
  141:     $current_domain = $sdomain;
  142:     undef(%courseopt);
  143:     &load_cached_export_rows();
  144:     &load_parameter_caches();
  145: }
  146: 
  147: ########################################################
  148: ########################################################
  149: 
  150: =pod
  151: 
  152: =item &load_parameter_caches()
  153: 
  154: =cut
  155: 
  156: ########################################################
  157: ########################################################
  158: sub load_parameter_caches {
  159:     my $userprefix = $current_name.':'.$current_domain.'_';
  160:     $userprefix =~ s/:/_/g;
  161:     #
  162:     # Course Parameters Cache
  163:     if (! %courseopt) {
  164:         &Apache::lonnet::logthis("loading course options");
  165:         $current_course = $ENV{'request.course.id'};
  166:         undef(%courseopt);
  167:         if (! defined($current_name) || ! defined($current_domain)) {
  168:             &Apache::lonnet::logthis('bad call to setup_parameter_caches');
  169:             return;
  170:         }
  171:         my $dom = $ENV{'course.'.$ENV{'request.course.id'}.'.domain'};
  172:         my $id  = $ENV{'course.'.$ENV{'request.course.id'}.'.num'};
  173:         my %Tmp = &Apache::lonnet::dump('resourcedata',$dom,$id);
  174:         while (my ($name,$value) = each(%Tmp)) {
  175:             $courseopt{$name}=$value;
  176:         }
  177:     }
  178:     if (! %useropt) {
  179:         my %Tmp = &Apache::lonnet::dump('resourcedata',
  180:                                         $current_domain,$current_name);
  181:         while (my ($name,$value) = each(%Tmp)) {
  182:             if ($name =~ /^error: 2/ || $name =~ /no such file/) {
  183:                 undef(%useropt);
  184:                 last;
  185:             }
  186:             $useropt{$userprefix.$name}=$value;
  187:         }
  188:     }
  189: }
  190: 
  191: ########################################################
  192: ########################################################
  193: 
  194: =pod
  195: 
  196: =head2 assesscalc object methods
  197: 
  198: =cut
  199: 
  200: ########################################################
  201: ########################################################
  202: sub ensure_current_parameter_caches {
  203:     my $self = shift;
  204:     if (! defined($current_course) || 
  205:         $current_course ne $ENV{'request.course.id'} ) {
  206:         $current_course = $ENV{'request.course.id'};
  207:         undef(%courseopt); 
  208:     }
  209:     if (! defined($current_name)   || $current_name ne $self->{'name'} ||
  210:         ! defined($current_domain) || $current_domain ne $self->{'domain'}) {
  211:         $current_domain = $self->{'domain'};
  212:         $current_name   = $self->{'name'};
  213:         undef(%useropt);
  214:     }
  215:     &load_parameter_caches();
  216: }
  217: 
  218: ##################################################
  219: ##################################################
  220: 
  221: =pod
  222: 
  223: =item &parmval()
  224: 
  225: Determine the value of a parameter.
  226: 
  227: Inputs: $what, the parameter needed, $symb, $uname, $udom, $csec 
  228: 
  229: Returns: The value of a parameter, or '' if none.
  230: 
  231: This function cascades through the possible levels searching for a value for
  232: a parameter.  The levels are checked in the following order:
  233: user, course (at section level and course level), map, and lonnet::metadata.
  234: This function uses %parmhash, which must be tied prior to calling it.
  235: This function also requires %courseopt and %useropt to be initialized for
  236: this user and course.
  237: 
  238: =cut
  239: 
  240: ##################################################
  241: ##################################################
  242: sub parmval {
  243:     my $self = shift;
  244:     my ($what,$symb,$uname,$udom,$csec)=@_;
  245:     $uname = $self->{'name'}    if (! defined($uname));
  246:     $udom  = $self->{'domain'}  if (! defined($udom));
  247:     $csec  = $self->{'section'} if (! defined($csec));
  248:     $symb  = $self->{'symb'}    if (! defined($symb));
  249:     #
  250:     my $result='';
  251:     #
  252:     # This should be a 
  253:     my ($mapname,$id,$fn)=split(/___/,$symb);
  254:     # Cascading lookup scheme
  255:     my $rwhat=$what;
  256:     $what =~ s/^parameter\_//;
  257:     $what =~ s/\_([^\_]+)$/\.$1/;
  258:     #
  259:     my $symbparm = $symb.'.'.$what;
  260:     my $mapparm  = $mapname.'___(all).'.$what;
  261:     my $courseprefix = $self->{'cid'};
  262:     my $usercourseprefix = $uname.'_'.$udom.'_'.$self->{'cid'};
  263:     #
  264:     my $seclevel  = $courseprefix.'.['.$csec.'].'.$what;
  265:     my $seclevelr = $courseprefix.'.['.$csec.'].'.$symbparm;
  266:     my $seclevelm = $courseprefix.'.['.$csec.'].'.$mapparm;
  267:     #
  268:     my $courselevel  = $courseprefix.'.'.$what;
  269:     my $courselevelr = $courseprefix.'.'.$symbparm;
  270:     my $courselevelm = $courseprefix.'.'.$mapparm;
  271:     #
  272:     my $ucourselevel  = $usercourseprefix.'.'.$what;
  273:     my $ucourselevelr = $usercourseprefix.'.'.$symbparm;
  274:     my $ucourselevelm = $usercourseprefix.'.'.$mapparm;
  275:    # check user
  276:     if (defined($uname)) {
  277:         return $useropt{$ucourselevelr} if (defined($useropt{$ucourselevelr}));
  278:         return $useropt{$ucourselevelm} if (defined($useropt{$ucourselevelm}));
  279:         return $useropt{$ucourselevel}  if (defined($useropt{$ucourselevel}));
  280:     }
  281:     # check section
  282:     if (defined($csec)) {
  283:         return $courseopt{$seclevelr} if (defined($courseopt{$seclevelr}));
  284:         return $courseopt{$seclevelm} if (defined($courseopt{$seclevelm}));
  285:         return $courseopt{$seclevel}  if (defined($courseopt{$seclevel}));
  286:     }
  287:     #
  288:     # check course
  289:     return $courseopt{$courselevelr} if (defined($courseopt{$courselevelr}));
  290:     return $courseopt{$courselevelm} if (defined($courseopt{$courselevelm}));
  291:     return $courseopt{$courselevel}  if (defined($courseopt{$courselevel}));
  292:     # check map parms
  293:     my $thisparm = $parmhash{$symbparm};
  294:     return $thisparm if (defined($thisparm));
  295:     # check default
  296:     $thisparm = &Apache::lonnet::metadata($fn,$rwhat.'.default');
  297:     return $thisparm if (defined($thisparm));
  298:     #
  299:     # Cascade Up
  300:     my $space=$what;
  301:     $space=~s/\.\w+$//;
  302:     if ($space ne '0') {
  303: 	my @parts=split(/_/,$space);
  304: 	my $id=pop(@parts);
  305: 	my $part=join('_',@parts);
  306: 	if ($part eq '') { $part='0'; }
  307: 	my $newwhat=$rwhat;
  308: 	$newwhat=~s/\Q$space\E/$part/;
  309: 	my $partgeneral=$self->parmval($newwhat,$symb,$uname,$udom,$csec);
  310: 	if (defined($partgeneral)) { return $partgeneral; }
  311:     }
  312:     #nothing defined
  313:     return '';
  314: }
  315: 
  316: sub get_title {
  317:     my $self = shift;
  318:     my $title;
  319:     if (($self->{'usymb'} eq '_feedback') ||
  320:         ($self->{'usymb'} eq '_evaluation') ||
  321:         ($self->{'usymb'} eq '_discussion') ||
  322:         ($self->{'usymb'} eq '_tutoring')) {
  323:         $title = $self->{'usymb'};
  324:         $title =~ s/^_//;
  325:         $title = '<h1>'.ucfirst($title)."</h1>\n";
  326:     } else {
  327:         $title = '<h1>'.&Apache::lonnet::gettitle($self->{'symb'})."</h1>\n";
  328:     }
  329:     # Look up the users identifying information
  330:     # Get the users information
  331:     my %userenv = &Apache::loncoursedata::GetUserName($self->{'name'},
  332:                                                       $self->{'domain'});
  333:     my $name = 
  334:         join(' ',@userenv{'firstname','middlename','lastname','generation'});
  335:     $name =~ s/\s+$//;
  336:     $title .= '<h2>'.$name.', '.
  337:         &Apache::loncommon::aboutmewrapper($self->{'name'}.'@'.$self->{'domain'},
  338:                                            $self->{'name'},$self->{'domain'}).
  339:                                            "</h2>\n";
  340:     $title .= '<h3>'.localtime(time).'</h3>';
  341:     #
  342:     return $title;
  343: }
  344: 
  345: sub parent_link {
  346:     my $self = shift;
  347:     my $link .= '<p><a href="/adm/studentcalc?'.
  348:         'sname='.$self->{'name'}.
  349:             '&sdomain='.$self->{'domain'}.'">'.
  350:                 'Student level sheet</a></p>'."\n";
  351:     return $link;
  352: }
  353: 
  354: sub outsheet_html {
  355:     my $self = shift;
  356:     my ($r) = @_;
  357:     ###################################
  358:     # Determine table structure
  359:     ###################################
  360:     my $num_uneditable = 1;
  361:     my $num_left = 52-$num_uneditable;
  362:     my $tableheader =<<"END";
  363: <table border="2">
  364: <tr>
  365:   <th colspan="2" rowspan="2"><font size="+2">Assessment</font></th>
  366:   <td bgcolor="#FFDDDD" colspan="$num_uneditable">&nbsp;</td>
  367:   <td colspan="$num_left">
  368:       <b><font size="+1">Calculations</font></b></td>
  369: </tr><tr>
  370: END
  371:     my $label_num = 0;
  372:     foreach (split(//,'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz')){
  373:         if ($label_num<$num_uneditable) { 
  374:             $tableheader .= '<td bgcolor="#FFDDDD">';
  375:         } else {
  376:             $tableheader .= '<td>';
  377:         }
  378:         $tableheader .= "<b><font size=+1>$_</font></b></td>";
  379:         $label_num++;
  380:     }
  381:     $tableheader.="</tr>\n";
  382:     #
  383:     $r->print($tableheader);
  384:     #
  385:     # Print out template row
  386:     $r->print('<tr><td>Template</td><td>&nbsp;</td>'.
  387: 	      $self->html_template_row($num_uneditable)."</tr>\n");
  388:     #
  389:     # Print out summary/export row
  390:     $r->print('<tr><td>Export</td><td>0</td>'.
  391: 	      $self->html_export_row()."</tr>\n");
  392:     #
  393:     # Prepare to output rows
  394:     $tableheader =<<"END";
  395: <table border="2">
  396: <tr><th>row</th><th>Item</th>
  397: END
  398:     foreach (split(//,'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz')){
  399: 	if ($label_num<$num_uneditable) { 
  400:             $tableheader.='<th bgcolor="#FFDDDD">';
  401:         } else {
  402:             $tableheader.='<th>';
  403:         }
  404:         $tableheader.="<b><font size=+1>$_</font></b></th>";
  405:     }
  406:     #
  407:     my $num_output = 0;
  408:     foreach my $rownum ($self->rows()) {
  409: 	if ($num_output++ % 50 == 0) {
  410: 	    $r->print("</table>\n".$tableheader);
  411: 	}
  412: 	$r->print('<tr><td>'.$rownum.'</td>'.
  413:                   $self->assess_html_row($num_uneditable,$rownum)."</tr>\n");
  414:     }
  415:     $r->print("</table>\n");
  416:     return;
  417: }
  418: 
  419: sub assess_html_row {
  420:     my $self = shift();
  421:     my ($num_uneditable,$row) = @_;
  422:     my $requester_is_student = ($ENV{'request.role'} =~ /^st\./);
  423:     my $parameter_name = $self->{'formulas'}->{'A'.$row};
  424:     my @rowdata = $self->get_row($row);
  425:     my $num_cols_output = 0;
  426:     my $row_html;
  427:     if (exists($nice_parameter_name{$parameter_name})) {
  428:         my $name = $nice_parameter_name{$parameter_name};
  429:         $name =~ s/ /\&nbsp;/g;
  430:         $row_html .= '<td>'.$name.'<br />'.$parameter_name.'</td>';
  431:     } else {
  432:         $row_html .= '<td>'.$parameter_name.'</td>';
  433:     }
  434:     foreach my $cell (@rowdata) {
  435: 	if ($requester_is_student || 
  436: 	    $num_cols_output++ < $num_uneditable) {
  437: 	    $row_html .= '<td bgcolor="#FFDDDD">';
  438: 	    $row_html .= &Apache::Spreadsheet::html_uneditable_cell($cell,'#FFDDDD');
  439: 	} else {
  440: 	    $row_html .= '<td bgcolor="#EOFFDD">';
  441: 	    $row_html .= &Apache::Spreadsheet::html_editable_cell($cell,'#E0FFDD');
  442: 	}
  443: 	$row_html .= '</td>';
  444:     }
  445:     return $row_html;
  446: }
  447: 
  448: sub outsheet_csv {
  449:     my $self = shift;
  450:     my ($r)=@_;
  451: }
  452: 
  453: sub outsheet_excel {
  454:     my $self = shift;
  455:     my ($r)=@_;
  456: }
  457: 
  458: sub display {
  459:     my $self = shift;
  460:     my ($r) = @_;
  461:     $self->compute();
  462:     $self->outsheet_html($r);
  463: }
  464: 
  465: sub compute {
  466:     my $self = shift;
  467:     $self->logthis('computing');
  468:     $self->initialize_safe_space();
  469:     #
  470:     # Definitions
  471:     undef(%nice_parameter_name);
  472:     my %parameters;   # holds underscored parameters by name
  473:     #
  474:     # Get the metadata fields and determine their proper names
  475:     my ($symap,$syid,$srcf)=split(/___/,$self->{'symb'});
  476:     my @Metadata = split(/\,/,&Apache::lonnet::metadata($srcf,'keys'));
  477:     foreach my $parm (@Metadata) {
  478:         next if ($parm !~ /^(resource\.|stores|parameter)_/);
  479:         my $cleaned_name = $parm;
  480:         $cleaned_name =~ s/^resource\./stores_/;
  481:         $cleaned_name =~ s/\./_/g;
  482:         my $display = &Apache::lonnet::metadata($srcf,
  483:                                                 $cleaned_name.'.display');
  484:         if (! $display) {
  485:             $display .= &Apache::lonnet::metadata($srcf,$cleaned_name.'.name');
  486:         }
  487:         $parameters{$cleaned_name}++;
  488:         $nice_parameter_name{$cleaned_name} = $display;
  489:     }
  490:     #
  491:     # Get the values of the metadata fields
  492:     $self->ensure_current_parameter_caches();
  493:     my $filename = $self->{'coursefilename'}.'_parms.db';
  494:     if (tie(%parmhash,'GDBM_File',
  495:             $self->{'coursefilename'}.'_parms.db',&GDBM_READER(),0640)) {
  496:         foreach my $parmname (keys(%parameters)) {
  497:             my $value = $self->parmval($parmname);
  498:             $parameters{$parmname} =$value;
  499:         }
  500:         untie(%parmhash);
  501:     } else {
  502:         $self->logthis('unable to tie '.$filename);
  503:     }
  504:     #
  505:     # Clean out unnecessary parameters
  506:     foreach (keys(%parameters)) {
  507:         delete($parameters{$_}) if (! /(resource\.|stores_|parameter_)/);
  508:     }
  509:     #
  510:     # Get the students performance data
  511:     my %student_parameters = 
  512:         &Apache::loncoursedata::get_current_state($self->{'name'},
  513:                                                   $self->{'domain'},
  514:                                                   $self->{'symb'},
  515:                                                   $self->{'cid'});
  516:     while (my ($parm,$value) = each(%student_parameters)) {
  517:         $parm =~ s/^resource\./stores_/;
  518:         $parm =~ s/\./_/g;
  519:         $parameters{$parm} = $value;
  520:     }
  521:     #
  522:     # Set up the formulas and parameter values
  523:     my %f=$self->formulas();
  524:     my %c;
  525:     #
  526:     # Check for blackout requirements
  527:     if ((!exists($ENV{'request.role.adv'}) || !$ENV{'request.role.adv'})) {
  528:         while (my ($parm,$value) = each(%parameters)) {
  529:             last if ($self->blackout());
  530:             next if ($parm !~ /^(parameter_.*)_problemstatus$/);
  531:             next if ($parameters{$1.'_answerdate'}<time);
  532:             if (lc($value) eq 'no') {
  533:                 # We must blackout this sheet
  534:                 $self->blackout(1);
  535:             }
  536:         }
  537:     }
  538:     #
  539:     # Move the parameters into the spreadsheet
  540:     while (my ($parm,$value) = each(%parameters)) {
  541:         my $cell = 'A'.$self->get_row_number_from_key($parm);
  542:         $f{$cell} = $parm;
  543:         $c{$parm} = '';
  544:         if ($value ne '') {
  545:             $c{$parm} = '"'.$value.'"';
  546:         }
  547:     }
  548:     $self->formulas(%f);
  549:     $self->constants(%c);
  550:     $self->calcsheet();
  551:     #
  552:     # Store export row in cache
  553:     my @exportarray = $self->exportrow();
  554:     $Exportrows{$self->{'symb'}}->{'time'} = time;
  555:     $Exportrows{$self->{'symb'}}->{$self->{'filename'}} = \@exportarray;
  556:     #
  557:     # Save the export data
  558:     $self->save_export_data();
  559:     return;
  560: }
  561: 
  562: ##
  563: ## sett overrides Spreadsheet::sett
  564: ##
  565: sub sett {
  566:     my $self = shift;
  567:     my %t=();
  568:     #
  569:     # Deal with the template row by copying the template formulas into each
  570:     # row.
  571:     foreach my $col ($self->template_cells()) {
  572:         next if ($col=~/^A/);
  573:         foreach my $row ($self->rows()) {
  574:             # Get the name of this cell
  575:             my $cell=$col.$row;
  576:             # Grab the template declaration
  577:             $t{$cell}=$self->formula('template_'.$col);
  578:             # Replace '#' with the row number
  579:             $t{$cell}=~s/\#/$row/g;
  580:             # Replace '....' with ','
  581:             $t{$cell}=~s/\.\.+/\,/g;
  582:             # Replace 'A0' with the value from 'A0'
  583:             $t{$cell}=~s/(^|[^\"\'])([A-Za-z]\d+)/$1\$sheet_values\{\'$2\'\}/g;
  584:             # Replace parameters
  585:             $t{$cell}=~s/(^|[^\"\'])\[([^\]]+)\]/$1.$self->expandnamed($2)/ge;
  586:         }
  587:     }
  588:     #
  589:     # Deal with the cells which have formulas
  590:     while (my ($cell,$formula) = each(%{$self->{'formulas'}})) {
  591: 	next if ($cell =~ /template_/);
  592:         if ($cell =~ /^A/ && $cell ne 'A0') {
  593:             if ($formula !~ /^\!/) {
  594:                 $t{$cell}=$self->{'constants'}->{$formula};
  595:             }
  596:         } else {
  597:             $t{$cell}=$formula;
  598:             $t{$cell}=~s/\.\.+/\,/g;
  599:             $t{$cell}=~s/(^|[^\"\'])([A-Za-z]\d+)/$1\$sheet_values\{\'$2\'\}/g;
  600:             $t{$cell}=~s/(^|[^\"\'])\[([^\]]+)\]/$1.$self->expandnamed($2)/ge;
  601:         }
  602:     }
  603:     # Put %t into the safe space
  604:     %{$self->{'safe'}->varglob('t')}=%t;
  605: }
  606: 
  607: 
  608: ########################################################
  609: ########################################################
  610: 
  611: =pod
  612: 
  613: =item &load_cached_export_rows()
  614: 
  615: Retrieves and parsers the export rows of the assessment spreadsheets.
  616: These rows are saved in the students directory in the format:
  617: 
  618:  sname:sdom:assesscalc:symb.time => time
  619: 
  620:  sname:sdom:assesscalc:symb => filename___=___Adata___;___Bdata___;___ ...
  621: 
  622: =cut
  623: 
  624: ########################################################
  625: ########################################################
  626: sub load_cached_export_rows {
  627:     %Exportrows = undef;
  628:     my @tmp = &Apache::lonnet::dump('nohist_calculatedsheets_'.
  629:                                     $ENV{'request.course.id'},
  630:                                     $current_domain,$current_name,undef);
  631:     if ($tmp[0]!~/^error/) {
  632:         my %tmp = @tmp;
  633:         my $default_filename =  $ENV{'course.'.$ENV{'request.course.id'}.
  634:                                          '.spreadsheet_default_assesscalc'};
  635:         # We only got one key, so we will access it directly.
  636:         while (my ($key,$sheetdata) = each(%tmp)) {
  637:             my ($sname,$sdom,$sheettype,$symb) = split(':',$key);
  638:             if ($symb =~ /\.time$/) {
  639:                 $symb =~ s/\.time$//;
  640:                 $Exportrows{$symb}->{'time'} = $sheetdata;
  641:             } else {
  642:                 $sheetdata =~ s/^(.*)___=___//;
  643:                 my $filename = $1;
  644:                 $filename = $default_filename if (! defined($filename));
  645:                 my @Data = split('___;___',$sheetdata);
  646:                 $Exportrows{$symb}->{$filename} = \@Data;
  647:             }
  648:         }
  649:     }
  650: }
  651: 
  652: #############################################
  653: #############################################
  654: 
  655: =pod
  656: 
  657: =item &export_data
  658: 
  659: Returns the export data associated with the spreadsheet.  Computes the
  660: spreadsheet only if necessary.
  661: 
  662: =cut
  663: 
  664: #############################################
  665: #############################################
  666: sub export_data {
  667:     my $self = shift;
  668:     my $symb = $self->{'symb'};
  669:     if (! exists($ENV{'request.role.adv'}) || ! $ENV{'request.role.adv'} ||
  670:         ! exists($Exportrows{$symb}) || ! defined($Exportrows{$symb})  ||
  671:         ! $self->check_expiration_time($Exportrows{$symb}->{'time'}) ||
  672:         ! exists($Exportrows{$symb}->{$self->{'filename'}}) ||
  673:         ! defined($Exportrows{$symb}->{$self->{'filename'}})) {
  674:         $self->compute();
  675:     }
  676:     my @Data = @{$Exportrows{$symb}->{$self->{'filename'}}};
  677:     if ($Data[0] =~ /^(.*)___=___/) {
  678:         $self->{'sheetname'} = $1;
  679:         $Data[0] =~ s/^(.*)___=___//;
  680:     }
  681:     for (my $i=0;$i<$#Data;$i++) {
  682:         $Data[$i]="'".$Data[$i]."'" if ($Data[$i]=~/\D/ && defined($Data[$i]));
  683:     }
  684:     return @Data;
  685: }
  686: 
  687: #############################################
  688: #############################################
  689: 
  690: =pod
  691: 
  692: =item &save_export_data()
  693: 
  694: Writes the export data for this spreadsheet to the students cache.
  695: 
  696: =cut
  697: 
  698: #############################################
  699: #############################################
  700: sub save_export_data {
  701:     my $self = shift;
  702:     my $student = $self->{'name'}.':'.$self->{'domain'};
  703:     my $symb    = $self->{'symb'};
  704:     if (! exists($Exportrows{$symb}) || 
  705:         ! exists($Exportrows{$symb}->{$self->{'filename'}})) {
  706:         return;
  707:     }
  708:     my $key = join(':',($self->{'name'},$self->{'domain'},'assesscalc',$symb));
  709:     my $timekey = $key.'.time';
  710:     my $newstore= join('___;___',@{$Exportrows{$symb}->{$self->{'filename'}}});
  711:     $newstore = $self->{'filename'}.'___=___'.$newstore;
  712:     my $result = &Apache::lonnet::put
  713:         ('nohist_calculatedsheets_'.$ENV{'request.course.id'},
  714:          { $key     => $newstore,
  715:            $timekey => $Exportrows{$symb}->{'time'} },
  716:          $self->{'domain'},
  717:          $self->{'name'});
  718: 
  719:     return;
  720: }
  721: 
  722: 1;
  723: 
  724: __END__

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