--- loncom/interface/Attic/lonspreadsheet.pm 2003/01/29 16:26:08 1.164
+++ loncom/interface/Attic/lonspreadsheet.pm 2003/03/20 19:10:27 1.178
@@ -1,5 +1,5 @@
#
-# $Id: lonspreadsheet.pm,v 1.164 2003/01/29 16:26:08 matthew Exp $
+# $Id: lonspreadsheet.pm,v 1.178 2003/03/20 19:10:27 matthew Exp $
#
# Copyright Michigan State University Board of Trustees
#
@@ -152,9 +152,9 @@ sub handler {
$ENV{'form.ufn'} eq 'default')) {
$ENV{'form.ufn'}='default_'.$1;
}
- if (!$ENV{'form.ufn'} || $ENV{'form.ufn'} eq 'default') {
- $ENV{'form.ufn'}='course_default_'.$sheettype;
- }
+# if (!$ENV{'form.ufn'} || $ENV{'form.ufn'} eq 'default') {
+# $ENV{'form.ufn'}='course_default_'.$sheettype;
+# }
#
# Interactive loading of specific sheet?
#
@@ -183,10 +183,7 @@ sub handler {
# Header....
#
$r->print('
LON-CAPA Spreadsheet');
- 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(<includedir($r->dir_config('lonIncludes'));
- $sheet->tmpdir($r->dir_config('lonDaemons').'/tmp/');
#
# Check user permissions
if (($sheet->{'type'} eq 'classcalc' ) ||
@@ -356,6 +352,7 @@ ENDSCRIPT
$oldsheets{'course'} ne $sheet->{'cid'}) {
undef %oldsheets;
undef %loadedcaches;
+ &Apache::lonspreadsheet::Spreadsheet::clear_package_variables();
}
$oldsheets{'course'} = $sheet->{'cid'};
#
@@ -487,6 +484,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 +521,38 @@ 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 clear_package_variables {
+ undef %courseopt;
+ undef %useropt;
+ undef %parmhash;
+ undef %Section;
+ undef %expiredates;
+ undef $cachedassess;
+ undef %cachedstores;
+ undef %starttimes;
+ undef %usedtimes;
+ undef %numbertimes;
+ undef $includedir;
+ undef %spreadsheets;
+ undef %courserdatas;
+ undef %userrdatas;
+ undef %defaultsheets;
+ undef %rowlabel_cache;
+}
sub complete_recalc {
my $self = shift;
@@ -607,7 +619,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 +739,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 '';
}
#
@@ -740,6 +771,15 @@ sub new {
#
my ($uname,$udom,$stype,$usymb)=@_;
#
+ if (! exists($Section{$uname.':'.$udom})) {
+ my $classlist = &Apache::loncoursedata::get_classlist();
+ #
+ foreach my $student (keys(%$classlist)) {
+ my ($studentDomain,$studentName,undef,undef,undef,$studentSection,
+ undef,undef) = @{$classlist->{$student}};
+ $Section{$studentName.':'.$studentDomain} = $studentSection;
+ }
+ }
my $self = {
uname => $uname,
udom => $udom,
@@ -756,7 +796,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 +1552,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 +1623,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 +1783,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 +1823,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 +1842,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 +1853,7 @@ sub formulas {
$formulas = \%tmp;
}
$self->{'formulas'} = $formulas;
- $self->{'A_column'} = [];
+ $self->{'rows'} = [];
$self->{'template_cells'} = [];
return;
} else {
@@ -1831,7 +1867,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 +1892,7 @@ sub logthis {
&Apache::lonnet::logthis($self->{'type'}.':'.
$self->{'uname'}.':'.$self->{'udom'}.':'.
$message);
+ return;
}
##
@@ -1895,22 +1931,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 +1974,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 +2005,7 @@ sub rowlabels {
$self->{'rowlabel'}=$rowlabel;
return;
} else {
- return %{$self->{'rowlabel'}} if (defined($self->{'rowlabels'}));
+ return %{$self->{'rowlabel'}} if (defined($self->{'rowlabel'}));
}
}
@@ -2545,6 +2595,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 +2720,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 +2775,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 +2832,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 +2851,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 +2998,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 +3035,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 +3089,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 +3135,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 +3152,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 +3163,6 @@ sub updatestudentassesssheet {
($formula =~ /^(~~~|---)/) ||
($formula =~ /^\s*$/)) {
$f{$cell}='!!! Obsolete';
-# $self->logthis('obsoleted row '.$n);
$changed=1;
}
}
@@ -3141,22 +3187,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 +3230,7 @@ sub loadstudent{
$self->constants(\%constants);
}
-# --------------------------------------------------- Load data for one student
+# --------------------------------------------------- Load Course Sheet
#
sub loadcourse {
my $self = shift;
@@ -3191,40 +3240,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(<
- popwin=open('','popwin','width=400,height=100');
- popwin.document.writeln(''+
- 'Spreadsheet Calculation Progress
'+
- ''+
- '');
- popwin.document.close();
-
-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('');
- $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 +3283,7 @@ ENDPOP
}
$self->formulas(\%formulas);
$self->constants(\%constants);
- $r->print('');
- $r->rflush();
+ &Apache::lonhtmlcommon::Close_PrgWin($r,\%prog_state);
}
# ------------------------------------------------ Load data for one assessment
@@ -3342,7 +3380,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/) {