--- loncom/interface/Attic/lonspreadsheet.pm	2003/01/29 16:26:08	1.164
+++ loncom/interface/Attic/lonspreadsheet.pm	2003/03/11 15:00:47	1.177
@@ -1,5 +1,5 @@
 #
-# $Id: lonspreadsheet.pm,v 1.164 2003/01/29 16:26:08 matthew Exp $
+# $Id: lonspreadsheet.pm,v 1.177 2003/03/11 15:00:47 albertel Exp $
 #
 # Copyright Michigan State University Board of Trustees
 #
@@ -183,10 +183,7 @@ sub handler {
     # Header....
     #
     $r->print('<html><head><title>LON-CAPA Spreadsheet</title>');
-    my $nothing = "''";
-    if ($ENV{'browser.type'} eq 'explorer') {
-        $nothing = "'javascript:void(0);'";
-    }
+    my $nothing = &Apache::lonhtmlcommon::javascript_nothing();
 
     if ($ENV{'request.role'} !~ /^st\./) {
         $r->print(<<ENDSCRIPT);
@@ -262,7 +259,6 @@ ENDSCRIPT
     # Global directory configs
     #
     $sheet->includedir($r->dir_config('lonIncludes'));
-    $sheet->tmpdir($r->dir_config('lonDaemons').'/tmp/');
     #
     # Check user permissions
     if (($sheet->{'type'}  eq 'classcalc'       ) || 
@@ -487,6 +483,8 @@ use GDBM_File;
 use HTML::Entities();
 use HTML::TokeParser;
 use Spreadsheet::WriteExcel;
+use Time::HiRes;
+
 #
 # These global hashes are dependent on user, course and resource, 
 # and need to be initialized every time when a sheet is calculated
@@ -522,25 +520,19 @@ my %numbertimes;
 # Directories
 #
 my $includedir;
-my $tmpdir;
 
 sub includedir {
     my $self = shift;
     $includedir = shift;
 }
 
-sub tmpdir {
-    my $self = shift;
-    $tmpdir = shift;
-}
-
 my %spreadsheets;
-my %loadedcaches;
+#my %loadedcaches;
 my %courserdatas;
 my %userrdatas;
 my %defaultsheets;
 my %rowlabel_cache;
-my %oldsheets;
+#my %oldsheets;
 
 sub complete_recalc {
     my $self = shift;
@@ -607,7 +599,7 @@ sub cachedssheets {
     my ($uname,$udom) = @_;
     $uname = $uname || $self->{'uname'};
     $udom  = $udom  || $self->{'udom'};
-    if (! $Apache::lonspreadsheet::loadedcaches{$uname.'_'.$udom}) {
+    if (! exists($Apache::lonspreadsheet::loadedcaches{$uname.'_'.$udom})) {
         my @tmp = &Apache::lonnet::dump('nohist_calculatedsheets_'.
                                         $ENV{'request.course.id'},
                                         $self->{'udom'},
@@ -727,8 +719,27 @@ sub parmval {
     # second, check map parms
     my $thisparm = $parmhash{$symbparm};
     return $thisparm if (defined($thisparm));
+
     # first, check default
-    return &Apache::lonnet::metadata($fn,$rwhat.'.default');
+    $thisparm = &Apache::lonnet::metadata($fn,$rwhat.'.default');
+    return $thisparm if (defined($thisparm));
+
+    #Cascade Up
+    my $space=$what;
+    $space=~s/\.\w+$//;
+    if ($space ne '0') {
+	my @parts=split(/_/,$space);
+	my $id=pop(@parts);
+	my $part=join('_',@parts);
+	if ($part eq '') { $part='0'; }
+	my $newwhat=$rwhat;
+	$newwhat=~s/\Q$space\E/$part/;
+	my $partgeneral=&parmval($newwhat,$symb,$uname,$udom,$csec);
+	if (defined($partgeneral)) { return $partgeneral; }
+    }
+
+    #nothing defined
+    return '';
 }
 
 #
@@ -756,7 +767,7 @@ sub new {
         chome => $ENV{'course.'.$ENV{'request.course.id'}.'.home'},
         coursefilename => $ENV{'request.course.fn'},
         coursedesc => $ENV{'course.'.$ENV{'request.course.id'}.'.description'},
-        A_column       => [],
+        rows       => [],
         template_cells => [],
         };
     $self->{'uhome'} = &Apache::lonnet::homeserver($uname,$udom);
@@ -1512,7 +1523,7 @@ sub expandnamed {
 	foreach my $varname ( @vars ) {
             if ($varname=~/\D/) {
                $formula=~s/$varname/'$c{\''.$varname.'\'}'/ge;
-               $varname=~s/$var/\(\\w\+\)/g;
+               $varname=~s/$var/\([\\w:\\- ]\+\)/g;
 	       foreach (keys(%{$self->{'constants'}})) {
 		  if ($_=~/$varname/) {
 		      $values{$1}=1;
@@ -1583,12 +1594,9 @@ sub sett {
         $pattern='[A-Z]';
     }
     # Deal with the template row
-    foreach ($self->template_cells()) {
-        my ($col) = ($_=~/template\_(\w)/);
+    foreach my $col ($self->template_cells()) {
         next if ($col=~/^$pattern/);
-        foreach ($self->A_column()) {
-            my ($trow)=($_!~/A(\d+)/);
-            next if (! $trow);
+        foreach my $trow ($self->rows()) {
             # Get the name of this cell
             my $lb=$col.$trow;
             # Grab the template declaration
@@ -1746,7 +1754,6 @@ sub calcsheet {
     my $result =  $self->{'safe'}->reval('&calc();');
     %{$self->{'values'}} = %{$self->{'safe'}->varglob('sheet_values')};
 #    $self->logthis($self->get_errorlog());
-#    $self->logthis('number of values = '.(keys(%{$self->{'values'}})));
     return $result;
 }
 
@@ -1787,8 +1794,8 @@ sub clear_errorlog {
 #### Spreadsheet content retrieval/setting methods #####
 ########################################################
 ##
-## contents:  either set or get the constants.  Cannot do both.  It is just too
-## clunky to swing around big hashes when we may not need to.
+## constants:  either set or get the constants
+##
 ##
 sub constants {
     my $self=shift;
@@ -1806,8 +1813,8 @@ sub constants {
 }
     
 ##
-## formulas: either set or get the formulas.  Cannot do both.  It is just too
-## clunky to swing around big hashes when we may not need to.
+## formulas: either set or get the formulas
+##
 sub formulas {
     my $self=shift;
     my ($formulas) = @_;
@@ -1817,7 +1824,7 @@ sub formulas {
             $formulas = \%tmp;
         }
         $self->{'formulas'} = $formulas;
-        $self->{'A_column'} = [];
+        $self->{'rows'} = [];
         $self->{'template_cells'} = [];
         return;
     } else {
@@ -1831,7 +1838,6 @@ sub formulas {
 sub formulas_keys {
     my $self = shift;
     my @keys = keys(%{$self->{'formulas'}});
-#    $self->logthis('formulas keys has '.@keys.' elements');
     return keys(%{$self->{'formulas'}});
 }
 
@@ -1857,6 +1863,7 @@ sub logthis {
     &Apache::lonnet::logthis($self->{'type'}.':'.
                              $self->{'uname'}.':'.$self->{'udom'}.':'.
                              $message);
+    return;
 }
 
 ##
@@ -1895,22 +1902,36 @@ sub dump_values_to_log {
     }
     $self->logthis("--------------------------------------------------------");}
 
+##
+## Yet another debugging function
+##
+sub dump_hash_to_log {
+    my $self= shift();
+    my %tmp = @_;
+    if (@_<2) {
+        %tmp = %{$_[0]};
+    }
+    $self->logthis('---------------------------- (entries end with ":"');
+    while (my ($key,$val) = each (%tmp)) {
+        $self->logthis($key.' = '.$val.':');
+    }
+    $self->logthis('---------------------------- (entries end with ":"');
+}
+
 ################################
 ##      Helper functions      ##
 ################################
 ##
-## rebuild_stats: rebuilds the A_column and template_cells arrays
+## rebuild_stats: rebuilds the rows and template_cells arrays
 ##
 sub rebuild_stats {
     my $self = shift;
-    $self->{'A_column'}=[];
+    $self->{'rows'}=[];
     $self->{'template_cells'}=[];
     foreach my $cell($self->formulas_keys()) {
-        push(@{$self->{'A_column'}},$cell) if $cell =~ /^A\d+/;
-        push(@{$self->{'template_cells'}},$cell) if ($cell =~ /^template_/);
+        push(@{$self->{'rows'}},$1) if ($cell =~ /^A(\d+)/ && $1 != 0);
+        push(@{$self->{'template_cells'}},$1) if ($cell =~ /^template_(\w+)/);
     }
-    # $self->logthis('rebuilt A_column '.@{$self->{'A_column'}});
-    # $self->logthis('rebuilt tempate_cells '.@{$self->{'template_cells'}});
     return;
 }
 
@@ -1924,12 +1945,12 @@ sub template_cells {
 }
 
 ##
-## A_column returns a list of the names of cells defined in the A column
+## rows returns a list of the names of cells defined in the A column
 ##
-sub A_column {
+sub rows {
     my $self = shift;
-    $self->rebuild_stats() if (!@{$self->{'A_column'}});
-    return @{$self->{'A_column'}};
+    $self->rebuild_stats() if (!@{$self->{'rows'}});
+    return @{$self->{'rows'}};
 }
 
 ##
@@ -1955,7 +1976,7 @@ sub rowlabels {
         $self->{'rowlabel'}=$rowlabel;
         return;
     } else {
-        return %{$self->{'rowlabel'}} if (defined($self->{'rowlabels'}));
+        return %{$self->{'rowlabel'}} if (defined($self->{'rowlabel'}));
     }
 }
 
@@ -2545,6 +2566,7 @@ sub export_sheet_as_excel {
             }
             next if ($row_is_empty);
         }
+        $worksheet->write($rows_output,$cols_output++,$rownum);
         $worksheet->write($rows_output,$cols_output++,$label);
         if (ref($label)) {
             $cols_output = (scalar(@$label));
@@ -2669,12 +2691,11 @@ sub readsheet {
     # $fn now has a value
     $self->{'filename'} = $fn;
     # see if sheet is cached
-    my $fstring='';
-    if ($fstring=$spreadsheets{$cnum.'_'.$cdom.'_'.$stype.'_'.$fn}) {
-        my %tmp = split(/___;___/,$fstring);
+    if (exists($spreadsheets{$cnum.'_'.$cdom.'_'.$stype.'_'.$fn})) {
+        
+        my %tmp = split(/___;___/,
+                        $spreadsheets{$cnum.'_'.$cdom.'_'.$stype.'_'.$fn});
         $self->formulas(\%tmp);
-#        $self->logthis('readsheet found cached ');
-#        $self->dump_formulas_to_log();
     } else {
         # Not cached, need to read
         my %f=();
@@ -2725,8 +2746,6 @@ sub readsheet {
         # Cache and set
         $spreadsheets{$cnum.'_'.$cdom.'_'.$stype.'_'.$fn}=join('___;___',%f);  
         $self->formulas(\%f);
-#        $self->logthis('readsheet loaded ');
-#        $self->dump_formulas_to_log();
     }
 }
 
@@ -2784,7 +2803,7 @@ sub tmpwrite {
         $ENV{'user.domain'}.'_spreadsheet_'.$self->{'usymb'}.'_'.
            $self->{'filename'};
     $fn=~s/\W/\_/g;
-    $fn=$tmpdir.$fn.'.tmp';
+    $fn=$Apache::lonnet::tmpdir.$fn.'.tmp';
     my $fh;
     if ($fh=Apache::File->new('>'.$fn)) {
         my %f = $self->formulas();
@@ -2803,7 +2822,7 @@ sub tmpread {
            $ENV{'user.domain'}.'_spreadsheet_'.$self->{'usymb'}.'_'.
            $self->{'filename'};
     $fn=~s/\W/\_/g;
-    $fn=$tmpdir.$fn.'.tmp';
+    $fn=$Apache::lonnet::tmpdir.$fn.'.tmp';
     my $fh;
     my %fo=();
     my $countrows=0;
@@ -2950,14 +2969,13 @@ sub updateclasssheet {
     my %existing=();
     #
     # Now obsolete rows
-    foreach my $cell ($self->A_column()) {
-        $cell =~ /^A(\d+)/;
-        if ($1 > $self->{'maxrow'}) {
-            $self->{'maxrow'}= $1;
+    foreach my $rownum ($self->rows()) {
+        my $cell = 'A'.$rownum;
+        if ($rownum > $self->{'maxrow'}) {
+            $self->{'maxrow'}= $rownum;
         }
         $existing{$f{$cell}}=1;
-        unless ((defined($currentlist{$f{$cell}})) || (!$1) ||
-                ($f{$cell}=~/^(~~~|---)/)) {
+        if (! defined($currentlist{$f{$cell}}) && ($f{$cell}=~/^(~~~|---)/)) {
             $f{$cell}='!!! Obsolete';
             $changed=1;
         }
@@ -2988,8 +3006,9 @@ sub get_student_rowlabels {
     $self->{'rowlabel'} = {};
     #
     my $identifier =$self->{'coursefilename'}.'_'.$stype;
-    if  ($rowlabel_cache{$identifier}) {
-        %{$self->{'rowlabel'}}=split(/___;___/,$rowlabel_cache{$identifier});
+    if  (exists($rowlabel_cache{$identifier})) {
+        my %tmp = split(/___;___/,$rowlabel_cache{$identifier});
+        $self->rowlabels(\%tmp);
     } else {
         # Get the data and store it in the cache
         # Tie hash
@@ -3041,8 +3060,9 @@ sub get_assess_rowlabels {
     $self->rowlabels({});
     my $identifier =$self->{'coursefilename'}.'_'.$stype.'_'.$usymb;
     #
-    if  ($rowlabel_cache{$identifier}) {
-        $self->rowlabels(split(/___;___/,$rowlabel_cache{$identifier}));
+    if (exists($rowlabel_cache{$identifier})) {
+        my %tmp = split('___;___',$rowlabel_cache{$identifier});
+        $self->rowlabels(\%tmp);
     } else {
         # Get the data and store it in the cache
         # Tie hash
@@ -3086,9 +3106,8 @@ sub get_assess_rowlabels {
         untie(%course_db);
         # Store away the results
         $self->rowlabels(\%parameter_labels);
-        $rowlabel_cache{$identifier}=join('___;___',$self->rowlabels());
+        $rowlabel_cache{$identifier}=join('___;___',%parameter_labels);
     }
-        
 }
 
 sub updatestudentassesssheet {
@@ -3104,11 +3123,10 @@ sub updatestudentassesssheet {
     $self->{'maxrow'} = 0;
     my %existing=();
     # Now obsolete rows
-    foreach my $cell ($self->A_column()) {
+    foreach my $rownum ($self->rows()) {
+        my $cell = 'A'.$rownum;
         my $formula = $f{$cell};
-        my ($n)= ($cell =~ /A(\d+)/);
-        next if ($n eq '0');
-        $self->{'maxrow'} = $n if ($n > $self->{'maxrow'});
+        $self->{'maxrow'} = $rownum if ($rownum > $self->{'maxrow'});
         my ($usy,$ufn)=split(/__&&&\__/,$formula);
         $existing{$usy}=1;
         if ( ! exists($self->{'rowlabel'}->{$usy})  ||
@@ -3116,7 +3134,6 @@ sub updatestudentassesssheet {
              ($formula =~ /^(~~~|---)/) ||
              ($formula =~ /^\s*$/)) {
             $f{$cell}='!!! Obsolete';
-#            $self->logthis('obsoleted row '.$n);
             $changed=1;
         }
     }
@@ -3141,22 +3158,25 @@ sub loadstudent{
     my %formulas  = $self->formulas();
     $cachedassess = $self->{'uname'}.':'.$self->{'udom'};
     # Get ALL the student preformance data
-    my @tmp = &Apache::lonnet::currentdump($self->{'cid'},
-                                           $self->{'udom'},
-                                           $self->{'uname'});
+    my @tmp = &Apache::loncoursedata::get_current_state($self->{'uname'},
+                                                        $self->{'udom'},
+                                                        undef,
+                                                        $self->{'cid'});
     if ((scalar @tmp > 0) && ($tmp[0] !~ /^error:/)) {
         %cachedstores = @tmp;
     }
     undef @tmp;
-    # 
+    # debugging code
+    # $self->dump_hash_to_log(\%cachedstores);
+    #
     my @assessdata=();
-    foreach my $cell ($self->A_column()) {
+    foreach my $row ($self->rows()) {
+        my $cell = 'A'.$row;
         my $value = $formulas{$cell};
         if(defined($c) && ($c->aborted())) {
             last;
         }
-        my ($row)=($cell=~/A(\d+)/);
-        next if (($value =~ /^[!~-]/) || ($row==0));
+        next if ($value =~ /^[!~-]/);
         my ($usy,$ufn)=split(/__&&&\__/,$value);
         @assessdata=$self->exportsheet($self->{'uname'},
                                         $self->{'udom'},
@@ -3181,7 +3201,7 @@ sub loadstudent{
     $self->constants(\%constants);
 }
 
-# --------------------------------------------------- Load data for one student
+# --------------------------------------------------- Load Course Sheet
 #
 sub loadcourse {
     my $self = shift;
@@ -3191,40 +3211,30 @@ sub loadcourse {
     my %formulas=$self->formulas();
     #
     my $total=0;
-    foreach ($self->A_column()) {
-        $total++ if ($formulas{$_} !~ /^[!~-]/);
+    foreach ($self->rows()) {
+        $total++ if ($formulas{'A'.$_} !~ /^[!~-]/);
     }
-    my $now=0;
-    my $since=time;
-    $r->print(<<ENDPOP);
-<script>
-    popwin=open('','popwin','width=400,height=100');
-    popwin.document.writeln('<html><body bgcolor="#FFFFFF">'+
-      '<h3>Spreadsheet Calculation Progress</h3>'+
-      '<form name=popremain>'+
-      '<input type=text size=45 name=remaining value=Starting></form>'+
-      '</body></html>');
-    popwin.document.close();
-</script>
-ENDPOP
-    $r->rflush();
-    foreach ($self->A_column()) {
+
+    my %prog_state=&Apache::lonhtmlcommon::Create_PrgWin($r,
+	      'Spreadsheet Status','Spreadsheet Calculation Progress', $total);
+    &Apache::lonhtmlcommon::Update_PrgWin($r,\%prog_state,
+					  'Processing Course Assessment Data');
+
+    # It would be nice to load in the classlist and assessment info at this 
+    # point, before attacking the student spreadsheets.
+    foreach my $row ($self->rows()) {
         if(defined($c) && ($c->aborted())) {
             last;
         }
-        my ($row)=(/A(\d+)/);
-        next if (($formulas{$_}=~/^[\!\~\-]/)  || ($row==0));
-        my ($sname,$sdom) = split(':',$formulas{$_});
+        my $cell = 'A'.$row;
+        next if ($formulas{$cell}=~/^[\!\~\-]/);
+        my ($sname,$sdom) = split(':',$formulas{$cell});
         my $started = time;
         my @studentdata=$self->exportsheet($sname,$sdom,'studentcalc',
                                      undef,undef,$r);
         undef %userrdatas;
-        $now++;
-        $r->print('<script>popwin.document.popremain.remaining.value="'.
-                  $now.'/'.$total.': '.int((time-$since)/$now*($total-$now)).
-                  ' secs remaining '.(time-$started).' last";</script>');
-        $r->rflush(); 
-        #
+	&Apache::lonhtmlcommon::Increment_PrgWin($r,\%prog_state,
+						 'last student');
         my $index=0;
         foreach ('A','B','C','D','E','F','G','H','I','J','K','L','M',
                  'N','O','P','Q','R','S','T','U','V','W','X','Y','Z') {
@@ -3244,8 +3254,7 @@ ENDPOP
     }
     $self->formulas(\%formulas);
     $self->constants(\%constants);
-    $r->print('<script>popwin.close()</script>');
-    $r->rflush(); 
+    &Apache::lonhtmlcommon::Close_PrgWin($r,\%prog_state);
 }
 
 # ------------------------------------------------ Load data for one assessment
@@ -3342,7 +3351,8 @@ sub loadassessment {
     if (tie(%parmhash,'GDBM_File',
             $self->{'coursefilename'}.'_parms.db',&GDBM_READER(),0640)) {
         my %f=$self->formulas();
-        foreach my $cell ($self->A_column())  {
+        foreach my $row ($self->rows())  {
+            my $cell = 'A'.$row;
             my $formula = $self->formula($cell);
             next if ($formula =~/^[\!\~\-]/);
             if ($formula =~ /^parameter/) {