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

matthew lon-capa-cvs@mail.lon-capa.org
Mon, 21 Oct 2002 17:59:37 -0000


This is a MIME encoded message

--matthew1035223177
Content-Type: text/plain

matthew		Mon Oct 21 13:59:37 2002 EDT

  Modified files:              
    /loncom/interface	lonspreadsheet.pm 
  Log:
  Module-wide changes: There are no longer seperate $safeeval and $sheetdata
  entities.  There is only $sheet, which will eventually become an object of 
  sorts.  Most functions earlier took $safeeval and $sheetdata as parameters
  but now only take $sheet.
  Many comments added to the variables inside the safe space.  The safe space
  has not been changed in this commit, so there are no speedups to show off.
  No longer print a student status selection dialog on non-course spreadsheets.
  Still have the bug in which not all student export data makes it into the
  course sheet.
  
  
--matthew1035223177
Content-Type: text/plain
Content-Disposition: attachment; filename="matthew-20021021135937.txt"

Index: loncom/interface/lonspreadsheet.pm
diff -u loncom/interface/lonspreadsheet.pm:1.118 loncom/interface/lonspreadsheet.pm:1.119
--- loncom/interface/lonspreadsheet.pm:1.118	Fri Oct 18 09:46:01 2002
+++ loncom/interface/lonspreadsheet.pm	Mon Oct 21 13:59:36 2002
@@ -1,5 +1,5 @@
 #
-# $Id: lonspreadsheet.pm,v 1.118 2002/10/18 13:46:01 matthew Exp $
+# $Id: lonspreadsheet.pm,v 1.119 2002/10/21 17:59:36 matthew Exp $
 #
 # Copyright Michigan State University Board of Trustees
 #
@@ -221,12 +221,29 @@
 # rl: row label
 # os: other spreadsheets (for student spreadsheet only)
 
-undef %sheet_values; 
-undef %t;
-undef %f;
-undef %c;
-undef %rowlabel;
-undef @os;
+undef %sheet_values;   # Holds the (computed, final) values for the sheet
+    # This is only written to by &calc, the spreadsheet computation routine.
+    # It is read by many functions
+undef %t; # Holds the values of the spreadsheet temporarily. Set in &sett, 
+    # which does the translation of strings like C5 into the value in C5.
+    # Used in &calc - %t holds the values that are actually eval'd.
+undef %f;    # Holds the formulas for each cell.  This is the users
+    # (spreadsheet authors) data for each cell.
+    # set by &setformulas and returned by &getformulas
+    # &setformulas is called by &readsheet, &tmpread, &updateclasssheet,
+    # &updatestudentassesssheet, &loadstudent, &loadcourse
+    # &getformulas is called by &writesheet, &tmpwrite, &updateclasssheet,
+    # &updatestudentassesssheet, &loadstudent, &loadcourse, &loadassessment, 
+undef %c; # Holds the constants for a sheet.  In the assessment
+    # sheets, this is the A column.  Used in &MINPARM, &MAXPARM, &expandnamed,
+    # &sett, and &setconstants.  There is no &getconstants.
+    # &setconstants is called by &loadstudent, &loadcourse, &load assessment,
+undef %rowlabel;  # Holds the 'prefix' for each row.  Set by &setrowlabels.
+    # &setrowlabels is called by &updateclasssheet, &updatestudentassesssheet,
+undef @os;  # Holds the names of other spreadsheets - this is used to specify
+    # the spreadsheets that are available for the assessment sheet.
+    # Set by &setothersheets.  &setothersheets is called by &handler.  A
+    # related subroutine is &othersheets.
 
 $maxrow = 0;
 $sheettype = '';
@@ -1019,50 +1036,54 @@
 
 # ------------------------------------------------ Add or change formula values
 sub setformulas {
-    my ($safeeval,%f)=@_;
-    %{$safeeval->varglob('f')}=%f;
+    my ($sheet)=shift;
+    %{$sheet->{'safe'}->varglob('f')}=%{$sheet->{'f'}};
 }
 
 # ------------------------------------------------ Add or change formula values
 sub setconstants {
-    my ($safeeval,%c)=@_;
-    %{$safeeval->varglob('c')}=%c;
+    my ($sheet)=shift;
+    return %{$sheet->{'safe'}->varglob('c')}=%{$sheet->{'constants'}};
 }
 
 # --------------------------------------------- Set names of other spreadsheets
 sub setothersheets {
-    my ($safeeval,@os)=@_;
-    @{$safeeval->varglob('os')}=@os;
+    my $sheet = shift;
+    my @othersheets = @_;
+    $sheet->{'othersheets'} = \@othersheets;
+    @{$sheet->{'safe'}->varglob('os')}=@othersheets;
+    return;
 }
 
 # ------------------------------------------------ Add or change formula values
 sub setrowlabels {
-    my ($safeeval,%rowlabel)=@_;
-    %{$safeeval->varglob('rowlabel')}=%rowlabel;
+    my $sheet=shift;
+    %{$sheet->{'safe'}->varglob('rowlabel')}=%{$sheet->{'rowlabel'}};
 }
 
 # ------------------------------------------------------- Calculate spreadsheet
 sub calcsheet {
-    my $safeeval=shift;
-    return $safeeval->reval('&calc();');
+    my $sheet=shift;
+    return $sheet->{'safe'}->reval('&calc();');
 }
 
 # ---------------------------------------------------------------- Get formulas
 sub getformulas {
-    my $safeeval=shift;
-    return %{$safeeval->varglob('f')};
+    my $sheet = shift;
+    return %{$sheet->{'safe'}->varglob('f')};
 }
 
 # ----------------------------------------------------- Get value of $f{'A'.$n}
 sub getfa {
-    my ($safeeval,$n)=@_;
-    return $safeeval->reval('$f{"A'.$n.'"}');
+    my $sheet = shift;
+    my ($n)=@_;
+    return $sheet->{'safe'}->reval('$f{"A'.$n.'"}');
 }
 
 # ------------------------------------------------------------- Export of A-row
 sub exportdata {
-    my $safeeval=shift;
-    return $safeeval->reval('&exportrowa()');
+    my $sheet=shift;
+    return $sheet->{'safe'}->reval('&exportrowa()');
 }
 
 
