--- loncom/interface/Attic/lonspreadsheet.pm 2002/11/12 22:44:28 1.139
+++ loncom/interface/Attic/lonspreadsheet.pm 2002/12/09 16:06:56 1.157
@@ -1,5 +1,5 @@
#
-# $Id: lonspreadsheet.pm,v 1.139 2002/11/12 22:44:28 matthew Exp $
+# $Id: lonspreadsheet.pm,v 1.157 2002/12/09 16:06:56 matthew Exp $
#
# Copyright Michigan State University Board of Trustees
#
@@ -53,16 +53,17 @@ built-in functions.
package Apache::lonspreadsheet;
use strict;
+use Apache::Constants qw(:common :http);
+use Apache::lonnet;
+use Apache::lonhtmlcommon;
+use Apache::loncoursedata;
+use Apache::File();
use Safe;
use Safe::Hole;
use Opcode;
-use Apache::lonnet;
-use Apache::Constants qw(:common :http);
use GDBM_File;
+use HTML::Entities();
use HTML::TokeParser;
-use Apache::lonhtmlcommon;
-use Apache::loncoursedata;
-use Apache::File();
use Spreadsheet::WriteExcel;
#
@@ -965,11 +966,9 @@ sub templaterow {
'N','O','P','Q','R','S','T','U','V','W','X','Y','Z',
'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') {
- my $fm=$sheet->{'f'}->{'template_'.$_};
- $fm=~s/[\'\"]/\&\#34;/g;
push(@cols,{ name => 'template_'.$_,
- formula => $fm,
- value => $fm });
+ formula => $sheet->{'f'}->{'template_'.$_},
+ value => $sheet->{'f'}->{'template_'.$_} });
}
return ($rowlabel,@cols);
}
@@ -982,7 +981,11 @@ sub outrowassess {
if ($n) {
my ($usy,$ufn)=split(/__&&&\__/,$sheet->{'f'}->{'A'.$n});
if (exists($sheet->{'rowlabel'}->{$usy})) {
- $rowlabel = $sheet->{'rowlabel'}->{$usy};
+ # This is dumb, but we need the information when we output
+ # the html version of the studentcalc spreadsheet for the
+ # links to the assesscalc sheets.
+ $rowlabel = $sheet->{'rowlabel'}->{$usy}.':'.
+ &Apache::lonnet::escape($ufn);
} else {
$rowlabel = '';
}
@@ -993,10 +996,8 @@ sub outrowassess {
'N','O','P','Q','R','S','T','U','V','W','X','Y','Z',
'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') {
- my $fm=$sheet->{'f'}->{$_.$n};
- $fm=~s/[\'\"]/\&\#34;/g;
push(@cols,{ name => $_.$n,
- formula => $fm,
+ formula => $sheet->{'f'}->{$_.$n},
value => $sheet->{'values'}->{$_.$n}});
}
return ($rowlabel,@cols);
@@ -1019,10 +1020,8 @@ sub outrow {
'N','O','P','Q','R','S','T','U','V','W','X','Y','Z',
'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') {
- my $fm=$sheet->{'f'}->{$_.$n};
- $fm=~s/[\'\"]/\&\#34;/g;
push(@cols,{ name => $_.$n,
- formula => $fm,
+ formula => $sheet->{'f'}->{$_.$n},
value => $sheet->{'values'}->{$_.$n}});
}
return ($rowlabel,@cols);
@@ -1149,7 +1148,7 @@ sub exportdata {
sub update_student_sheet{
- my $sheet = shift;
+ my ($sheet,$r,$c) = @_;
# Load in the studentcalc sheet
&readsheet($sheet,'default_studentcalc');
# Determine the structure (contained assessments, etc) of the sheet
@@ -1157,7 +1156,7 @@ sub update_student_sheet{
# Load in the cached sheets for this student
&cachedssheets($sheet);
# Load in the (possibly cached) data from the assessment sheets
- &loadstudent($sheet);
+ &loadstudent($sheet,$r,$c);
# Compute the sheet
&calcsheet($sheet);
}
@@ -1186,17 +1185,49 @@ sub get_row {
########################################################################
sub sort_indicies {
my $sheet = shift;
- #
- # Sort the rows in some manner
- #
- my @sortby=();
my @sortidx=();
- # Skip row 0
- for (my $row=1;$row<=$sheet->{'maxrow'};$row++) {
- push (@sortby, $sheet->{'safe'}->reval('$f{"A'.$row.'"}'));
- push (@sortidx, $row);
+ #
+ if ($sheet->{'sheettype'} eq 'classcalc') {
+ my @sortby=(undef);
+ # Skip row 0
+ for (my $row=1;$row<=$sheet->{'maxrow'};$row++) {
+ my (undef,$sname,$sdom,$fullname,$section,$id) =
+ split(':',$sheet->{'rowlabel'}->{$sheet->{'f'}->{'A'.$row}});
+ push (@sortby, lc($fullname));
+ push (@sortidx, $row);
+ }
+ @sortidx = sort { $sortby[$a] cmp $sortby[$b]; } @sortidx;
+ } elsif ($sheet->{'sheettype'} eq 'studentcalc') {
+ my @sortby1=(undef);
+ my @sortby2=(undef);
+ # Skip row 0
+ for (my $row=1;$row<=$sheet->{'maxrow'};$row++) {
+ my ($key,undef) = split(/__&&&\__/,$sheet->{'f'}->{'A'.$row});
+ my $rowlabel = $sheet->{'rowlabel'}->{$key};
+ my (undef,$symb,$mapid,$resid,$title,$ufn) =
+ split(':',$rowlabel);
+ $ufn = &Apache::lonnet::unescape($ufn);
+ $symb = &Apache::lonnet::unescape($symb);
+ $title = &Apache::lonnet::unescape($title);
+ my ($sequence) = ($symb =~ /\/([^\/]*\.sequence)/);
+ if ($sequence eq '') {
+ $sequence = $symb;
+ }
+ push (@sortby1, $sequence);
+ push (@sortby2, $title);
+ push (@sortidx, $row);
+ }
+ @sortidx = sort { $sortby1[$a] cmp $sortby1[$b] ||
+ $sortby2[$a] cmp $sortby2[$b] } @sortidx;
+ } else {
+ my @sortby=(undef);
+ # Skip row 0
+ for (my $row=1;$row<=$sheet->{'maxrow'};$row++) {
+ push (@sortby, $sheet->{'safe'}->reval('$f{"A'.$row.'"}'));
+ push (@sortidx, $row);
+ }
+ @sortidx = sort { $sortby[$a] cmp $sortby[$b]; } @sortidx;
}
- @sortidx=sort { lc($sortby[$a]) cmp lc($sortby[$b]); } @sortidx;
return @sortidx;
}
@@ -1225,25 +1256,35 @@ sub html_editable_cell {
if ($formula ne '') {
$value = 'undefined value ';
}
- }
- if ($value =~ /^\s*$/ ) {
+ } elsif ($value =~ /^\s*$/ ) {
$value = '# ';
+ } else {
+ $value = &HTML::Entities::encode($value);
}
+ # Make the formula safe for outputting
+ $formula =~ s/\'/\"/g;
+ # The formula will be parsed by the browser *twice* before being
+ # displayed to the user for editing.
+ $formula = &HTML::Entities::encode(&HTML::Entities::encode($formula));
+ # Escape newlines so they make it into the edit window
$formula =~ s/\n/\\n/gs;
- $result .= ''.$value.' ';
+ # Glue everything together
+ $result .= "".$value." ";
return $result;
}
sub html_uneditable_cell {
my ($cell,$bgcolor) = @_;
my $value = (defined($cell) ? $cell->{'value'} : '');
+ $value = &HTML::Entities::encode($value);
return ' '.$value.' ';
}
sub outsheet_html {
my ($sheet,$r) = @_;
my ($num_uneditable,$realm,$row_type);
+ my $requester_is_student = ($ENV{'request.role'} =~ /^st\./);
if ($sheet->{'sheettype'} eq 'assesscalc') {
$num_uneditable = 1;
$realm = 'Assessment';
@@ -1288,34 +1329,39 @@ END
####################################
# Print out template row
####################################
- my ($rowlabel,@rowdata) = &get_row($sheet,'-');
- my $row_html = '
'.&format_html_rowlabel($rowlabel).' ';
- my $num_cols_output = 0;
- foreach my $cell (@rowdata) {
- if ($num_cols_output++ < $num_uneditable) {
- $row_html .= '';
- $row_html .= &html_uneditable_cell($cell,'#FFDDDD');
- } else {
- $row_html .= ' ';
- $row_html .= &html_editable_cell($cell,'#E0FFDD');
+ my ($num_cols_output,$row_html,$rowlabel,@rowdata);
+
+ if (! $requester_is_student) {
+ ($rowlabel,@rowdata) = &get_row($sheet,'-');
+ $row_html = ' '.&format_html_rowlabel($sheet,$rowlabel).' ';
+ $num_cols_output = 0;
+ foreach my $cell (@rowdata) {
+ if ($requester_is_student ||
+ $num_cols_output++ < $num_uneditable) {
+ $row_html .= '';
+ $row_html .= &html_uneditable_cell($cell,'#FFDDDD');
+ } else {
+ $row_html .= ' ';
+ $row_html .= &html_editable_cell($cell,'#E0FFDD');
+ }
+ $row_html .= ' ';
}
- $row_html .= '';
+ $row_html.= " \n";
+ $r->print($row_html);
}
- $row_html.= "\n";
- $r->print($row_html);
####################################
# Print out summary/export row
####################################
- my ($rowlabel,@rowdata) = &get_row($sheet,'0');
- $row_html = ''.&format_html_rowlabel($rowlabel).' ';
+ ($rowlabel,@rowdata) = &get_row($sheet,'0');
+ $row_html = ''.&format_html_rowlabel($sheet,'Summary').' ';
$num_cols_output = 0;
foreach my $cell (@rowdata) {
- if ($num_cols_output++ < 26) {
+ if ($num_cols_output++ < 26 && ! $requester_is_student) {
$row_html .= '';
$row_html .= &html_editable_cell($cell,'#CCCCFF');
} else {
$row_html .= ' ';
- $row_html .= &html_uneditable_cell(undef,'#CCCCFF');
+ $row_html .= &html_uneditable_cell($cell,'#CCCCFF');
}
$row_html .= ' ';
}
@@ -1332,6 +1378,20 @@ END
foreach my $rownum (@Rows) {
my ($rowlabel,@rowdata) = &get_row($sheet,$rownum);
next if ($rowlabel =~ /^\s*$/);
+ next if (($sheet->{'sheettype'} eq 'assesscalc') &&
+ (! $ENV{'form.showall'}) &&
+ ($rowdata[0]->{'value'} =~ /^\s*$/));
+ if (! $ENV{'form.showall'} &&
+ $sheet->{'sheettype'} =~ /^(studentcalc|classcalc)$/) {
+ my $row_is_empty = 1;
+ foreach my $cell (@rowdata) {
+ if ($cell->{'value'} !~ /^\s*$/) {
+ $row_is_empty = 0;
+ last;
+ }
+ }
+ next if ($row_is_empty);
+ }
#
my $defaultbg='#E0FF';
#
@@ -1339,25 +1399,28 @@ END
'';
#
if ($sheet->{'sheettype'} eq 'classcalc') {
- $row_html.=''.&format_html_rowlabel($rowlabel).' ';
+ $row_html.=''.&format_html_rowlabel($sheet,$rowlabel).' ';
# Output links for each student?
- # Nope, that is already done for us in format_html_rowlabel (for now)
+ # Nope, that is already done for us in format_html_rowlabel
+ # (for now)
} elsif ($sheet->{'sheettype'} eq 'studentcalc') {
- $row_html.=''.&format_html_rowlabel($rowlabel);
+ my $ufn = (split(/:/,$rowlabel))[5];
+ $row_html.=' '.&format_html_rowlabel($sheet,$rowlabel);
$row_html.= ' '.
''.
'Default ';
+
foreach (@{$sheet->{'othersheets'}}) {
$row_html.=''.$_.' ';
}
$row_html.=' ';
} elsif ($sheet->{'sheettype'} eq 'assesscalc') {
- $row_html.=''.&format_html_rowlabel($rowlabel).' ';
+ $row_html.=''.&format_html_rowlabel($sheet,$rowlabel).' ';
}
#
my $shown_cells = 0;
@@ -1375,7 +1438,7 @@ END
$bgcolor='#FFDDDD' if ($shown_cells < $num_uneditable);
#
$row_html.='';
- if ($shown_cells < $num_uneditable) {
+ if ($requester_is_student || $shown_cells < $num_uneditable) {
$row_html .= &html_uneditable_cell($cell,$bgcolor);
} else {
$row_html .= &html_editable_cell($cell,$bgcolor);
@@ -1427,7 +1490,7 @@ sub outsheet_csv {
foreach my $rownum (@Rows) {
my ($rowlabel,@rowdata) = &get_row($sheet,$rownum);
next if ($rowlabel =~ /^\s*$/);
- push (@Values,&format_csv_rowlabel($rowlabel));
+ push (@Values,&format_csv_rowlabel($sheet,$rowlabel));
foreach my $cell (@rowdata) {
push (@Values,'"'.$cell->{'value'}.'"');
}
@@ -1488,15 +1551,14 @@ A link to the spreadsheet will be availa
END
$r->rflush();
my $starttime = time;
- foreach (keys(%f)) {
- next if ($_!~/^A(\d+)/ || $1 == 0 || ($f{$_}=~/^[!~-]/));
+ foreach my $rownum (&sort_indicies($sheet)) {
$count++;
- my ($sname,$sdom) = split(':',$f{$_});
+ my ($sname,$sdom) = split(':',$f{'A'.$rownum});
my $student_excel_worksheet=$workbook->addworksheet($sname.'@'.$sdom);
# Create a new spreadsheet
my $studentsheet = &makenewsheet($sname,$sdom,'studentcalc',undef);
# Read in the spreadsheet definition
- &update_student_sheet($studentsheet);
+ &update_student_sheet($studentsheet,$r,$c);
# Stuff the sheet into excel
&export_sheet_as_excel($studentsheet,$student_excel_worksheet);
my $totaltime = int((time - $starttime) / $count * $sheet->{'maxrow'});
@@ -1597,7 +1659,7 @@ sub export_sheet_as_excel {
# Write the summary/export row #
####################################
my ($rowlabel,@rowdata) = &get_row($sheet,'0');
- my $label = &format_excel_rowlabel($rowlabel);
+ my $label = &format_excel_rowlabel($sheet,$rowlabel);
$cols_output = 0;
$worksheet->write($rows_output,$cols_output++,$label);
foreach my $cell (@rowdata) {
@@ -1612,9 +1674,20 @@ sub export_sheet_as_excel {
# Loop through the rows and output them one at a time
foreach my $rownum (@Rows) {
my ($rowlabel,@rowdata) = &get_row($sheet,$rownum);
- next if ($rowlabel =~ /^\s*$/);
+ next if ($rowlabel =~ /^[\s]*$/);
$cols_output = 0;
- my $label = &format_excel_rowlabel($rowlabel);
+ my $label = &format_excel_rowlabel($sheet,$rowlabel);
+ if ( ! $ENV{'form.showall'} &&
+ $sheet->{'sheettype'} =~ /^(studentcalc|classcalc)$/) {
+ my $row_is_empty = 1;
+ foreach my $cell (@rowdata) {
+ if ($cell->{'value'} !~ /^\s*$/) {
+ $row_is_empty = 0;
+ last;
+ }
+ }
+ next if ($row_is_empty);
+ }
$worksheet->write($rows_output,$cols_output++,$label);
if (ref($label)) {
$cols_output = (scalar(@$label));
@@ -1641,7 +1714,7 @@ sub outsheet_xml {
## Outsheet - calls other outsheet_* functions
##
sub outsheet {
- my ($r,$sheet)=@_;
+ my ($sheet,$r)=@_;
if (! exists($ENV{'form.output'})) {
$ENV{'form.output'} = 'HTML';
}
@@ -1753,7 +1826,8 @@ sub readsheet {
if ($fh=Apache::File->new($includedir.'/'.$dfn)) {
$sheetxml=join('',<$fh>);
} else {
- $sheetxml='"Error" ';
+ # $sheetxml='"Error" ';
+ $sheetxml=' ';
}
%f=%{&parse_sheet(\$sheetxml)};
} elsif($fn=~/\/*\.spreadsheet$/) {
@@ -1765,13 +1839,27 @@ sub readsheet {
}
%f=%{&parse_sheet(\$sheetxml)};
} else {
- my $sheet='';
my %tmphash = &Apache::lonnet::dump($fn,$cdom,$cnum);
my ($tmp) = keys(%tmphash);
- unless ($tmp =~ /^(con_lost|error|no_such_host)/i) {
+ if ($tmp !~ /^(con_lost|error|no_such_host)/i) {
foreach (keys(%tmphash)) {
$f{$_}=$tmphash{$_};
}
+ } else {
+ # Unable to grab the specified spreadsheet,
+ # so we get the default ones instead.
+ $fn = 'default_'.$stype;
+ $sheet->{'filename'} = $fn;
+ my $dfn = $fn;
+ $dfn =~ s/\_/\./g;
+ my $sheetxml;
+ if (my $fh=Apache::File->new($includedir.'/'.$dfn)) {
+ $sheetxml = join('',<$fh>);
+ } else {
+ $sheetxml=''.
+ '"Unable to load spreadsheet" ';
+ }
+ %f=%{&parse_sheet(\$sheetxml)};
}
}
# Cache and set
@@ -1845,9 +1933,16 @@ sub writesheet {
$cdom,$cnum);
if ($reply eq 'ok') {
if ($makedef) {
- return &Apache::lonnet::put('environment',
- {'spreadsheet_default_'.$stype => $fn },
- $cdom,$cnum);
+ $reply = &Apache::lonnet::put('environment',
+ {'spreadsheet_default_'.$stype => $fn },
+ $cdom,$cnum);
+ if ($reply eq 'ok' &&
+ ($sheet->{'sheettype'} eq 'studentcalc' ||
+ $sheet->{'sheettype'} eq 'assesscalc')) {
+ # Expire the spreadsheets of the other students.
+ &Apache::lonnet::expirespread('','','studentcalc','');
+ }
+ return $reply;
}
return $reply;
}
@@ -1870,7 +1965,10 @@ sub tmpwrite {
$fn=$tmpdir.$fn.'.tmp';
my $fh;
if ($fh=Apache::File->new('>'.$fn)) {
- print $fh join("\n",&getformulas($sheet));
+ my %f = &getformulas($sheet);
+ while( my ($cell,$formula) = each(%f)) {
+ print $fh &Apache::lonnet::escape($cell)."=".&Apache::lonnet::escape($formula)."\n";
+ }
}
}
@@ -1886,32 +1984,36 @@ sub tmpread {
my %fo=();
my $countrows=0;
if ($fh=Apache::File->new($fn)) {
- my $name;
- while ($name=<$fh>) {
- chomp($name);
- my $value=<$fh>;
- chomp($value);
- $fo{$name}=$value;
- if ($name=~/^A(\d+)$/) {
- if ($1>$countrows) {
- $countrows=$1;
- }
- }
- }
- }
+ while (<$fh>) {
+ chomp;
+ my ($cell,$formula) = split(/=/);
+ $cell = &Apache::lonnet::unescape($cell);
+ $formula = &Apache::lonnet::unescape($formula);
+ $fo{$cell} = $formula;
+ }
+ }
+# chomp($value);
+# $fo{$name}=$value;
+# if ($name=~/^A(\d+)$/) {
+# if ($1>$countrows) {
+# $countrows=$1;
+# }
+# }
+# }
+# }
if ($nform eq 'changesheet') {
$fo{'A'.$nfield}=(split(/__&&&\__/,$fo{'A'.$nfield}))[0];
unless ($ENV{'form.sel_'.$nfield} eq 'Default') {
$fo{'A'.$nfield}.='__&&&__'.$ENV{'form.sel_'.$nfield};
}
- } elsif ($nfield eq 'insertrow') {
- $countrows++;
- my $newrow=substr('000000'.$countrows,-7);
- if ($nform eq 'top') {
- $fo{'A'.$countrows}='--- '.$newrow;
- } else {
- $fo{'A'.$countrows}='~~~ '.$newrow;
- }
+# } elsif ($nfield eq 'insertrow') {
+# $countrows++;
+# my $newrow=substr('000000'.$countrows,-7);
+# if ($nform eq 'top') {
+# $fo{'A'.$countrows}='--- '.$newrow;
+# } else {
+# $fo{'A'.$countrows}='~~~ '.$newrow;
+# }
} else {
if ($nfield) { $fo{$nfield}=$nform; }
}
@@ -1999,18 +2101,26 @@ sub parmval {
## Row label formatting routines ##
##################################################################
sub format_html_rowlabel {
+ my $sheet = shift;
my $rowlabel = shift;
return '' if ($rowlabel eq '');
my ($type,$labeldata) = split(':',$rowlabel,2);
my $result = '';
if ($type eq 'symb') {
- my ($symb,$uname,$udom,$mapid,$resid,$title) = split(':',$labeldata);
- $symb = &Apache::lonnet::unescape($symb);
+ my ($symb,$mapid,$resid,$title,$ufn) = split(':',$labeldata);
+ $ufn = 'default' if (!defined($ufn) || $ufn eq '');
+ $ufn = &Apache::lonnet::unescape($ufn);
+ $symb = &Apache::lonnet::unescape($symb);
+ $title = &Apache::lonnet::unescape($title);
$result = ''.$title.' ';
+ '&uname='.$sheet->{'uname'}.'&udom='.$sheet->{'udom'}.
+ '&ufn='.$ufn.
+ '&mapid='.$mapid.'&resid='.$resid.'">'.$title.'';
} elsif ($type eq 'student') {
my ($sname,$sdom,$fullname,$section,$id) = split(':',$labeldata);
+ if ($fullname =~ /^\s*$/) {
+ $fullname = $sname.'@'.$sdom;
+ }
$result ='';
$result.=$section.' '.$id." ".$fullname.' ';
@@ -2023,13 +2133,16 @@ sub format_html_rowlabel {
}
sub format_csv_rowlabel {
+ my $sheet = shift;
my $rowlabel = shift;
return '' if ($rowlabel eq '');
my ($type,$labeldata) = split(':',$rowlabel,2);
my $result = '';
if ($type eq 'symb') {
- my ($symb,$uname,$udom,$mapid,$resid,$title) = split(':',$labeldata);
- $symb = &Apache::lonnet::unescape($symb);
+ my ($symb,$mapid,$resid,$title,$ufn) = split(':',$labeldata);
+ $ufn = &Apache::lonnet::unescape($ufn);
+ $symb = &Apache::lonnet::unescape($symb);
+ $title = &Apache::lonnet::unescape($title);
$result = $title;
} elsif ($type eq 'student') {
my ($sname,$sdom,$fullname,$section,$id) = split(':',$labeldata);
@@ -2044,13 +2157,16 @@ sub format_csv_rowlabel {
}
sub format_excel_rowlabel {
+ my $sheet = shift;
my $rowlabel = shift;
return '' if ($rowlabel eq '');
my ($type,$labeldata) = split(':',$rowlabel,2);
my $result = '';
if ($type eq 'symb') {
- my ($symb,$uname,$udom,$mapid,$resid,$title) = split(':',$labeldata);
- $symb = &Apache::lonnet::unescape($symb);
+ my ($symb,$mapid,$resid,$title,$ufn) = split(':',$labeldata);
+ $ufn = &Apache::lonnet::unescape($ufn);
+ $symb = &Apache::lonnet::unescape($symb);
+ $title = &Apache::lonnet::unescape($title);
$result = $title;
} elsif ($type eq 'student') {
my ($sname,$sdom,$fullname,$section,$id) = split(':',$labeldata);
@@ -2158,10 +2274,11 @@ sub get_student_rowlabels {
return 'Could not access course data';
}
#
- my %assesslist;
+ my %assesslist = ();
foreach ('Feedback','Evaluation','Tutoring','Discussion') {
my $symb = '_'.lc($_);
- $assesslist{$symb} = join(':',('symb',$symb,$uname,$udom,0,0,$_));
+ $assesslist{$symb} = join(':',('symb',$symb,0,0,
+ &Apache::lonnet::escape($_)));
}
#
while (my ($key,$srcf) = each(%course_db)) {
@@ -2173,9 +2290,9 @@ sub get_student_rowlabels {
my $symb=
&Apache::lonnet::declutter($course_db{'map_id_'.$mapid}).
'___'.$resid.'___'.&Apache::lonnet::declutter($srcf);
- $assesslist{$symb}='symb:'.&Apache::lonnet::escape($symb).':'
- .$uname.':'.$udom.':'.$mapid.':'.$resid.':'.
- $course_db{'title_'.$id};
+ $assesslist{$symb} ='symb:'.&Apache::lonnet::escape($symb).':'
+ .$mapid.':'.$resid.':'.
+ &Apache::lonnet::escape($course_db{'title_'.$id});
}
}
untie(%course_db);
@@ -2263,7 +2380,8 @@ sub updatestudentassesssheet {
$sheet->{'maxrow'} = 0;
my %existing=();
# Now obsolete rows
- while (my ($cell, $formula) = each (%f)) {
+ foreach my $cell (keys(%f)) {
+ my $formula = $f{$cell};
next if ($cell !~ /^A(\d+)/);
$sheet->{'maxrow'} = $1 if ($1 > $sheet->{'maxrow'});
my ($usy,$ufn)=split(/__&&&\__/,$formula);
@@ -2273,10 +2391,6 @@ sub updatestudentassesssheet {
($formula =~ /^(~~~|---)/) )) {
$f{$_}='!!! Obsolete';
$changed=1;
- } elsif ($ufn) {
- # I do not think this works any more
- $sheet->{'rowlabel'}->{$usy}
- =~s/assesscalc\?usymb\=/assesscalc\?ufn\=$ufn&\usymb\=/;
}
}
# New and unknown keys
@@ -2296,9 +2410,9 @@ sub updatestudentassesssheet {
# ------------------------------------------------ Load data for one assessment
sub loadstudent{
- my ($sheet)=@_;
- my %c=();
- my %f=&getformulas($sheet);
+ my ($sheet,$r,$c)=@_;
+ my %constants=();
+ my %formulas=&getformulas($sheet);
$cachedassess=$sheet->{'uname'}.':'.$sheet->{'udom'};
# Get ALL the student preformance data
my @tmp = &Apache::lonnet::dump($sheet->{'cid'},
@@ -2311,50 +2425,51 @@ sub loadstudent{
undef @tmp;
#
my @assessdata=();
- while (my ($cell,$value) = each (%f)) {
+ foreach my $cell (keys(%formulas)) {
+ my $value = $formulas{$cell};
+ if(defined($c) && ($c->aborted())) {
+ last;
+ }
next if ($cell !~ /^A(\d+)/);
my $row=$1;
next if (($value =~ /^[!~-]/) || ($row==0));
my ($usy,$ufn)=split(/__&&&\__/,$value);
@assessdata=&exportsheet($sheet,$sheet->{'uname'},
$sheet->{'udom'},
- 'assesscalc',$usy,$ufn);
+ 'assesscalc',$usy,$ufn,$r);
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') {
+ foreach my $col ('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') {
if (defined($assessdata[$index])) {
- my $col=$_;
if ($assessdata[$index]=~/\D/) {
- $c{$col.$row}="'".$assessdata[$index]."'";
+ $constants{$col.$row}="'".$assessdata[$index]."'";
} else {
- $c{$col.$row}=$assessdata[$index];
- }
- unless ($col eq 'A') {
- $f{$col.$row}='import';
+ $constants{$col.$row}=$assessdata[$index];
}
+ $formulas{$col.$row}='import' if ($col ne 'A');
}
$index++;
}
}
$cachedassess='';
undef %cachedstores;
- $sheet->{'f'} = \%f;
+ $sheet->{'f'} = \%formulas;
&setformulas($sheet);
- &setconstants($sheet,\%c);
+ &setconstants($sheet,\%constants);
}
# --------------------------------------------------- Load data for one student
#
sub loadcourse {
- my ($sheet,$r)=@_;
+ my ($sheet,$r,$c)=@_;
#
- my %c=();
- my %f=&getformulas($sheet);
+ my %constants=();
+ my %formulas=&getformulas($sheet);
#
my $total=0;
- foreach (keys(%f)) {
+ foreach (keys(%formulas)) {
if ($_=~/^A(\d+)/) {
- unless ($f{$_}=~/^[\!\~\-]/) { $total++; }
+ unless ($formulas{$_}=~/^[\!\~\-]/) { $total++; }
}
}
my $now=0;
@@ -2371,12 +2486,16 @@ sub loadcourse {
ENDPOP
$r->rflush();
- foreach (keys(%f)) {
+ foreach (keys(%formulas)) {
+ if(defined($c) && ($c->aborted())) {
+ last;
+ }
next if ($_!~/^A(\d+)/);
my $row=$1;
- next if (($f{$_}=~/^[\!\~\-]/) || ($row==0));
- my ($sname,$sdom) = split(':',$f{$_});
- my @studentdata=&exportsheet($sheet,$sname,$sdom,'studentcalc');
+ next if (($formulas{$_}=~/^[\!\~\-]/) || ($row==0));
+ my ($sname,$sdom) = split(':',$formulas{$_});
+ my @studentdata=&exportsheet($sheet,$sname,$sdom,'studentcalc',
+ undef,undef,$r);
undef %userrdatas;
$now++;
$r->print('');
$r->rflush();
}
@@ -2411,7 +2530,7 @@ ENDPOP
# ------------------------------------------------ Load data for one assessment
#
sub loadassessment {
- my ($sheet)=@_;
+ my ($sheet,$r,$c)=@_;
my $uhome = $sheet->{'uhome'};
my $uname = $sheet->{'uname'};
@@ -2575,13 +2694,14 @@ sub updatesheet {
sub loadrows {
my ($sheet,$r)=@_;
+ my $c = $r->connection;
my $stype=$sheet->{'sheettype'};
if ($stype eq 'classcalc') {
- &loadcourse($sheet,$r);
+ &loadcourse($sheet,$r,$c);
} elsif ($stype eq 'studentcalc') {
- &loadstudent($sheet);
+ &loadstudent($sheet,$r,$c);
} else {
- &loadassessment($sheet);
+ &loadassessment($sheet,$r,$c);
}
}
@@ -2589,7 +2709,11 @@ sub loadrows {
sub checkthis {
my ($keyname,$time)=@_;
- return ($time<$expiredates{$keyname});
+ if (! exists($expiredates{$keyname})) {
+ return 0;
+ } else {
+ return ($time<$expiredates{$keyname});
+ }
}
sub forcedrecalc {
@@ -2607,7 +2731,7 @@ sub forcedrecalc {
&checkthis($uname.':'.$udom.':assesscalc:'.$map,$time) ||
&checkthis($uname.':'.$udom.':assesscalc:'.$usymb,$time)) {
return 1;
- }
+ }
} else {
if (&checkthis('::studentcalc:',$time) ||
&checkthis($uname.':'.$udom.':studentcalc:',$time)) {
@@ -2622,11 +2746,13 @@ sub forcedrecalc {
# returns the export row for a spreadsheet.
#
sub exportsheet {
- my ($sheet,$uname,$udom,$stype,$usymb,$fn)=@_;
+ my ($sheet,$uname,$udom,$stype,$usymb,$fn,$r)=@_;
+ my $flag = 0;
$uname = $uname || $sheet->{'uname'};
$udom = $udom || $sheet->{'udom'};
$stype = $stype || $sheet->{'sheettype'};
my @exportarr=();
+ # This handles the assessment sheets for '_feedback', etc
if (defined($usymb) && ($usymb=~/^\_(\w+)/) &&
(!defined($fn) || $fn eq '')) {
$fn='default_'.$1;
@@ -2676,7 +2802,7 @@ sub exportsheet {
my ($newsheet)=&makenewsheet($uname,$udom,$stype,$usymb);
&readsheet($newsheet,$fn);
&updatesheet($newsheet);
- &loadrows($newsheet);
+ &loadrows($newsheet,$r);
&calcsheet($newsheet);
@exportarr=&exportdata($newsheet);
##
@@ -2691,14 +2817,24 @@ sub exportsheet {
[$key],
$sheet->{'cdom'},$sheet->{'cnum'});
if ($tmp[0]!~/^error/) {
- %currentlystored = @tmp;
+ # We only got one key, so we will access it directly.
+ foreach (split('___&___',$tmp[1])) {
+ my ($key,$value) = split('___=___',$_);
+ $key = '' if (! defined($key));
+ $currentlystored{$key} = $value;
+ }
}
} else {
my @tmp = &Apache::lonnet::get('nohist_calculatedsheets_'.
$sheet->{'cid'},[$key],
$sheet->{'udom'},$sheet->{'uname'});
if ($tmp[0]!~/^error/) {
- %currentlystored = @tmp;
+ # We only got one key, so we will access it directly.
+ foreach (split('___&___',$tmp[1])) {
+ my ($key,$value) = split('___=___',$_);
+ $key = '' if (! defined($key));
+ $currentlystored{$key} = $value;
+ }
}
}
#
@@ -2717,17 +2853,19 @@ sub exportsheet {
#
# Store away the new value
#
+ my $timekey = $key.'.time';
if ($stype eq 'studentcalc') {
- &Apache::lonnet::put('nohist_calculatedsheets',
- { $key => $newstore,
- $key.time => $now },
- $sheet->{'cdom'},$sheet->{'cnum'});
- } else {
- &Apache::lonnet::put('nohist_calculatedsheets_'.$sheet->{'cid'},
- { $key => $newstore,
- $key.time => $now },
- $sheet->{'udom'},
- $sheet->{'uname'})
+ my $result = &Apache::lonnet::put('nohist_calculatedsheets',
+ { $key => $newstore,
+ $timekey => $now },
+ $sheet->{'cdom'},
+ $sheet->{'cnum'});
+ } else {
+ my $result = &Apache::lonnet::put('nohist_calculatedsheets_'.$sheet->{'cid'},
+ { $key => $newstore,
+ $timekey => $now },
+ $sheet->{'udom'},
+ $sheet->{'uname'});
}
return @exportarr;
}
@@ -2742,7 +2880,7 @@ sub load_spreadsheet_expirationdates {
my @tmp = &Apache::lonnet::dump('nohist_expirationdates',
$ENV{'course.'.$cid.'.domain'},
$ENV{'course.'.$cid.'.num'});
- if (lc($tmp[0])!~/^error/){
+ if (lc($tmp[0]) !~ /^error/){
%expiredates = @tmp;
}
}
@@ -2860,11 +2998,16 @@ sub handler {
delete $ENV{'form.unewformula'} if (exists($ENV{'form.unewformula'}));
}
#
- # Clean up symb and spreadsheet filename
+ # Look for special assessment spreadsheets - '_feedback', etc.
#
- if (($ENV{'form.usymb'}=~/^\_(\w+)/) && (!$ENV{'form.ufn'})) {
+ if (($ENV{'form.usymb'}=~/^\_(\w+)/) && (!$ENV{'form.ufn'} ||
+ $ENV{'form.ufn'} eq '' ||
+ $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;
+ }
#
# Interactive loading of specific sheet?
#
@@ -2906,6 +3049,8 @@ sub handler {
function celledit(cellname,cellformula) {
var edit_text = '';
+ // cellformula may contain less-than and greater-than symbols, so
+ // we need to escape them?
edit_text +='Cell Edit Window ';
edit_text += '');
# Done
return OK;
@@ -3171,3 +3322,5 @@ ENDSCRIPT
1;
__END__
+
+