@@ -1075,7 +1096,7 @@
 # --------------------------------------------- Produce output row n from sheet
 
 sub rown {
-    my ($safeeval,$n,$sheetdata)=@_;
+    my ($sheet,$n)=@_;
     my $defaultbg;
     my $rowdata='';
     my $dataflag=0;
@@ -1092,7 +1113,7 @@
     my $showf=0;
     my $proc;
     my $maxred=1;
-    my $sheettype=$sheetdata->{'sheettype'};
+    my $sheettype=$sheet->{'sheettype'};
     if ($sheettype eq 'studentcalc') {
         $proc='&outrowassess';
         $maxred=26;
@@ -1104,13 +1125,13 @@
     } else {
         $maxred=26;
     }
-    if (&getfa($safeeval,$n)=~/^[\~\-]/) { $maxred=1; }
+    if (&getfa($sheet,$n)=~/^[\~\-]/) { $maxred=1; }
     if ($n eq '-') { 
         $proc='&templaterow'; 
         $n=-1; 
         $dataflag=1; 
     }
-    foreach ($safeeval->reval($proc.'('.$n.')')) {
+    foreach ($sheet->{'safe'}->reval($proc.'('.$n.')')) {
         my $bgcolor=$defaultbg.((($showf-1)/5==int(($showf-1)/5))?'99':'DD');
         my ($fm,$vl)=split(/\_\_\_eq\_\_\_/,$_);
         if ((($vl ne '') || ($vl eq '0')) &&
@@ -1149,17 +1170,17 @@
 # ------------------------------------------------------------- Print out sheet
 
 sub outsheet {
-    my ($r,$safeeval,$sheetdata)=@_;
+    my ($r,$sheet)=@_;
     my $maxred = 26;    # The maximum number of cells to show as 
                         # red (uneditable) 
                         # To make student sheets uneditable could we 
                         # set $maxred = 52?
                         #
     my $realm='Course'; # 'assessment', 'user', or 'course' sheet
-    if ($sheetdata->{'sheettype'} eq 'assesscalc') {
+    if ($sheet->{'sheettype'} eq 'assesscalc') {
         $maxred=1;
         $realm='Assessment';
-    } elsif ($sheetdata->{'sheettype'} eq 'studentcalc') {
+    } elsif ($sheet->{'sheettype'} eq 'studentcalc') {
         $maxred=26;
         $realm='User';
     }
@@ -1188,35 +1209,34 @@
             }
             $tabledata.="<b><font size=+1>$_</font></b></td>";
         }
-        $tabledata.='</tr>'.&rown($safeeval,'-',$sheetdata).
-            &rown($safeeval,0,$sheetdata);
+        $tabledata.='</tr>'.&rown($sheet,'-').
+            &rown($sheet,0);
     }
     $r->print($tabledata);
     #
     # Prepare to output rows
     my $row;
-    my $maxrow=$sheetdata->{'maxrow'};
     #
     my @sortby=();
     my @sortidx=();
-    for ($row=1;$row<=$maxrow;$row++) {
-        push (@sortby, $safeeval->reval('$f{"A'.$row.'"}'));
+    for ($row=1;$row<=$sheet->{'maxrow'};$row++) {
+        push (@sortby, $sheet->{'safe'}->reval('$f{"A'.$row.'"}'));
         push (@sortidx, $row-1);
     }
     @sortidx=sort { lc($sortby[$a]) cmp lc($sortby[$b]); } @sortidx;
     #
     # Determine the type of child spreadsheets
     my $what='Student';
-    if ($sheetdata->{'sheettype'} eq 'assesscalc') {
+    if ($sheet->{'sheettype'} eq 'assesscalc') {
         $what='Item';
-    } elsif ($sheetdata->{'sheettype'} eq 'studentcalc') {
+    } elsif ($sheet->{'sheettype'} eq 'studentcalc') {
         $what='Assessment';
     }
     #
     # Loop through the rows and output them one at a time
     my $n=0;
-    for ($row=0;$row<$maxrow;$row++) {
-        my $thisrow=&rown($safeeval,$sortidx[$row]+1,$sheetdata);
+    for ($row=0;$row<$sheet->{'maxrow'};$row++) {
+        my $thisrow=&rown($sheet,$sortidx[$row]+1);
         if ($thisrow) {
             if (($n/25==int($n/25)) && (!$ENV{'form.showcsv'})) {
                 $r->print("</table>\n<br>\n");
@@ -1239,11 +1259,12 @@
 # ----------------------------------------------- Read list of available sheets
 # 
 sub othersheets {
-    my ($safeeval,$stype,$sheetdata)=@_;
+    my ($sheet,$stype)=@_;
+    $stype = $sheet->{'sheettype'} if (! defined($stype));
     #
-    my $cnum  = $sheetdata->{'cnum'};
-    my $cdom  = $sheetdata->{'cdom'};
-    my $chome = $sheetdata->{'chome'};
+    my $cnum  = $sheet->{'cnum'};
+    my $cdom  = $sheet->{'cdom'};
+    my $chome = $sheet->{'chome'};
     #
     my @alternatives=();
     my %results=&Apache::lonnet::dump($stype.'_spreadsheets',$cdom,$cnum);
@@ -1287,12 +1308,12 @@
 # -------------------------------------- Read spreadsheet formulas for a course
 #
 sub readsheet {
-    my ($safeeval,$sheetdata,$fn)=@_;
+    my ($sheet,$fn)=@_;
     #
-    my $stype = $sheetdata->{'sheettype'};
-    my $cnum  = $sheetdata->{'cnum'};
-    my $cdom  = $sheetdata->{'cdom'};
-    my $chome = $sheetdata->{'chome'};
+    my $stype = $sheet->{'sheettype'};
+    my $cnum  = $sheet->{'cnum'};
+    my $cdom  = $sheet->{'cdom'};
+    my $chome = $sheet->{'chome'};
     #
     if (! defined($fn)) {
         # There is no filename. Look for defaults in course and global, cache
@@ -1313,11 +1334,13 @@
         }
     }
     # $fn now has a value
-    $sheetdata->{'filename'} = $fn;
+    $sheet->{'filename'} = $fn;
     # see if sheet is cached
     my $fstring='';
     if ($fstring=$spreadsheets{$cnum.'_'.$cdom.'_'.$stype.'_'.$fn}) {
-        &setformulas($safeeval,split(/\_\_\_\;\_\_\_/,$fstring));
+        my %tmp = split(/___;___/,$fstring);
+        $sheet->{'f'} = \%tmp;
+        &setformulas($sheet);
     } else {
         # Not cached, need to read
         my %f=();
@@ -1352,48 +1375,58 @@
         }
         # Cache and set
         $spreadsheets{$cnum.'_'.$cdom.'_'.$stype.'_'.$fn}=join('___;___',%f);  
-        &setformulas($safeeval,%f);
+        $sheet->{'f'}=\%f;
+        &setformulas($sheet);
     }
 }
 
 # -------------------------------------------------------- Make new spreadsheet
 sub makenewsheet {
     my ($uname,$udom,$stype,$usymb)=@_;
-    my %sheetdata=();
-    $sheetdata{'uname'} = $uname;
-    $sheetdata{'udom'}  = $udom;
-    $sheetdata{'sheettype'} = $stype;
-    $sheetdata{'usymb'} = $usymb;
-    $sheetdata{'cid'}   = $ENV{'request.course.id'};
-    $sheetdata{'csec'}  = $Section{$uname.':'.$udom};
-    $sheetdata{'coursefilename'}   = $ENV{'request.course.fn'};
-    $sheetdata{'cnum'}  = $ENV{'course.'.$ENV{'request.course.id'}.'.num'};
-    $sheetdata{'cdom'}  = $ENV{'course.'.$ENV{'request.course.id'}.'.domain'};
-    $sheetdata{'chome'} = $ENV{'course.'.$ENV{'request.course.id'}.'.home'};
-    $sheetdata{'uhome'} = &Apache::lonnet::homeserver($uname,$udom);
-    
-    my $safeeval=initsheet($stype);
+    my $sheet={};
+    $sheet->{'uname'} = $uname;
+    $sheet->{'udom'}  = $udom;
+    $sheet->{'sheettype'} = $stype;
+    $sheet->{'usymb'} = $usymb;
+    $sheet->{'cid'}   = $ENV{'request.course.id'};
+    $sheet->{'csec'}  = $Section{$uname.':'.$udom};
+    $sheet->{'coursefilename'}   = $ENV{'request.course.fn'};
+    $sheet->{'cnum'}  = $ENV{'course.'.$ENV{'request.course.id'}.'.num'};
+    $sheet->{'cdom'}  = $ENV{'course.'.$ENV{'request.course.id'}.'.domain'};
+    $sheet->{'chome'} = $ENV{'course.'.$ENV{'request.course.id'}.'.home'};
+    $sheet->{'uhome'} = &Apache::lonnet::homeserver($uname,$udom);
+    #
+    #
+    $sheet->{'f'} = {};
+    $sheet->{'constants'} = {};
+    $sheet->{'othersheets'} = [];
+    $sheet->{'rowlabel'} = {};
+    #
     #
-    # Place all the %sheetdata items into the safe space
+    $sheet->{'safe'}=&initsheet($sheet->{'sheettype'});
+    #
+    # Place all the %$sheet items into the safe space except the safe space
+    # itself
     my $initstring = '';
-    foreach (keys(%sheetdata)) {
-        $initstring.= qq{\$$_="$sheetdata{$_}";};
+    foreach (qw/uname udom sheettype usymb cid csec coursefilename
+             cnum cdom chome uhome/) {
+        $initstring.= qq{\$$_="$sheet->{$_}";};
     }
-    $safeeval->reval($initstring);
-    return $safeeval,\%sheetdata;
+    $sheet->{'safe'}->reval($initstring);
+    return $sheet;
 }
 
 # ------------------------------------------------------------ Save spreadsheet
 sub writesheet {
-    my ($safeeval,$makedef,$sheetdata)=@_;
-    my $cid=$sheetdata->{'cid'};
+    my ($sheet,$makedef)=@_;
+    my $cid=$sheet->{'cid'};
     if (&Apache::lonnet::allowed('opa',$cid)) {
-        my %f=&getformulas($safeeval);
-        my $stype= $sheetdata->{'sheettype'};
-        my $cnum = $sheetdata->{'cnum'};
-        my $cdom = $sheetdata->{'cdom'};
-        my $chome= $sheetdata->{'chome'};
-        my $fn   = $sheetdata->{'filename'};
+        my %f=&getformulas($sheet);
+        my $stype= $sheet->{'sheettype'};
+        my $cnum = $sheet->{'cnum'};
+        my $cdom = $sheet->{'cdom'};
+        my $chome= $sheet->{'chome'};
+        my $fn   = $sheet->{'filename'};
         # Cache new sheet
         $spreadsheets{$cnum.'_'.$cdom.'_'.$stype.'_'.$fn}=join('___;___',%f);
         # Write sheet
@@ -1436,24 +1469,24 @@
 # "Modified workcopy" - interactive only
 #
 sub tmpwrite {
-    my ($safeeval,$sheetdata) = @_;
+    my ($sheet) = @_;
     my $fn=$ENV{'user.name'}.'_'.
-        $ENV{'user.domain'}.'_spreadsheet_'.$sheetdata->{'usymb'}.'_'.
-           $sheetdata->{'filename'};
+        $ENV{'user.domain'}.'_spreadsheet_'.$sheet->{'usymb'}.'_'.
+           $sheet->{'filename'};
     $fn=~s/\W/\_/g;
     $fn=$tmpdir.$fn.'.tmp';
     my $fh;
     if ($fh=Apache::File->new('>'.$fn)) {
-	print $fh join("\n",&getformulas($safeeval));
+	print $fh join("\n",&getformulas($sheet));
     }
 }
 
 # ---------------------------------------------------------- Read the temp copy
 sub tmpread {
-    my ($safeeval,$sheetdata,$nfield,$nform)=@_;
+    my ($sheet,$nfield,$nform)=@_;
     my $fn=$ENV{'user.name'}.'_'.
-           $ENV{'user.domain'}.'_spreadsheet_'.$sheetdata->{'usymb'}.'_'.
-           $sheetdata->{'filename'};
+           $ENV{'user.domain'}.'_spreadsheet_'.$sheet->{'usymb'}.'_'.
+           $sheet->{'filename'};
     $fn=~s/\W/\_/g;
     $fn=$tmpdir.$fn.'.tmp';
     my $fh;
@@ -1489,7 +1522,8 @@
     } else {
        if ($nfield) { $fo{$nfield}=$nform; }
     }
-    &setformulas($safeeval,%fo);
+    $sheet->{'f'}=\%fo;
+    &setformulas($sheet);
 }
 
 ##################################################
@@ -1501,7 +1535,7 @@
 
 Determine the value of a parameter.
 
-Inputs: $what, the parameter needed, $safeeval, the safe space
+Inputs: $what, the parameter needed, $sheet, the safe space
 
 Returns: The value of a parameter, or '' if none.
 
@@ -1517,14 +1551,14 @@
 ##################################################
 ##################################################
 sub parmval {
-    my ($what,$safeeval,$sheetdata)=@_;
-    my $symb  = $sheetdata->{'usymb'};
+    my ($what,$sheet)=@_;
+    my $symb  = $sheet->{'usymb'};
     unless ($symb) { return ''; }
     #
-    my $cid   = $sheetdata->{'cid'};
-    my $csec  = $sheetdata->{'csec'};
-    my $uname = $sheetdata->{'uname'};
-    my $udom  = $sheetdata->{'udom'};
+    my $cid   = $sheet->{'cid'};
+    my $csec  = $sheet->{'csec'};
+    my $uname = $sheet->{'uname'};
+    my $udom  = $sheet->{'udom'};
     my $result='';
     #
     my ($mapname,$id,$fn)=split(/\_\_\_/,$symb);
@@ -1569,11 +1603,11 @@
 
 # ---------------------------------------------- Update rows for course listing
 sub updateclasssheet {
-    my ($safeeval,$sheetdata) = @_;
-    my $cnum  =$sheetdata->{'cnum'};
-    my $cdom  =$sheetdata->{'cdom'};
-    my $cid   =$sheetdata->{'cid'};
-    my $chome =$sheetdata->{'chome'};
+    my ($sheet) = @_;
+    my $cnum  =$sheet->{'cnum'};
+    my $cdom  =$sheet->{'cdom'};
+    my $cid   =$sheet->{'cid'};
+    my $chome =$sheet->{'chome'};
     #
     %Section = ();
 
@@ -1605,16 +1639,18 @@
     #
     # Find discrepancies between the course row table and this
     #
-    my %f=&getformulas($safeeval);
+    my %f=&getformulas($sheet);
     my $changed=0;
     #
-    my $maxrow=0;
+    $sheet->{'maxrow'}=0;
     my %existing=();
     #
     # Now obsolete rows
     foreach (keys(%f)) {
         if ($_=~/^A(\d+)/) {
-            $maxrow=($1>$maxrow)?$1:$maxrow;
+            if ($1 > $sheet->{'maxrow'}) {
+                $sheet->{'maxrow'}= $1;
+            }
             $existing{$f{$_}}=1;
             unless ((defined($currentlist{$f{$_}})) || (!$1) ||
                     ($f{$_}=~/^(\~\~\~|\-\-\-)/)) {
@@ -1628,27 +1664,30 @@
     foreach (sort keys(%currentlist)) {
         unless ($existing{$_}) {
             $changed=1;
-            $maxrow++;
-            $f{'A'.$maxrow}=$_;
+            $sheet->{'maxrow'}++;
+            $f{'A'.$sheet->{'maxrow'}}=$_;
         }
     }
-    if ($changed) { &setformulas($safeeval,%f); }
+    if ($changed) { 
+        $sheet->{'f'} = \%f;
+        &setformulas($sheet,%f); 
+    }
     #
-    $sheetdata->{'maxrow'} = $maxrow;
-    &setrowlabels($safeeval,%currentlist);
+    $sheet->{'rowlabel'} = \%currentlist;
+    &setrowlabels($sheet);
 }
 
 # ----------------------------------- Update rows for student and assess sheets
 sub updatestudentassesssheet {
-    my ($safeeval,$sheetdata) = @_;
+    my ($sheet) = @_;
     my %bighash;
-    my $stype=$sheetdata->{'sheettype'};
-    my $uname=$sheetdata->{'uname'};
-    my $udom =$sheetdata->{'udom'};
-    my %current=();
+    my $stype=$sheet->{'sheettype'};
+    my $uname=$sheet->{'uname'};
+    my $udom =$sheet->{'udom'};
+    $sheet->{'rowlabel'} = {};
     if  ($updatedata
          {$ENV{'request.course.fn'}.'_'.$stype.'_'.$uname.'_'.$udom}) {
-        %current=split(/\_\_\_\;\_\_\_/,
+        %{$sheet->{'rowlabel'}}=split(/___;___/,
                        $updatedata{$ENV{'request.course.fn'}.
                                        '_'.$stype.'_'.$uname.'_'.$udom});
     } else {
@@ -1716,63 +1755,67 @@
         # %allassess has a list of all resource displays by symb
         #
         if ($stype eq 'assesscalc') {
-            %current=%allkeys;
+            $sheet->{'rowlabel'} = \%allkeys;
         } elsif ($stype eq 'studentcalc') {
-            %current=%allassess;
+            $sheet->{'rowlabel'} = \%allassess;
         }
         $updatedata{$ENV{'request.course.fn'}.'_'.$stype.'_'.$uname.'_'.$udom}=
-            join('___;___',%current);
+            join('___;___',%{$sheet->{'rowlabel'}});
         # Get current from cache
     }
     # Find discrepancies between the course row table and this
     #
-    my %f=&getformulas($safeeval);
+    my %f=&getformulas($sheet);
     my $changed=0;
     
-    my $maxrow=0;
+    $sheet->{'maxrow'} = 0;
     my %existing=();
     # Now obsolete rows
     foreach (keys(%f)) {
         next if ($_!~/^A(\d+)/);
-        $maxrow=($1>$maxrow)?$1:$maxrow;
-        my ($usy,$ufn)=split(/\_\_\&\&\&\_\_/,$f{$_});
+        if ($1 > $sheet->{'maxrow'}) {
+            $sheet->{'maxrow'} = $1;
+        }
+        my ($usy,$ufn)=split(/__&&&\__/,$f{$_});
         $existing{$usy}=1;
-        unless ((defined($current{$usy})) || (!$1) ||
-                ($f{$_}=~/^(\~\~\~|\-\-\-)/)){
+        unless ((exists($sheet->{'rowlabel'}->{$usy}) && 
+                 (defined($sheet->{'rowlabel'}->{$usy})) || (!$1) ||
+                ($f{$_}=~/^(\~\~\~|\-\-\-)/))){
             $f{$_}='!!! Obsolete';
             $changed=1;
         } elsif ($ufn) {
-            $current{$usy}
-            =~s/assesscalc\?usymb\=/assesscalc\?ufn\=$ufn\&usymb\=/;
+            $sheet->{'rowlabel'}->{$usy}
+                =~s/assesscalc\?usymb\=/assesscalc\?ufn\=$ufn\&usymb\=/;
         }
     }
     # New and unknown keys
-    foreach (keys(%current)) {
+    foreach (keys(%{$sheet->{'rowlabel'}})) {
         unless ($existing{$_}) {
             $changed=1;
-            $maxrow++;
-            $f{'A'.$maxrow}=$_;
+            $sheet->{'maxrow'}++;
+            $f{'A'.$sheet->{'maxrow'}}=$_;
         }
     }
-    if ($changed) { &setformulas($safeeval,%f); }
-    $sheetdata->{'maxrow'} = $maxrow;
-    &setrowlabels($safeeval,%current);
+    if ($changed) { 
+        $sheet->{'f'} = \%f;
+        &setformulas($sheet); 
+    }
+    &setrowlabels($sheet);
     #
-    undef %current;
     undef %existing;
 }
 
 # ------------------------------------------------ Load data for one assessment
 
 sub loadstudent {
-    my ($safeeval,$sheetdata)=@_;
+    my ($sheet)=@_;
     my %c=();
-    my %f=&getformulas($safeeval);
-    $cachedassess=$sheetdata->{'uname'}.':'.$sheetdata->{'udom'};
+    my %f=&getformulas($sheet);
+    $cachedassess=$sheet->{'uname'}.':'.$sheet->{'udom'};
     # Get ALL the student preformance data
-    my @tmp = &Apache::lonnet::dump($sheetdata->{'cid'},
-                                    $sheetdata->{'udom'},
-                                    $sheetdata->{'uname'},
+    my @tmp = &Apache::lonnet::dump($sheet->{'cid'},
+                                    $sheet->{'udom'},
+                                    $sheet->{'uname'},
                                     undef);
     if ($tmp[0] !~ /^error:/) {
         %cachedstores = @tmp;
@@ -1785,8 +1828,8 @@
         my $row=$1;
         next if (($f{$_}=~/^[\!\~\-]/) || ($row==0));
         my ($usy,$ufn)=split(/__&&&\__/,$f{$_});
-        @assessdata=&exportsheet($sheetdata->{'uname'},
-                                 $sheetdata->{'udom'},
+        @assessdata=&exportsheet($sheet->{'uname'},
+                                 $sheet->{'udom'},
                                  'assesscalc',$usy,$ufn);
         my $index=0;
         foreach ('A','B','C','D','E','F','G','H','I','J','K','L','M',
@@ -1807,16 +1850,18 @@
     }
     $cachedassess='';
     undef %cachedstores;
-    &setformulas($safeeval,%f);
-    &setconstants($safeeval,%c);
+    $sheet->{'f'} = \%f;
+    $sheet->{'constants'} = \%c;
+    &setformulas($sheet);
+    &setconstants($sheet);
 }
 
 # --------------------------------------------------- Load data for one student
 #
 sub loadcourse {
-    my ($safeeval,$sheetdata,$r)=@_;
+    my ($sheet,$r)=@_;
     my %c=();
-    my %f=&getformulas($safeeval);
+    my %f=&getformulas($sheet);
     my $total=0;
     foreach (keys(%f)) {
 	if ($_=~/^A(\d+)/) {
@@ -1867,8 +1912,10 @@
             }
         }
     }
-    &setformulas($safeeval,%f);
-    &setconstants($safeeval,%c);
+    $sheet->{'f'}=\%f;
+    $sheet->{'constants'}=\%c;
+    &setformulas($sheet);
+    &setconstants($sheet);
     $r->print('<script>popwin.close()</script>');
     $r->rflush(); 
 }
@@ -1876,16 +1923,16 @@
 # ------------------------------------------------ Load data for one assessment
 #
 sub loadassessment {
-    my ($safeeval,$sheetdata)=@_;
+    my ($sheet)=@_;
 
-    my $uhome = $sheetdata->{'uhome'};
-    my $uname = $sheetdata->{'uname'};
-    my $udom  = $sheetdata->{'udom'};
-    my $symb  = $sheetdata->{'usymb'};
-    my $cid   = $sheetdata->{'cid'};
-    my $cnum  = $sheetdata->{'cnum'};
-    my $cdom  = $sheetdata->{'cdom'};
-    my $chome = $sheetdata->{'chome'};
+    my $uhome = $sheet->{'uhome'};
+    my $uname = $sheet->{'uname'};
+    my $udom  = $sheet->{'udom'};
+    my $symb  = $sheet->{'usymb'};
+    my $cid   = $sheet->{'cid'};
+    my $cnum  = $sheet->{'cnum'};
+    my $cdom  = $sheet->{'cdom'};
+    my $chome = $sheet->{'chome'};
 
     my $namespace;
     unless ($namespace=$cid) { return ''; }
@@ -1970,14 +2017,14 @@
     #
     my %c=();
     if (tie(%parmhash,'GDBM_File',
-            $sheetdata->{'coursefilename'}.'_parms.db',&GDBM_READER(),0640)) {
-        my %f=&getformulas($safeeval);
+            $sheet->{'coursefilename'}.'_parms.db',&GDBM_READER(),0640)) {
+        my %f=&getformulas($sheet);
         foreach (keys(%f))  {
             next if ($_!~/^A/);
             next if  ($f{$_}=~/^[\!\~\-]/);
             if ($f{$_}=~/^parameter/) {
                 if ($thisassess{$f{$_}}) {
-                    my $val=&parmval($f{$_},$safeeval,$sheetdata);
+                    my $val=&parmval($f{$_},$sheet);
                     $c{$_}=$val;
                     $c{$f{$_}}=$val;
                 }
@@ -1992,7 +2039,8 @@
         }
         untie(%parmhash);
     }
-    &setconstants($safeeval,%c);
+    $sheet->{'constants'}=\%c;
+    &setconstants($sheet);
 }
 
 # --------------------------------------------------------- Various form fields
@@ -2025,12 +2073,12 @@
 #
 
 sub updatesheet {
-    my ($safeeval,$sheetdata)=@_;
-    my $stype=$sheetdata->{'sheettype'};
+    my ($sheet)=@_;
+    my $stype=$sheet->{'sheettype'};
     if ($stype eq 'classcalc') {
-	return &updateclasssheet($safeeval,$sheetdata);
+	return &updateclasssheet($sheet);
     } else {
-        return &updatestudentassesssheet($safeeval,$sheetdata);
+        return &updatestudentassesssheet($sheet);
     }
 }
 
@@ -2040,14 +2088,14 @@
 #
 
 sub loadrows {
-    my ($safeeval,$sheetdata,$r)=@_;
-    my $stype=$sheetdata->{'sheettype'};
+    my ($sheet,$r)=@_;
+    my $stype=$sheet->{'sheettype'};
     if ($stype eq 'classcalc') {
-	&loadcourse($safeeval,$sheetdata,$r);
+	&loadcourse($sheet,$r);
     } elsif ($stype eq 'studentcalc') {
-        &loadstudent($safeeval,$sheetdata);
+        &loadstudent($sheet);
     } else {
-        &loadassessment($safeeval,$sheetdata);
+        &loadassessment($sheet);
     }
 }
 
@@ -2135,12 +2183,12 @@
         #
         # Not cached
         #        
-        my ($thissheet,$sheetdata)=&makenewsheet($uname,$udom,$stype,$usymb);
-        &readsheet($thissheet,$sheetdata,$fn);
-        &updatesheet($thissheet,$sheetdata);
-        &loadrows($thissheet,$sheetdata);
-        &calcsheet($thissheet); 
-        @exportarr=&exportdata($thissheet);
+        my ($sheet)=&makenewsheet($uname,$udom,$stype,$usymb);
+        &readsheet($sheet,$fn);
+        &updatesheet($sheet);
+        &loadrows($sheet);
+        &calcsheet($sheet); 
+        @exportarr=&exportdata($sheet);
         #
         # Store now
         #
@@ -2154,12 +2202,12 @@
                                             &Apache::lonnet::escape($key),
                                             $ENV{'course.'.$cid.'.home'});
         } else {
-            $current=&Apache::lonnet::reply('get:'.$sheetdata->{'udom'}.':'.
-                                            $sheetdata->{'uname'}.
+            $current=&Apache::lonnet::reply('get:'.$sheet->{'udom'}.':'.
+                                            $sheet->{'uname'}.
                                             ':nohist_calculatedsheets_'.
                                             $ENV{'request.course.id'}.':'.
                                             &Apache::lonnet::escape($key),
-                                            $sheetdata->{'uhome'});
+                                            $sheet->{'uhome'});
         }
         my %currentlystored=();
         unless ($current=~/^error\:/) {
@@ -2187,14 +2235,14 @@
                                    $ENV{'course.'.$cid.'.home'});
         } else {
             &Apache::lonnet::reply('put:'.
-                                   $sheetdata->{'udom'}.':'.
-                                   $sheetdata->{'uname'}.
+                                   $sheet->{'udom'}.':'.
+                                   $sheet->{'uname'}.
                                    ':nohist_calculatedsheets_'.
                                    $ENV{'request.course.id'}.':'.
                                    &Apache::lonnet::escape($key).'='.
                                    &Apache::lonnet::escape($newstore).'&'.
                                    &Apache::lonnet::escape($key).'.time='.$now,
-                                   $sheetdata->{'uhome'});
+                                   $sheet->{'uhome'});
         }
     }
     return @exportarr;
@@ -2386,7 +2434,7 @@
     }
     # Read new sheet or modified worksheet
     $r->uri=~/\/(\w+)$/;
-    my ($sheet,$sheetdata)=&makenewsheet($aname,$adom,$1,$ENV{'form.usymb'});
+    my ($sheet)=&makenewsheet($aname,$adom,$1,$ENV{'form.usymb'});
     #
     # If a new formula had been entered, go from work copy
     if ($ENV{'form.unewfield'}) {
@@ -2394,20 +2442,19 @@
         $ENV{'form.unewformula'}=~s/\'/\"/g;
         $r->print('<p>New formula: '.$ENV{'form.unewfield'}.'='.
                   $ENV{'form.unewformula'}.'<p>');
-        $sheetdata->{'filename'} = $ENV{'form.ufn'};
-        &tmpread($sheet,$sheetdata,
-                 $ENV{'form.unewfield'},$ENV{'form.unewformula'});
+        $sheet->{'filename'} = $ENV{'form.ufn'};
+        &tmpread($sheet,$ENV{'form.unewfield'},$ENV{'form.unewformula'});
     } elsif ($ENV{'form.saveas'}) {
-        $sheetdata->{'filename'} = $ENV{'form.ufn'};
-        &tmpread($sheet,$sheetdata);
+        $sheet->{'filename'} = $ENV{'form.ufn'};
+        &tmpread($sheet);
     } else {
-        &readsheet($sheet,$sheetdata,$ENV{'form.ufn'});
+        &readsheet($sheet,$ENV{'form.ufn'});
     }
     # Print out user information
-    unless ($sheetdata->{'sheettype'} eq 'classcalc') {
-        $r->print('<p><b>User:</b> '.$sheetdata->{'uname'}.
-                  '<br><b>Domain:</b> '.$sheetdata->{'udom'});
-        $r->print('<br><b>Section/Group:</b> '.$sheetdata->{'csec'});
+    unless ($sheet->{'sheettype'} eq 'classcalc') {
+        $r->print('<p><b>User:</b> '.$sheet->{'uname'}.
+                  '<br><b>Domain:</b> '.$sheet->{'udom'});
+        $r->print('<br><b>Section/Group:</b> '.$sheet->{'csec'});
         if ($ENV{'form.usymb'}) {
             $r->print('<br><b>Assessment:</b> <tt>'.
                       $ENV{'form.usymb'}.'</tt>');
@@ -2415,10 +2462,10 @@
     }
     #
     # Check user permissions
-    if (($sheetdata->{'sheettype'} eq 'classcalc'       ) || 
-        ($sheetdata->{'uname'}     ne $ENV{'user.name'} ) ||
-        ($sheetdata->{'udom'}      ne $ENV{'user.domain'})) {
-        unless (&Apache::lonnet::allowed('vgr',$sheetdata->{'cid'})) {
+    if (($sheet->{'sheettype'} eq 'classcalc'       ) || 
+        ($sheet->{'uname'}     ne $ENV{'user.name'} ) ||
+        ($sheet->{'udom'}      ne $ENV{'user.domain'})) {
+        unless (&Apache::lonnet::allowed('vgr',$sheet->{'cid'})) {
             $r->print('<h1>Access Permission Denied</h1>'.
                       '</form></body></html>');
             return OK;
@@ -2428,15 +2475,15 @@
     $r->print('<br />'.
               '<input type="submit" name="forcerecalc" '.
               'value="Completely Recalculate Sheet"><p>');
-    if ($sheetdata->{'sheettype'} eq 'assesscalc') {
+    if ($sheet->{'sheettype'} eq 'assesscalc') {
         $r->print('<p><font size=+2>'.
                   '<a href="/adm/studentcalc?'.
-                  'uname='.$sheetdata->{'uname'}.
-                  '&udom='.$sheetdata->{'udom'}.'">'.
+                  'uname='.$sheet->{'uname'}.
+                  '&udom='.$sheet->{'udom'}.'">'.
                   'Level up: Student Sheet</a></font><p>');
     }
-    if (($sheetdata->{'sheettype'} eq 'studentcalc') && 
-        (&Apache::lonnet::allowed('vgr',$sheetdata->{'cid'}))) {
+    if (($sheet->{'sheettype'} eq 'studentcalc') && 
+        (&Apache::lonnet::allowed('vgr',$sheet->{'cid'}))) {
         $r->print ('<p><font size=+2><a href="/adm/classcalc">'.
                    'Level up: Course Sheet</a></font><p>');
     }
@@ -2449,13 +2496,13 @@
                   '<input type=text size=20 name=newfn value="'.$fname.'">'.
                   'make default: <input type=checkbox name="makedefufn"><p>');
     }
-    $r->print(&hiddenfield('ufn',$sheetdata->{'filename'}));
+    $r->print(&hiddenfield('ufn',$sheet->{'filename'}));
     # Load dialog
     if (&Apache::lonnet::allowed('opa',$ENV{'request.course.id'})) {
         $r->print('<p><input type=submit name=load value="Load ...">'.
                   '<select name="loadthissheet">'.
                   '<option name="default">Default</option>');
-        foreach (&othersheets($sheet,$sheetdata->{'sheettype'},$sheetdata)) {
+        foreach (&othersheets($sheet)) {
             $r->print('<option name="'.$_.'"');
             if ($ENV{'form.ufn'} eq $_) {
                 $r->print(' selected');
@@ -2463,34 +2510,33 @@
             $r->print('>'.$_.'</option>');
         } 
         $r->print('</select><p>');
-        if ($sheetdata->{'sheettype'} eq 'studentcalc') {
+        if ($sheet->{'sheettype'} eq 'studentcalc') {
             &setothersheets($sheet,
-                            &othersheets($sheet,'assesscalc',$sheetdata));
+                            &othersheets($sheet,'assesscalc'));
         }
     }
     # Cached sheets
     &expirationdates();
     undef %oldsheets;
     undef %loadedcaches;
-    if ($sheetdata->{'sheettype'} eq 'classcalc') {
+    if ($sheet->{'sheettype'} eq 'classcalc') {
         $r->print("Loading previously calculated student sheets ...\n");
         $r->rflush();
         &cachedcsheets();
-    } elsif ($sheetdata->{'sheettype'} eq 'studentcalc') {
+    } elsif ($sheet->{'sheettype'} eq 'studentcalc') {
         $r->print("Loading previously calculated assessment sheets ...\n");
         $r->rflush();
-        &cachedssheets($sheetdata->{'uname'},$sheetdata->{'udom'},
-                       $sheetdata->{'uhome'});
+        &cachedssheets($sheet->{'uname'},$sheet->{'udom'},$sheet->{'uhome'});
     }
     # Update sheet, load rows
     $r->print("Loaded sheet(s), updating rows ...<br>\n");
     $r->rflush();
     #
-    &updatesheet($sheet,$sheetdata);
+    &updatesheet($sheet);
     $r->print("Updated rows, loading row data ...\n");
     $r->rflush();
     #
-    &loadrows($sheet,$sheetdata,$r);
+    &loadrows($sheet,$r);
     $r->print("Loaded row data, calculating sheet ...<br>\n");
     $r->rflush();
     #
@@ -2502,19 +2548,19 @@
         if ($ENV{'form.saveas'} && ($fname=$ENV{'form.newfn'})) {
             $fname=~s/\W/\_/g;
             if ($fname eq 'default') { $fname='course_default'; }
-            $fname.='_'.$sheetdata->{'sheettype'};
-            $sheetdata->{'filename'} = $fname;
+            $fname.='_'.$sheet->{'sheettype'};
+            $sheet->{'filename'} = $fname;
             $ENV{'form.ufn'}=$fname;
             $r->print('<p>Saving spreadsheet: '.
-                      &writesheet($sheet,$ENV{'form.makedefufn'},$sheetdata).
+                      &writesheet($sheet,$ENV{'form.makedefufn'}).
                       '<p>');
         }
     }
     #
     # Write the modified worksheet
-    $r->print('<b>Current sheet:</b> '.$sheetdata->{'filename'}.'<p>');
-    &tmpwrite($sheet,$sheetdata);
-    if ($sheetdata->{'sheettype'} eq 'studentcalc') {
+    $r->print('<b>Current sheet:</b> '.$sheet->{'filename'}.'<p>');
+    &tmpwrite($sheet);
+    if ($sheet->{'sheettype'} eq 'studentcalc') {
         $r->print('<br>Show rows with empty A column: ');
     } else {
         $r->print('<br>Show empty rows: ');
@@ -2535,19 +2581,19 @@
         }
     }
     $r->print('>');
-    #
-    # CSV format checkbox (classcalc sheets only)
-    if ($sheetdata->{'sheettype'} eq 'classcalc') {
+    if ($sheet->{'sheettype'} eq 'classcalc') {
+        #
+        # CSV format checkbox (classcalc sheets only)
         $r->print(' Output CSV format: <input type="checkbox" '.
                   'name="showcsv" onClick="submit()"');
         if ($ENV{'form.showcsv'}) { $r->print(' checked'); }
         $r->print('>');
+        #
+        # Buttons to insert rows
+        $r->print('&nbsp;Student Status: '.
+                  &Apache::lonhtmlcommon::StatusOptions
+                  ($ENV{'form.Status'},'sheet'));
     }
-    #
-    # Buttons to insert rows
-    $r->print('&nbsp;Student Status: '.
-              &Apache::lonhtmlcommon::StatusOptions
-              ($ENV{'form.Status'},'sheet'));
     $r->print(<<ENDINSERTBUTTONS);
 <br>
 <input type='button' onClick='insertrow("top");' 
@@ -2556,7 +2602,7 @@
 value='Insert Row Bottom'><br>
 ENDINSERTBUTTONS
     # Print out sheet
-    &outsheet($r,$sheet,$sheetdata);
+    &outsheet($r,$sheet);
     $r->print('</form></body></html>');
     #  Done
     return OK;
@@ -2564,7 +2610,3 @@
 
 1;
 __END__
-
-
-
-

--matthew1035223177--