--- loncom/interface/Attic/lonspreadsheet.pm 2002/07/05 01:31:25 1.95 +++ loncom/interface/Attic/lonspreadsheet.pm 2002/08/30 19:47:47 1.104 @@ -1,5 +1,5 @@ # -# $Id: lonspreadsheet.pm,v 1.95 2002/07/05 01:31:25 www Exp $ +# $Id: lonspreadsheet.pm,v 1.104 2002/08/30 19:47:47 matthew Exp $ # # Copyright Michigan State University Board of Trustees # @@ -71,7 +71,7 @@ use Apache::lonnet; use Apache::Constants qw(:common :http); use GDBM_File; use HTML::TokeParser; - +use Apache::lonhtmlcommon; # # Caches for previously calculated spreadsheets # @@ -112,6 +112,7 @@ my %parmhash; my %starttimes; my %usedtimes; +my %numbertimes; # Stuff that only the screen handler can know @@ -129,6 +130,7 @@ sub initsheet { $safeeval->permit("sort"); $safeeval->deny(":base_io"); $safehole->wrap(\&Apache::lonnet::EXT,$safeeval,'&EXT'); + $safeeval->share('$@'); my $code=<<'ENDDEFS'; # ---------------------------------------------------- Inside of the safe space @@ -140,41 +142,39 @@ sub initsheet { # rl: row label # os: other spreadsheets (for student spreadsheet only) -undef %v; +undef %sheet_values; undef %t; undef %f; undef %c; -undef %rl; +undef %rowlabel; undef @os; -$maxrow=0; -$sheettype=''; +$maxrow = 0; +$sheettype = ''; # filename/reference of the sheet - -$filename=''; +$filename = ''; # user data -$uname=''; -$uhome=''; -$udom=''; +$uname = ''; +$uhome = ''; +$udom = ''; # course data -$csec=''; -$chome=''; -$cnum=''; -$cdom=''; -$cid=''; -$cfn=''; +$csec = ''; +$chome= ''; +$cnum = ''; +$cdom = ''; +$cid = ''; +$cfn = ''; # symb -$usymb=''; +$usymb = ''; # error messages - -$errormsg=''; +$errormsg = ''; sub mask { my ($lower,$upper)=@_; @@ -383,8 +383,8 @@ sub CDLHASH { if ($key =~ /[A-z](\-[A-z])?\d+(\-\d+)?/) { my $keymask = &mask($key); # Assume the keys are addresses - my @Temp = grep /$keymask/,keys(%v); - @Keys = $v{@Temp}; + my @Temp = grep /$keymask/,keys(%sheet_values); + @Keys = $sheet_values{@Temp}; } else { $Keys[0]= $key; } @@ -395,8 +395,8 @@ sub CDLHASH { @Keys = @Temp; if ($value =~ /[A-z](\-[A-z])?\d+(\-\d+)?/) { my $valmask = &mask($value); - my @Temp = grep /$valmask/,keys(%v); - @Values =$v{@Temp}; + my @Temp = grep /$valmask/,keys(%sheet_values); + @Values =$sheet_values{@Temp}; } else { $Values[0]= $value; } @@ -430,7 +430,7 @@ sub GETHASH { $index = 0; } if ($key =~ /^[A-z]\d+$/) { - $key = $v{$key}; + $key = $sheet_values{$key}; } return $hashes{$name}->{$key}->[$index]; } @@ -487,8 +487,8 @@ sub HASH { if ($key =~ /[A-z](\-[A-z])?\d+(\-\d+)?/) { my $keymask = &mask($key); # Assume the keys are addresses - my @Temp = grep /$keymask/,keys(%v); - @Keys = $v{@Temp}; + my @Temp = grep /$keymask/,keys(%sheet_values); + @Keys = $sheet_values{@Temp}; } else { $Keys[0]= $key; } @@ -500,8 +500,8 @@ sub HASH { # Check to see if we have multiple $value(s) if ($value =~ /[A-z](\-[A-z])?\d+(\-\d+)?/) { my $valmask = &mask($value); - my @Temp = grep /$valmask/,keys(%v); - @Values =$v{@Temp}; + my @Temp = grep /$valmask/,keys(%sheet_values); + @Values =$sheet_values{@Temp}; } else { $Values[0]= $value; } @@ -530,7 +530,7 @@ returns the number of items in the range #------------------------------------------------------- sub NUM { my $mask=mask(@_); - my $num= $#{@{grep(/$mask/,keys(%v))}}+1; + my $num= $#{@{grep(/$mask/,keys(%sheet_values))}}+1; return $num; } @@ -538,8 +538,8 @@ sub BIN { my ($low,$high,$lower,$upper)=@_; my $mask=mask($lower,$upper); my $num=0; - foreach (grep /$mask/,keys(%v)) { - if (($v{$_}>=$low) && ($v{$_}<=$high)) { + foreach (grep /$mask/,keys(%sheet_values)) { + if (($sheet_values{$_}>=$low) && ($sheet_values{$_}<=$high)) { $num++; } } @@ -559,8 +559,8 @@ returns the sum of items in the range. sub SUM { my $mask=mask(@_); my $sum=0; - foreach (grep /$mask/,keys(%v)) { - $sum+=$v{$_}; + foreach (grep /$mask/,keys(%sheet_values)) { + $sum+=$sheet_values{$_}; } return $sum; } @@ -577,8 +577,8 @@ compute the average of the items in the sub MEAN { my $mask=mask(@_); my $sum=0; my $num=0; - foreach (grep /$mask/,keys(%v)) { - $sum+=$v{$_}; + foreach (grep /$mask/,keys(%sheet_values)) { + $sum+=$sheet_values{$_}; $num++; } if ($num) { @@ -600,15 +600,15 @@ compute the standard deviation of the it sub STDDEV { my $mask=mask(@_); my $sum=0; my $num=0; - foreach (grep /$mask/,keys(%v)) { - $sum+=$v{$_}; + foreach (grep /$mask/,keys(%sheet_values)) { + $sum+=$sheet_values{$_}; $num++; } unless ($num>1) { return undef; } my $mean=$sum/$num; $sum=0; - foreach (grep /$mask/,keys(%v)) { - $sum+=($v{$_}-$mean)**2; + foreach (grep /$mask/,keys(%sheet_values)) { + $sum+=($sheet_values{$_}-$mean)**2; } return sqrt($sum/($num-1)); } @@ -625,8 +625,8 @@ compute the product of the items in the sub PROD { my $mask=mask(@_); my $prod=1; - foreach (grep /$mask/,keys(%v)) { - $prod*=$v{$_}; + foreach (grep /$mask/,keys(%sheet_values)) { + $prod*=$sheet_values{$_}; } return $prod; } @@ -643,9 +643,9 @@ compute the maximum of the items in the sub MAX { my $mask=mask(@_); my $max='-'; - foreach (grep /$mask/,keys(%v)) { - unless ($max) { $max=$v{$_}; } - if (($v{$_}>$max) || ($max eq '-')) { $max=$v{$_}; } + foreach (grep /$mask/,keys(%sheet_values)) { + unless ($max) { $max=$sheet_values{$_}; } + if (($sheet_values{$_}>$max) || ($max eq '-')) { $max=$sheet_values{$_}; } } return $max; } @@ -662,9 +662,11 @@ compute the minimum of the items in the sub MIN { my $mask=mask(@_); my $min='-'; - foreach (grep /$mask/,keys(%v)) { - unless ($max) { $max=$v{$_}; } - if (($v{$_}<$min) || ($min eq '-')) { $min=$v{$_}; } + foreach (grep /$mask/,keys(%sheet_values)) { + unless ($max) { $max=$sheet_values{$_}; } + if (($sheet_values{$_}<$min) || ($min eq '-')) { + $min=$sheet_values{$_}; + } } return $min; } @@ -683,8 +685,8 @@ sub SUMMAX { my ($num,$lower,$upper)=@_; my $mask=mask($lower,$upper); my @inside=(); - foreach (grep /$mask/,keys(%v)) { - push (@inside,$v{$_}); + foreach (grep /$mask/,keys(%sheet_values)) { + push (@inside,$sheet_values{$_}); } @inside=sort(@inside); my $sum=0; my $i; @@ -708,8 +710,8 @@ sub SUMMIN { my ($num,$lower,$upper)=@_; my $mask=mask($lower,$upper); my @inside=(); - foreach (grep /$mask/,keys(%v)) { - $inside[$#inside+1]=$v{$_}; + foreach (grep /$mask/,keys(%sheet_values)) { + $inside[$#inside+1]=$sheet_values{$_}; } @inside=sort(@inside); my $sum=0; my $i; @@ -719,6 +721,53 @@ sub SUMMIN { return $sum; } +#------------------------------------------------------- + +=item MINPARM(parametername) + +Returns the minimum value of the parameters matching the parametername. +parametername should be a string such as 'duedate'. + +=cut + +#------------------------------------------------------- +sub MINPARM { + my ($expression) = @_; + my $min = undef; + study($expression); + foreach $parameter (keys(%c)) { + next if ($parameter !~ /$expression/); + if ((! defined($min)) || ($min > $c{$parameter})) { + $min = $c{$parameter} + } + } + return $min; +} + +#------------------------------------------------------- + +=item MAXPARM(parametername) + +Returns the maximum value of the parameters matching the input parameter name. +parametername should be a string such as 'duedate'. + +=cut + +#------------------------------------------------------- +sub MAXPARM { + my ($expression) = @_; + my $max = undef; + study($expression); + foreach $parameter (keys(%c)) { + next if ($parameter !~ /$expression/); + if ((! defined($min)) || ($max < $c{$parameter})) { + $max = $c{$parameter} + } + } + return $max; +} + +#-------------------------------------------------------- sub expandnamed { my $expression=shift; if ($expression=~/^\&/) { @@ -766,6 +815,14 @@ sub expandnamed { } if ($#matches == 0) { $returnvalue = '$c{\''.$matches[0].'\'}'; + } elsif ($#matches > 0) { + # more than one match. Look for a concise one + $returnvalue = "'non-unique parameter name : $expression'"; + foreach (@matches) { + if (/^$expression$/) { + $returnvalue = '$c{\''.$_.'\'}'; + } + } } else { $returnvalue = "'bad parameter name : $expression'"; } @@ -781,32 +838,30 @@ sub sett { } else { $pattern='[A-Z]'; } + # Deal with the template row foreach (keys(%f)) { - if ($_=~/template\_(\w)/) { - my $col=$1; - unless ($col=~/^$pattern/) { - foreach (keys(%f)) { - if ($_=~/A(\d+)/) { - my $trow=$1; - if ($trow) { - # Get the name of this cell - my $lb=$col.$trow; - # Grab the template declaration - $t{$lb}=$f{'template_'.$col}; - # Replace '#' with the row number - $t{$lb}=~s/\#/$trow/g; - # Replace '....' with ',' - $t{$lb}=~s/\.\.+/\,/g; - # Replace 'A0' with the value from 'A0' - $t{$lb}=~s/(^|[^\"\'])([A-Za-z]\d+)/$1\$v\{\'$2\'\}/g; - # Replace parameters - $t{$lb}=~s/(^|[^\"\'])\[([^\]]+)\]/$1.&expandnamed($2)/ge; - } - } - } - } - } + next if ($_!~/template\_(\w)/); + my $col=$1; + next if ($col=~/^$pattern/); + foreach (keys(%f)) { + next if ($_!~/A(\d+)/); + my $trow=$1; + next if (! $trow); + # Get the name of this cell + my $lb=$col.$trow; + # Grab the template declaration + $t{$lb}=$f{'template_'.$col}; + # Replace '#' with the row number + $t{$lb}=~s/\#/$trow/g; + # Replace '....' with ',' + $t{$lb}=~s/\.\.+/\,/g; + # Replace 'A0' with the value from 'A0' + $t{$lb}=~s/(^|[^\"\'])([A-Za-z]\d+)/$1\$sheet_values\{\'$2\'\}/g; + # Replace parameters + $t{$lb}=~s/(^|[^\"\'])\[([^\]]+)\]/$1.&expandnamed($2)/ge; + } } + # Deal with the normal cells foreach (keys(%f)) { if (($f{$_}) && ($_!~/template\_/)) { my $matches=($_=~/^$pattern(\d+)/); @@ -817,43 +872,56 @@ sub sett { } else { $t{$_}=$f{$_}; $t{$_}=~s/\.\.+/\,/g; - $t{$_}=~s/(^|[^\"\'])([A-Za-z]\d+)/$1\$v\{\'$2\'\}/g; + $t{$_}=~s/(^|[^\"\'])([A-Za-z]\d+)/$1\$sheet_values\{\'$2\'\}/g; $t{$_}=~s/(^|[^\"\'])\[([^\]]+)\]/$1.&expandnamed($2)/ge; } } } + # For inserted lines, [B-Z] is also valid + unless ($sheettype eq 'assesscalc') { + foreach (keys(%f)) { + if ($_=~/[B-Z](\d+)/) { + if ($f{'A'.$1}=~/^[\~\-]/) { + $t{$_}=$f{$_}; + $t{$_}=~s/\.\.+/\,/g; + $t{$_}=~s/(^|[^\"\'])([A-Za-z]\d+)/$1\$sheet_values\{\'$2\'\}/g; + $t{$_}=~s/(^|[^\"\'])\[([^\]]+)\]/$1.&expandnamed($2)/ge; + } + } + } + } # For some reason 'A0' gets special treatment... This seems superfluous # but I imagine it is here for a reason. $t{'A0'}=$f{'A0'}; $t{'A0'}=~s/\.\.+/\,/g; - $t{'A0'}=~s/(^|[^\"\'])([A-Za-z]\d+)/$1\$v\{\'$2\'\}/g; + $t{'A0'}=~s/(^|[^\"\'])([A-Za-z]\d+)/$1\$sheet_values\{\'$2\'\}/g; $t{'A0'}=~s/(^|[^\"\'])\[([^\]]+)\]/$1.&expandnamed($2)/ge; } sub calc { - undef %v; + undef %sheet_values; &sett(); my $notfinished=1; + my $lastcalc=''; my $depth=0; - my $errormsg; while ($notfinished) { $notfinished=0; foreach (keys(%t)) { - my $old=$v{$_}; - $v{$_}=eval($t{$_}); + my $old=$sheet_values{$_}; + $sheet_values{$_}=eval $t{$_}; if ($@) { - $v{$_}='"error"'; - $errormsg.=$_.': '.$@."\n"; + undef %sheet_values; + return $_.': '.$@; } - if ($v{$_} ne $old) { $notfinished=1; } + if ($sheet_values{$_} ne $old) { $notfinished=1; $lastcalc=$_; } } $depth++; if ($depth>100) { - undef %v; - return 'Maximum calculation depth exceeded'; + undef %sheet_values; + return $lastcalc.': Maximum calculation depth exceeded'; } } - return $errormsg; + return ''; } sub templaterow { @@ -865,31 +933,38 @@ sub templaterow { 'n','o','p','q','r','s','t','u','v','w','x','y','z') { my $fm=$f{'template_'.$_}; $fm=~s/[\'\"]/\&\#34;/g; - $cols[$#cols+1]="'template_$_','$fm'".'___eq___'.$fm; + push(@cols,"'template_$_','$fm'".'___eq___'.$fm); } return @cols; } +# +# This is actually used for the student spreadsheet, not the assessment sheet +# Do not be fooled by the name! +# sub outrowassess { + # $n is the current row number my $n=shift; my @cols=(); if ($n) { - my ($usy,$ufn)=split(/\_\_\&\&\&\_\_/,$f{'A'.$n}); - if ($rl{$usy}) { - $cols[0]=$rl{$usy}.'<br>'. - '<select name="sel_'.$n.'" onChange="changesheet('.$n. - ')"><option name="default">Default</option>'; - } else { $cols[0]=''; } - foreach (@os) { - $cols[0].='<option name="'.$_.'"'; + my ($usy,$ufn)=split(/__&&&\__/,$f{'A'.$n}); + if ($rowlabel{$usy}) { + $cols[0]=$rowlabel{$usy}.'<br>'. + '<select name="sel_'.$n.'" onChange="changesheet('.$n.')">'. + '<option name="default">Default</option>'; + } else { + $cols[0]=''; + } + foreach (@os) { + $cols[0].='<option name="'.$_.'"'; if ($ufn eq $_) { - $cols[0].=' selected'; + $cols[0].=' selected'; } $cols[0].='>'.$_.'</option>'; - } - $cols[0].='</select>'; + } + $cols[0].='</select>'; } else { - $cols[0]='<b><font size=+1>Export</font></b>'; + $cols[0]='<b><font size=+1>Export</font></b>'; } 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', @@ -897,7 +972,7 @@ sub outrowassess { 'n','o','p','q','r','s','t','u','v','w','x','y','z') { my $fm=$f{$_.$n}; $fm=~s/[\'\"]/\&\#34;/g; - push(@cols,"'$_$n','$fm'".'___eq___'.$v{$_.$n}); + push(@cols,"'$_$n','$fm'".'___eq___'.$sheet_values{$_.$n}); } return @cols; } @@ -906,7 +981,7 @@ sub outrow { my $n=shift; my @cols=(); if ($n) { - $cols[0]=$rl{$f{'A'.$n}}; + $cols[0]=$rowlabel{$f{'A'.$n}}; } else { $cols[0]='<b><font size=+1>Export</font></b>'; } @@ -916,7 +991,7 @@ sub outrow { 'n','o','p','q','r','s','t','u','v','w','x','y','z') { my $fm=$f{$_.$n}; $fm=~s/[\'\"]/\&\#34;/g; - $cols[$#cols+1]="'$_$n','$fm'".'___eq___'.$v{$_.$n}; + push(@cols,"'$_$n','$fm'".'___eq___'.$sheet_values{$_.$n}); } return @cols; } @@ -925,7 +1000,7 @@ sub exportrowa { my @exportarray=(); 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') { - $exportarray[$#exportarray+1]=$v{$_.'0'}; + push(@exportarray,$sheet_values{$_.'0'}); } return @exportarray; } @@ -960,8 +1035,8 @@ sub setothersheets { # ------------------------------------------------ Add or change formula values sub setrowlabels { - my ($safeeval,%rl)=@_; - %{$safeeval->varglob('rl')}=%rl; + my ($safeeval,%rowlabel)=@_; + %{$safeeval->varglob('rowlabel')}=%rowlabel; } # ------------------------------------------------------- Calculate spreadsheet @@ -975,7 +1050,7 @@ sub calcsheet { sub getvalues { my $safeeval=shift; - return $safeeval->reval('%v'); + return $safeeval->reval('%sheet_values'); } # ---------------------------------------------------------------- Get formulas @@ -985,6 +1060,13 @@ sub getformulas { return %{$safeeval->varglob('f')}; } +# ----------------------------------------------------- Get value of $f{'A'.$n} + +sub getfa { + my ($safeeval,$n)=@_; + return $safeeval->reval('$f{"A'.$n.'"}'); +} + # -------------------------------------------------------------------- Get type sub gettype { @@ -1123,7 +1205,7 @@ sub rown { } my $showf=0; my $proc; - my $maxred; + my $maxred=1; my $sheettype=&gettype($safeeval); if ($sheettype eq 'studentcalc') { $proc='&outrowassess'; @@ -1136,7 +1218,12 @@ sub rown { } else { $maxred=26; } - if ($n eq '-') { $proc='&templaterow'; $n=-1; $dataflag=1; } + if (&getfa($safeeval,$n)=~/^[\~\-]/) { $maxred=1; } + if ($n eq '-') { + $proc='&templaterow'; + $n=-1; + $dataflag=1; + } foreach ($safeeval->reval($proc.'('.$n.')')) { my $bgcolor=$defaultbg.((($showf-1)/5==int(($showf-1)/5))?'99':'DD'); my ($fm,$vl)=split(/\_\_\_eq\_\_\_/,$_); @@ -1194,20 +1281,20 @@ sub outsheet { '><b><font size=+1>Import</font></b></td>'. '<td colspan='.$maxyellow. '><b><font size=+1>Calculations</font></b></td></tr><tr>'; - my $showf=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', - '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') { - $showf++; - if ($showf<=$maxred) { - $tabledata.='<td bgcolor="#FFDDDD">'; - } else { - $tabledata.='<td>'; - } - $tabledata.="<b><font size=+1>$_</font></b></td>"; - } - $tabledata.='</tr>'.&rown($safeeval,'-').&rown($safeeval,0); + my $showf=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', + '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') { + $showf++; + if ($showf<=$maxred) { + $tabledata.='<td bgcolor="#FFDDDD">'; + } else { + $tabledata.='<td>'; + } + $tabledata.="<b><font size=+1>$_</font></b></td>"; + } + $tabledata.='</tr>'.&rown($safeeval,'-').&rown($safeeval,0); } else { $tabledata='<pre>'; } $r->print($tabledata); @@ -1222,7 +1309,6 @@ sub outsheet { $sortidx[$row-1]=$row-1; } @sortidx=sort { $sortby[$a] cmp $sortby[$b]; } @sortidx; - my $what='Student'; if (&gettype($safeeval) eq 'assesscalc') { $what='Item'; @@ -1232,23 +1318,20 @@ sub outsheet { my $n=0; for ($row=0;$row<$maxrow;$row++) { - my $thisrow=&rown($safeeval,$sortidx[$row]+1); - if ($thisrow) { - if (($n/25==int($n/25)) && (!$ENV{'form.showcsv'})) { - $r->print("</table>\n<br>\n"); - $r->rflush(); - $r->print('<table border=2><tr><td> <td>'.$what.'</td>'); - 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', - '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') { - $r->print('<td>'.$_.'</td>'); + my $thisrow=&rown($safeeval,$sortidx[$row]+1); + if ($thisrow) { + if (($n/25==int($n/25)) && (!$ENV{'form.showcsv'})) { + $r->print("</table>\n<br>\n"); + $r->rflush(); + $r->print('<table border=2><tr><td> <td>'.$what.'</td>'); + $r->print('<td>'.join('</td><td>', + (split(//,'ABCDEFGHIJKLMNOPQRSTUVWXYZ'. + 'abcdefghijklmnopqrstuvwxyz'))). + "</td></tr>\n"); + } + $n++; + $r->print($thisrow); } - $r->print('</tr>'); - } - $n++; - $r->print($thisrow); - } } $r->print($ENV{'form.showcsv'}?'</pre>':'</table>'); } @@ -1259,9 +1342,9 @@ sub outsheet { sub othersheets { my ($safeeval,$stype)=@_; # - my $cnum=&getcnum($safeeval); - my $cdom=&getcdom($safeeval); - my $chome=&getchome($safeeval); + my $cnum = &getcnum($safeeval); + my $cdom = &getcdom($safeeval); + my $chome = &getchome($safeeval); # my @alternatives=(); my %results=&Apache::lonnet::dump($stype.'_spreadsheets',$cdom,$cnum); @@ -1306,77 +1389,71 @@ sub parse_sheet { # sub readsheet { - my ($safeeval,$fn)=@_; - my $stype=&gettype($safeeval); - my $cnum=&getcnum($safeeval); - my $cdom=&getcdom($safeeval); - my $chome=&getchome($safeeval); - - if (! defined($fn)) { - # There is no filename. Look for defaults in course and global, cache - unless ($fn=$defaultsheets{$cnum.'_'.$cdom.'_'.$stype}) { - my %tmphash = &Apache::lonnet::get('environment', - ['spreadsheet_default_'.$stype], - $cdom,$cnum); - my ($tmp) = keys(%tmphash); - if ($tmp =~ /^(con_lost|error|no_such_host)/i) { - $fn = 'default_'.$stype; - } else { - $fn = $tmphash{'spreadsheet_default_'.$stype}; - } - unless (($fn) && ($fn!~/^error\:/)) { - $fn='default_'.$stype; - } - $defaultsheets{$cnum.'_'.$cdom.'_'.$stype}=$fn; - } - } - -# ---------------------------------------------------------- fn now has a value - - &setfilename($safeeval,$fn); - -# ------------------------------------------------------ see if sheet is cached - my $fstring=''; - if ($fstring=$spreadsheets{$cnum.'_'.$cdom.'_'.$stype.'_'.$fn}) { - &setformulas($safeeval,split(/\_\_\_\;\_\_\_/,$fstring)); - } else { - -# ---------------------------------------------------- Not cached, need to read - - my %f=(); - - if ($fn=~/^default\_/) { - my $sheetxml=''; - my $fh; - my $dfn=$fn; - $dfn=~s/\_/\./g; - if ($fh=Apache::File->new($includedir.'/'.$dfn)) { - $sheetxml=join('',<$fh>); - } else { - $sheetxml='<field row="0" col="A">"Error"</field>'; - } - %f=%{&parse_sheet(\$sheetxml)}; - } elsif($fn=~/\/*\.spreadsheet$/) { - my $sheetxml=&Apache::lonnet::getfile - (&Apache::lonnet::filelocation('',$fn)); - if ($sheetxml == -1) { - $sheetxml='<field row="0" col="A">"Error loading spreadsheet ' - .$fn.'"</field>'; - } - %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) { - foreach (keys(%tmphash)) { - $f{$_}=$tmphash{$_}; - } - } - } -# --------------------------------------------------------------- Cache and set - $spreadsheets{$cnum.'_'.$cdom.'_'.$stype.'_'.$fn}=join('___;___',%f); - &setformulas($safeeval,%f); + my ($safeeval,$fn)=@_; + my $stype = &gettype($safeeval); + my $cnum = &getcnum($safeeval); + my $cdom = &getcdom($safeeval); + my $chome = &getchome($safeeval); + + if (! defined($fn)) { + # There is no filename. Look for defaults in course and global, cache + unless ($fn=$defaultsheets{$cnum.'_'.$cdom.'_'.$stype}) { + my %tmphash = &Apache::lonnet::get('environment', + ['spreadsheet_default_'.$stype], + $cdom,$cnum); + my ($tmp) = keys(%tmphash); + if ($tmp =~ /^(con_lost|error|no_such_host)/i) { + $fn = 'default_'.$stype; + } else { + $fn = $tmphash{'spreadsheet_default_'.$stype}; + } + unless (($fn) && ($fn!~/^error\:/)) { + $fn='default_'.$stype; + } + $defaultsheets{$cnum.'_'.$cdom.'_'.$stype}=$fn; + } + } + # $fn now has a value + &setfilename($safeeval,$fn); + # see if sheet is cached + my $fstring=''; + if ($fstring=$spreadsheets{$cnum.'_'.$cdom.'_'.$stype.'_'.$fn}) { + &setformulas($safeeval,split(/\_\_\_\;\_\_\_/,$fstring)); + } else { + # Not cached, need to read + my %f=(); + if ($fn=~/^default\_/) { + my $sheetxml=''; + my $fh; + my $dfn=$fn; + $dfn=~s/\_/\./g; + if ($fh=Apache::File->new($includedir.'/'.$dfn)) { + $sheetxml=join('',<$fh>); + } else { + $sheetxml='<field row="0" col="A">"Error"</field>'; + } + %f=%{&parse_sheet(\$sheetxml)}; + } elsif($fn=~/\/*\.spreadsheet$/) { + my $sheetxml=&Apache::lonnet::getfile + (&Apache::lonnet::filelocation('',$fn)); + if ($sheetxml == -1) { + $sheetxml='<field row="0" col="A">"Error loading spreadsheet ' + .$fn.'"</field>'; + } + %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) { + foreach (keys(%tmphash)) { + $f{$_}=$tmphash{$_}; + } + } + } + # Cache and set + $spreadsheets{$cnum.'_'.$cdom.'_'.$stype.'_'.$fn}=join('___;___',%f); + &setformulas($safeeval,%f); } } @@ -1404,52 +1481,51 @@ sub makenewsheet { # ------------------------------------------------------------ Save spreadsheet sub writesheet { - my ($safeeval,$makedef)=@_; - my $cid=&getcid($safeeval); - if (&Apache::lonnet::allowed('opa',$cid)) { - my %f=&getformulas($safeeval); - my $stype=&gettype($safeeval); - my $cnum=&getcnum($safeeval); - my $cdom=&getcdom($safeeval); - my $chome=&getchome($safeeval); - my $fn=&getfilename($safeeval); - -# ------------------------------------------------------------- Cache new sheet - $spreadsheets{$cnum.'_'.$cdom.'_'.$stype.'_'.$fn}=join('___;___',%f); -# ----------------------------------------------------------------- Write sheet - my $sheetdata=''; - foreach (keys(%f)) { - unless ($f{$_} eq 'import') { - $sheetdata.=&Apache::lonnet::escape($_).'='. - &Apache::lonnet::escape($f{$_}).'&'; - } - } - $sheetdata=~s/\&$//; - my $reply=&Apache::lonnet::reply('put:'.$cdom.':'.$cnum.':'.$fn.':'. - $sheetdata,$chome); - if ($reply eq 'ok') { - $reply=&Apache::lonnet::reply('put:'.$cdom.':'.$cnum.':'. - $stype.'_spreadsheets:'. - &Apache::lonnet::escape($fn).'='.$ENV{'user.name'}.'@'. - $ENV{'user.domain'}, - $chome); - if ($reply eq 'ok') { - if ($makedef) { - return &Apache::lonnet::reply('put:'.$cdom.':'.$cnum. - ':environment:spreadsheet_default_'.$stype.'='. - &Apache::lonnet::escape($fn), - $chome); - } else { - return $reply; - } - } else { - return $reply; - } - } else { - return $reply; - } - } - return 'unauthorized'; + my ($safeeval,$makedef)=@_; + my $cid=&getcid($safeeval); + if (&Apache::lonnet::allowed('opa',$cid)) { + my %f=&getformulas($safeeval); + my $stype=&gettype($safeeval); + my $cnum=&getcnum($safeeval); + my $cdom=&getcdom($safeeval); + my $chome=&getchome($safeeval); + my $fn=&getfilename($safeeval); + # Cache new sheet + $spreadsheets{$cnum.'_'.$cdom.'_'.$stype.'_'.$fn}=join('___;___',%f); + # Write sheet + my $sheetdata=''; + foreach (keys(%f)) { + unless ($f{$_} eq 'import') { + $sheetdata.=&Apache::lonnet::escape($_).'='. + &Apache::lonnet::escape($f{$_}).'&'; + } + } + $sheetdata=~s/\&$//; + my $reply=&Apache::lonnet::reply('put:'.$cdom.':'.$cnum.':'.$fn.':'. + $sheetdata,$chome); + if ($reply eq 'ok') { + $reply=&Apache::lonnet::reply('put:'.$cdom.':'.$cnum.':'. + $stype.'_spreadsheets:'. + &Apache::lonnet::escape($fn). + '='.$ENV{'user.name'}.'@'. + $ENV{'user.domain'}, + $chome); + if ($reply eq 'ok') { + if ($makedef) { + return &Apache::lonnet::reply('put:'.$cdom.':'.$cnum. + ':environment:'. + 'spreadsheet_default_'. + $stype.'='. + &Apache::lonnet::escape($fn), + $chome); + } + return $reply; + } + return $reply; + } + return $reply; + } + return 'unauthorized'; } # ----------------------------------------------- Make a temp copy of the sheet @@ -1459,7 +1535,7 @@ sub writesheet { sub tmpwrite { my $safeeval=shift; my $fn=$ENV{'user.name'}.'_'. - $ENV{'user.domain'}.'_spreadsheet_'.&getusymb($safeeval).'_'. + $ENV{'user.domain'}.'_spreadsheet_'.&getusymb($safeeval).'_'. &getfilename($safeeval); $fn=~s/\W/\_/g; $fn=$tmpdir.$fn.'.tmp'; @@ -1514,210 +1590,203 @@ sub tmpread { &setformulas($safeeval,%fo); } -# ================================================================== Parameters -# -------------------------------------------- Figure out a cascading parameter -# -# For this function to work -# -# * parmhash needs to be tied -# * courseopt and useropt need to be initialized for this user and course -# - -sub parmval { - my ($what,$safeeval)=@_; - my $cid=&getcid($safeeval); - my $csec=&getcsec($safeeval); - my $uname=&getuname($safeeval); - my $udom=&getudom($safeeval); - my $symb=&getusymb($safeeval); - - unless ($symb) { return ''; } - my $result=''; - - my ($mapname,$id,$fn)=split(/\_\_\_/,$symb); -# ----------------------------------------------------- Cascading lookup scheme - my $rwhat=$what; - $what=~s/^parameter\_//; - $what=~s/\_([^\_]+)$/\.$1/; - - my $symbparm=$symb.'.'.$what; - my $mapparm=$mapname.'___(all).'.$what; - my $usercourseprefix=$uname.'_'.$udom.'_'.$cid; - - my $seclevel= - $usercourseprefix.'.['. - $csec.'].'.$what; - my $seclevelr= - $usercourseprefix.'.['. - $csec.'].'.$symbparm; - my $seclevelm= - $usercourseprefix.'.['. - $csec.'].'.$mapparm; - - my $courselevel= - $usercourseprefix.'.'.$what; - my $courselevelr= - $usercourseprefix.'.'.$symbparm; - my $courselevelm= - $usercourseprefix.'.'.$mapparm; - -# ---------------------------------------------------------- fourth, check user - - if ($uname) { +################################################## +################################################## - if ($useropt{$courselevelr}) { return $useropt{$courselevelr}; } +=pod - if ($useropt{$courselevelm}) { return $useropt{$courselevelm}; } +=item &parmval() - if ($useropt{$courselevel}) { return $useropt{$courselevel}; } +Determine the value of a parameter. - } +Inputs: $what, the parameter needed, $safeeval, the safe space -# --------------------------------------------------------- third, check course - - if ($csec) { - - if ($courseopt{$seclevelr}) { return $courseopt{$seclevelr}; } - - if ($courseopt{$seclevelm}) { return $courseopt{$seclevelm}; } - - if ($courseopt{$seclevel}) { return $courseopt{$seclevel}; } - - } +Returns: The value of a parameter, or '' if none. - if ($courseopt{$courselevelr}) { return $courseopt{$courselevelr}; } +This function cascades through the possible levels searching for a value for +a parameter. The levels are checked in the following order: +user, course (at section level and course level), map, and lonnet::metadata. +This function uses %parmhash, which must be tied prior to calling it. +This function also requires %courseopt and %useropt to be initialized for +this user and course. - if ($courseopt{$courselevelm}) { return $courseopt{$courselevelm}; } - - if ($courseopt{$courselevel}) { return $courseopt{$courselevel}; } - -# ----------------------------------------------------- second, check map parms - - my $thisparm=$parmhash{$symbparm}; - if ($thisparm) { return $thisparm; } - -# -------------------------------------------------------- first, check default +=cut - return &Apache::lonnet::metadata($fn,$rwhat.'.default'); - +################################################## +################################################## +sub parmval { + my ($what,$safeeval)=@_; + my $symb = &getusymb($safeeval); + unless ($symb) { return ''; } + # + my $cid = &getcid($safeeval); + my $csec = &getcsec($safeeval); + my $uname = &getuname($safeeval); + my $udom = &getudom($safeeval); + my $result=''; + # + my ($mapname,$id,$fn)=split(/\_\_\_/,$symb); + # Cascading lookup scheme + my $rwhat=$what; + $what =~ s/^parameter\_//; + $what =~ s/\_([^\_]+)$/\.$1/; + # + my $symbparm = $symb.'.'.$what; + my $mapparm = $mapname.'___(all).'.$what; + my $usercourseprefix = $uname.'_'.$udom.'_'.$cid; + # + my $seclevel = $usercourseprefix.'.['.$csec.'].'.$what; + my $seclevelr = $usercourseprefix.'.['.$csec.'].'.$symbparm; + my $seclevelm = $usercourseprefix.'.['.$csec.'].'.$mapparm; + # + my $courselevel = $usercourseprefix.'.'.$what; + my $courselevelr = $usercourseprefix.'.'.$symbparm; + my $courselevelm = $usercourseprefix.'.'.$mapparm; + # fourth, check user + if ($uname) { + return $useropt{$courselevelr} if ($useropt{$courselevelr}); + return $useropt{$courselevelm} if ($useropt{$courselevelm}); + return $useropt{$courselevel} if ($useropt{$courselevel}); + } + # third, check course + if ($csec) { + return $courseopt{$seclevelr} if ($courseopt{$seclevelr}); + return $courseopt{$seclevelm} if ($courseopt{$seclevelm}); + return $courseopt{$seclevel} if ($courseopt{$seclevel}); + } + # + return $courseopt{$courselevelr} if ($courseopt{$courselevelr}); + return $courseopt{$courselevelm} if ($courseopt{$courselevelm}); + return $courseopt{$courselevel} if ($courseopt{$courselevel}); + # second, check map parms + my $thisparm = $parmhash{$symbparm}; + return $thisparm if ($thisparm); + # first, check default + return &Apache::lonnet::metadata($fn,$rwhat.'.default'); } # ---------------------------------------------- Update rows for course listing - sub updateclasssheet { my $safeeval=shift; my $cnum=&getcnum($safeeval); my $cdom=&getcdom($safeeval); my $cid=&getcid($safeeval); my $chome=&getchome($safeeval); - -# ---------------------------------------------- Read class list and row labels - - my $classlst=&Apache::lonnet::reply - ('dump:'.$cdom.':'.$cnum.':classlist',$chome); + # + # Read class list and row labels + my %classlist; + my @tmp = &Apache::lonnet::dump('classlist',$cdom,$cnum); + if ($tmp[0] !~ /^error/) { + %classlist = @tmp; + } else { + return 'Could not access course data'; + } + undef @tmp; + # my %currentlist=(); my $now=time; - unless ($classlst=~/^error\:/) { - foreach (split(/\&/,$classlst)) { - my ($name,$value)=split(/\=/,$_); - my ($end,$start)=split(/\:/,&Apache::lonnet::unescape($value)); - my $active=1; - if (($end) && ($now>$end)) { $active=0; } - if ($active) { - my $rowlabel=''; - $name=&Apache::lonnet::unescape($name); - my ($sname,$sdom)=split(/\:/,$name); - my $ssec=&Apache::lonnet::usection($sdom,$sname,$cid); - if ($ssec==-1) { - unless ($ENV{'form.showcsv'}) { - $rowlabel='<font color=red>Data not available: '.$name. - '</font>'; - } else { - $rowlabel='ERROR","'.$name. - '","Data not available","","","'; - } + foreach my $student (keys(%classlist)) { + my ($end,$start)=split(/\:/,$classlist{$student}); + my $active=1; + $active = 0 if (($end) && ($now>$end)); + $active = 1 if ($ENV{'form.Status'} eq 'Any'); + $active = !$active if ($ENV{'form.Status'} eq 'Expired'); + if ($active) { + my $rowlabel=''; + my ($studentName,$studentDomain)=split(/\:/,$student); + my $studentSection=&Apache::lonnet::usection($studentDomain, + $studentName,$cid); + if ($studentSection==-1) { + unless ($ENV{'form.showcsv'}) { + $rowlabel='<font color=red>Data not available: '. + $studentName.'</font>'; } else { - my %reply=&Apache::lonnet::idrget($sdom,$sname); - my $reply=&Apache::lonnet::reply('get:'.$sdom.':'.$sname. - ':environment:firstname&middlename&lastname&generation', - &Apache::lonnet::homeserver($sname,$sdom)); - unless ($ENV{'form.showcsv'}) { - $rowlabel='<a href="/adm/studentcalc?uname='.$sname. - '&udom='.$sdom.'">'. - $ssec.' '.$reply{$sname}.'<br>'; - foreach ( split(/\&/,$reply)) { - $rowlabel.=&Apache::lonnet::unescape($_).' '; + $rowlabel='ERROR","'.$studentName. + '","Data not available","","","'; + } + } else { + my %reply=&Apache::lonnet::idrget($studentDomain,$studentName); + my %studentInformation=&Apache::lonnet::get + ('environment', + ['lastname','generation','firstname','middlename','id'], + $studentDomain,$studentName); + if (! $ENV{'form.showcsv'}) { + $rowlabel='<a href="/adm/studentcalc?uname='.$studentName. + '&udom='.$studentDomain.'">'. + $studentSection.' '; + foreach ('id','firstname','middlename', + 'lastname','generation'){ + $rowlabel.=$studentInformation{$_}." "; } $rowlabel.='</a>'; - } else { - $rowlabel=$ssec.'","'.$reply{$sname}.'"'; - my $ncount=0; - foreach (split(/\&/,$reply)) { - $rowlabel.=',"'.&Apache::lonnet::unescape($_).'"'; - $ncount++; - } - unless ($ncount==4) { $rowlabel.=',""'; } - $rowlabel=~s/\"$//; - } + } else { + $rowlabel= '"'.join('","', + ($studentSection, + $studentInformation{'id'}, + $studentInformation{'firstname'}, + $studentInformation{'middlename'}, + $studentInformation{'lastname'}, + $studentInformation{'generation'}) + ).'"'; } - $currentlist{&Apache::lonnet::unescape($name)}=$rowlabel; } - } # end of foreach (split(/\&/,$classlst)) -# -# -------------------- Find discrepancies between the course row table and this -# - my %f=&getformulas($safeeval); - my $changed=0; - - my $maxrow=0; - my %existing=(); - -# ----------------------------------------------------------- Now obsolete rows - foreach (keys(%f)) { - if ($_=~/^A(\d+)/) { - $maxrow=($1>$maxrow)?$1:$maxrow; - $existing{$f{$_}}=1; - unless ((defined($currentlist{$f{$_}})) || (!$1)) { - $f{$_}='!!! Obsolete'; - $changed=1; - } + $currentlist{$student}=$rowlabel; + } # end of if ($active) + } # end of foreach my $student (keys(%classlist)) + # + # Find discrepancies between the course row table and this + # + my %f=&getformulas($safeeval); + my $changed=0; + # + my $maxrow=0; + my %existing=(); + # + # Now obsolete rows + foreach (keys(%f)) { + if ($_=~/^A(\d+)/) { + $maxrow=($1>$maxrow)?$1:$maxrow; + $existing{$f{$_}}=1; + unless ((defined($currentlist{$f{$_}})) || (!$1) || + ($f{$_}=~/^(\~\~\~|\-\-\-)/)) { + $f{$_}='!!! Obsolete'; + $changed=1; } } - -# -------------------------------------------------------- New and unknown keys - - foreach (sort keys(%currentlist)) { - unless ($existing{$_}) { - $changed=1; - $maxrow++; - $f{'A'.$maxrow}=$_; - } + } + # + # New and unknown keys + foreach (sort keys(%currentlist)) { + unless ($existing{$_}) { + $changed=1; + $maxrow++; + $f{'A'.$maxrow}=$_; } - - if ($changed) { &setformulas($safeeval,%f); } - - &setmaxrow($safeeval,$maxrow); - &setrowlabels($safeeval,%currentlist); - - } else { - return 'Could not access course data'; } + if ($changed) { &setformulas($safeeval,%f); } + # + &setmaxrow($safeeval,$maxrow); + &setrowlabels($safeeval,%currentlist); } # ----------------------------------- Update rows for student and assess sheets - sub updatestudentassesssheet { my $safeeval=shift; my %bighash; my $stype=&gettype($safeeval); my %current=(); - unless ($updatedata{$ENV{'request.course.fn'}.'_'.$stype}) { -# -------------------------------------------------------------------- Tie hash - if (tie(%bighash,'GDBM_File',$ENV{'request.course.fn'}.'.db', - &GDBM_READER,0640)) { -# --------------------------------------------------------- Get all assessments - - my %allkeys=('timestamp' => + if ($updatedata{$ENV{'request.course.fn'}.'_'.$stype}) { + %current=split(/\_\_\_\;\_\_\_/, + $updatedata{$ENV{'request.course.fn'}.'_'.$stype}); + } else { + # Tie hash + tie(%bighash,'GDBM_File',$ENV{'request.course.fn'}.'.db', + &GDBM_READER(),0640); + if (! tied(%bighash)) { + return 'Could not access course data'; + } + # Get all assessments + my %allkeys=('timestamp' => 'Timestamp of Last Transaction<br>timestamp', 'subnumber' => 'Number of Submissions<br>subnumber', @@ -1725,124 +1794,101 @@ sub updatestudentassesssheet { 'Number of Tutor Responses<br>tutornumber', 'totalpoints' => 'Total Points Granted<br>totalpoints'); - my $adduserstr=''; if ((&getuname($safeeval) ne $ENV{'user.name'}) || (&getudom($safeeval) ne $ENV{'user.domain'})) { $adduserstr='&uname='.&getuname($safeeval). - '&udom='.&getudom($safeeval); + '&udom='.&getudom($safeeval); } - - my %allassess=('_feedback' => - '<a href="/adm/assesscalc?usymb=_feedback'.$adduserstr. - '">Feedback</a>', - '_evaluation' => - '<a href="/adm/assesscalc?usymb=_evaluation'.$adduserstr. - '">Evaluation</a>', - '_tutoring' => - '<a href="/adm/assesscalc?usymb=_tutoring'.$adduserstr. - '">Tutoring</a>', - '_discussion' => - '<a href="/adm/assesscalc?usymb=_discussion'.$adduserstr. - '">Discussion</a>' - ); - + my %allassess = + ('_feedback' =>'<a href="/adm/assesscalc?usymb=_feedback'. + $adduserstr.'">Feedback</a>', + '_evaluation' =>'<a href="/adm/assesscalc?usymb=_evaluation'. + $adduserstr.'">Evaluation</a>', + '_tutoring' =>'<a href="/adm/assesscalc?usymb=_tutoring'. + $adduserstr.'">Tutoring</a>', + '_discussion' =>'<a href="/adm/assesscalc?usymb=_discussion'. + $adduserstr.'">Discussion</a>' + ); foreach (keys(%bighash)) { - if ($_=~/^src\_(\d+)\.(\d+)$/) { - my $mapid=$1; - my $resid=$2; - my $id=$mapid.'.'.$resid; - my $srcf=$bighash{$_}; - if ($srcf=~/\.(problem|exam|quiz|assess|survey|form)$/) { - my $symb= - &Apache::lonnet::declutter($bighash{'map_id_'.$mapid}). - '___'.$resid.'___'. - &Apache::lonnet::declutter($srcf); - $allassess{$symb}= - '<a href="/adm/assesscalc?usymb='.$symb.$adduserstr.'">'. - $bighash{'title_'.$id}.'</a>'; - if ($stype eq 'assesscalc') { - foreach (split(/\,/, - &Apache::lonnet::metadata($srcf,'keys'))) { - if (($_=~/^stores\_(.*)/) || ($_=~/^parameter\_(.*)/)) { - my $key=$_; - my $display= - &Apache::lonnet::metadata($srcf,$key.'.display'); - unless ($display) { - $display.= - &Apache::lonnet::metadata($srcf,$key.'.name'); - } - $display.='<br>'.$key; - $allkeys{$key}=$display; - } - } # end of foreach - } - } - } + next if ($_!~/^src\_(\d+)\.(\d+)$/); + my $mapid=$1; + my $resid=$2; + my $id=$mapid.'.'.$resid; + my $srcf=$bighash{$_}; + if ($srcf=~/\.(problem|exam|quiz|assess|survey|form)$/) { + my $symb= + &Apache::lonnet::declutter($bighash{'map_id_'.$mapid}). + '___'.$resid.'___'.&Apache::lonnet::declutter($srcf); + $allassess{$symb}= + '<a href="/adm/assesscalc?usymb='.$symb.$adduserstr.'">'. + $bighash{'title_'.$id}.'</a>'; + next if ($stype ne 'assesscalc'); + foreach my $key (split(/\,/, + &Apache::lonnet::metadata($srcf,'keys') + )) { + next if ($key !~ /^(stores|parameter)_/); + my $display= + &Apache::lonnet::metadata($srcf,$key.'.display'); + unless ($display) { + $display.= + &Apache::lonnet::metadata($srcf,$key.'.name'); + } + $display.='<br>'.$key; + $allkeys{$key}=$display; + } # end of foreach + } } # end of foreach (keys(%bighash)) untie(%bighash); - -# -# %allkeys has a list of storage and parameter displays by unikey -# %allassess has a list of all resource displays by symb -# - + # + # %allkeys has a list of storage and parameter displays by unikey + # %allassess has a list of all resource displays by symb + # if ($stype eq 'assesscalc') { - %current=%allkeys; + %current=%allkeys; } elsif ($stype eq 'studentcalc') { %current=%allassess; } $updatedata{$ENV{'request.course.fn'}.'_'.$stype}= - join('___;___',%current); - } else { - return 'Could not access course data'; + join('___;___',%current); + # Get current from cache } -# ------------------------------------------------------ Get current from cache - } else { - %current=split(/\_\_\_\;\_\_\_/, - $updatedata{$ENV{'request.course.fn'}.'_'.$stype}); - } -# -------------------- Find discrepancies between the course row table and this -# - my %f=&getformulas($safeeval); - my $changed=0; - - my $maxrow=0; - my %existing=(); - -# ----------------------------------------------------------- Now obsolete rows - foreach (keys(%f)) { - if ($_=~/^A(\d+)/) { - $maxrow=($1>$maxrow)?$1:$maxrow; - my ($usy,$ufn)=split(/\_\_\&\&\&\_\_/,$f{$_}); - $existing{$usy}=1; - unless ((defined($current{$usy})) || (!$1)) { - $f{$_}='!!! Obsolete'; - $changed=1; - } elsif ($ufn) { - $current{$usy} - =~s/assesscalc\?usymb\=/assesscalc\?ufn\=$ufn\&usymb\=/; - } - } - } - -# -------------------------------------------------------- New and unknown keys - - foreach (keys(%current)) { - unless ($existing{$_}) { - $changed=1; - $maxrow++; - $f{'A'.$maxrow}=$_; - } - } + # Find discrepancies between the course row table and this + # + my %f=&getformulas($safeeval); + my $changed=0; - if ($changed) { &setformulas($safeeval,%f); } - - &setmaxrow($safeeval,$maxrow); - &setrowlabels($safeeval,%current); - - undef %current; - undef %existing; + my $maxrow=0; + my %existing=(); + # Now obsolete rows + foreach (keys(%f)) { + next if ($_!~/^A(\d+)/); + $maxrow=($1>$maxrow)?$1:$maxrow; + my ($usy,$ufn)=split(/\_\_\&\&\&\_\_/,$f{$_}); + $existing{$usy}=1; + unless ((defined($current{$usy})) || (!$1) || + ($f{$_}=~/^(\~\~\~|\-\-\-)/)){ + $f{$_}='!!! Obsolete'; + $changed=1; + } elsif ($ufn) { + $current{$usy} + =~s/assesscalc\?usymb\=/assesscalc\?ufn\=$ufn\&usymb\=/; + } + } + # New and unknown keys + foreach (keys(%current)) { + unless ($existing{$_}) { + $changed=1; + $maxrow++; + $f{'A'.$maxrow}=$_; + } + } + if ($changed) { &setformulas($safeeval,%f); } + &setmaxrow($safeeval,$maxrow); + &setrowlabels($safeeval,%current); + # + undef %current; + undef %existing; } # ------------------------------------------------ Load data for one assessment @@ -1852,46 +1898,40 @@ sub loadstudent { my %c=(); my %f=&getformulas($safeeval); $cachedassess=&getuname($safeeval).':'.&getudom($safeeval); - %cachedstores=(); - { - my $reply=&Apache::lonnet::reply('dump:'.&getudom($safeeval).':'. - &getuname($safeeval).':'. - &getcid($safeeval), - &getuhome($safeeval)); - unless ($reply=~/^error\:/) { - foreach ( split(/\&/,$reply)) { - my ($name,$value)=split(/\=/,$_); - $cachedstores{&Apache::lonnet::unescape($name)}= - &Apache::lonnet::unescape($value); - } - } + # Get ALL the student preformance data + my @tmp = &Apache::lonnet::dump(&getcid($safeeval), + &getudom($safeeval), + &getuname($safeeval), + undef); + if ($tmp[0] !~ /^error:/) { + %cachedstores = @tmp; } + undef @tmp; + # my @assessdata=(); foreach (keys(%f)) { - if ($_=~/^A(\d+)/) { - my $row=$1; - unless (($f{$_}=~/^\!/) || ($row==0)) { - my ($usy,$ufn)=split(/\_\_\&\&\&\_\_/,$f{$_}); - @assessdata=&exportsheet(&getuname($safeeval), - &getudom($safeeval), - 'assesscalc',$usy,$ufn); - 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') { - if ($assessdata[$index]) { - my $col=$_; - if ($assessdata[$index]=~/\D/) { - $c{$col.$row}="'".$assessdata[$index]."'"; - } else { - $c{$col.$row}=$assessdata[$index]; - } - unless ($col eq 'A') { - $f{$col.$row}='import'; - } - } - $index++; - } - } + next if ($_!~/^A(\d+)/); + my $row=$1; + next if (($f{$_}=~/^[\!\~\-]/) || ($row==0)); + my ($usy,$ufn)=split(/__&&&\__/,$f{$_}); + @assessdata=&exportsheet(&getuname($safeeval), + &getudom($safeeval), + 'assesscalc',$usy,$ufn); + 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') { + if ($assessdata[$index]) { + my $col=$_; + if ($assessdata[$index]=~/\D/) { + $c{$col.$row}="'".$assessdata[$index]."'"; + } else { + $c{$col.$row}=$assessdata[$index]; + } + unless ($col eq 'A') { + $f{$col.$row}='import'; + } + } + $index++; } } $cachedassess=''; @@ -1909,7 +1949,7 @@ sub loadcourse { my $total=0; foreach (keys(%f)) { if ($_=~/^A(\d+)/) { - unless ($f{$_}=~/^\!/) { $total++; } + unless ($f{$_}=~/^[\!\~\-]/) { $total++; } } } my $now=0; @@ -1927,35 +1967,33 @@ sub loadcourse { ENDPOP $r->rflush(); foreach (keys(%f)) { - if ($_=~/^A(\d+)/) { - my $row=$1; - unless (($f{$_}=~/^\!/) || ($row==0)) { - my @studentdata=&exportsheet(split(/\:/,$f{$_}), - 'studentcalc'); - undef %userrdatas; - $now++; - $r->print('<script>popwin.document.popremain.remaining.value="'. + next if ($_!~/^A(\d+)/); + my $row=$1; + next if (($f{$_}=~/^[\!\~\-]/) || ($row==0)); + my @studentdata=&exportsheet(split(/\:/,$f{$_}), + 'studentcalc'); + undef %userrdatas; + $now++; + $r->print('<script>popwin.document.popremain.remaining.value="'. $now.'/'.$total.': '.int((time-$since)/$now*($total-$now)). - ' secs remaining";</script>'); - $r->rflush(); - - 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') { - if ($studentdata[$index]) { - my $col=$_; - if ($studentdata[$index]=~/\D/) { - $c{$col.$row}="'".$studentdata[$index]."'"; - } else { - $c{$col.$row}=$studentdata[$index]; - } - unless ($col eq 'A') { - $f{$col.$row}='import'; - } - } - $index++; - } - } + ' secs remaining";</script>'); + $r->rflush(); + # + 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') { + if ($studentdata[$index]) { + my $col=$_; + if ($studentdata[$index]=~/\D/) { + $c{$col.$row}="'".$studentdata[$index]."'"; + } else { + $c{$col.$row}=$studentdata[$index]; + } + unless ($col eq 'A') { + $f{$col.$row}='import'; + } + $index++; + } } } &setformulas($safeeval,%f); @@ -1969,60 +2007,52 @@ ENDPOP sub loadassessment { my $safeeval=shift; - my $uhome=&getuhome($safeeval); - my $uname=&getuname($safeeval); - my $udom=&getudom($safeeval); - my $symb=&getusymb($safeeval); - my $cid=&getcid($safeeval); - my $cnum=&getcnum($safeeval); - my $cdom=&getcdom($safeeval); - my $chome=&getchome($safeeval); + my $uhome = &getuhome($safeeval); + my $uname = &getuname($safeeval); + my $udom = &getudom($safeeval); + my $symb = &getusymb($safeeval); + my $cid = &getcid($safeeval); + my $cnum = &getcnum($safeeval); + my $cdom = &getcdom($safeeval); + my $chome = &getchome($safeeval); my $namespace; unless ($namespace=$cid) { return ''; } - -# ----------------------------------------------------------- Get stored values - - my %returnhash=(); - - if ($cachedassess eq $uname.':'.$udom) { -# -# get data out of the dumped stores -# - - my $version=$cachedstores{'version:'.$symb}; - my $scope; - for ($scope=1;$scope<=$version;$scope++) { - foreach (split(/\:/,$cachedstores{$scope.':keys:'.$symb})) { - $returnhash{$_}=$cachedstores{$scope.':'.$symb.':'.$_}; - } - } - - } else { -# -# restore individual -# - - my $answer=&Apache::lonnet::reply( - "restore:$udom:$uname:". - &Apache::lonnet::escape($namespace).":". - &Apache::lonnet::escape($symb),$uhome); - foreach (split(/\&/,$answer)) { - my ($name,$value)=split(/\=/,$_); - $returnhash{&Apache::lonnet::unescape($name)}= - &Apache::lonnet::unescape($value); - } - my $version; - for ($version=1;$version<=$returnhash{'version'};$version++) { - foreach (split(/\:/,$returnhash{$version.':keys'})) { - $returnhash{$_}=$returnhash{$version.':'.$_}; - } + # Get stored values + my %returnhash=(); + if ($cachedassess eq $uname.':'.$udom) { + # + # get data out of the dumped stores + # + my $version=$cachedstores{'version:'.$symb}; + my $scope; + for ($scope=1;$scope<=$version;$scope++) { + foreach (split(/\:/,$cachedstores{$scope.':keys:'.$symb})) { + $returnhash{$_}=$cachedstores{$scope.':'.$symb.':'.$_}; + } + } + } else { + # + # restore individual + # + my $answer=&Apache::lonnet::reply( + "restore:$udom:$uname:". + &Apache::lonnet::escape($namespace).":". + &Apache::lonnet::escape($symb),$uhome); + foreach (split(/\&/,$answer)) { + my ($name,$value)=split(/\=/,$_); + $returnhash{&Apache::lonnet::unescape($name)}= + &Apache::lonnet::unescape($value); + } + my $version; + for ($version=1;$version<=$returnhash{'version'};$version++) { + foreach (split(/\:/,$returnhash{$version.':keys'})) { + $returnhash{$_}=$returnhash{$version.':'.$_}; + } + } } - } -# ----------------------------- returnhash now has all stores for this resource - -# --------- convert all "_" to "." to be able to use libraries, multiparts, etc - + # returnhash now has all stores for this resource + # convert all "_" to "." to be able to use libraries, multiparts, etc my @oldkeys=keys %returnhash; foreach (@oldkeys) { @@ -2032,88 +2062,82 @@ sub loadassessment { $name=~s/\_/\./g; $returnhash{$name}=$value; } - -# ---------------------------- initialize coursedata and userdata for this user + # initialize coursedata and userdata for this user undef %courseopt; undef %useropt; my $userprefix=$uname.'_'.$udom.'_'; - + unless ($uhome eq 'no_host') { -# -------------------------------------------------------------- Get coursedata - unless - ((time-$courserdatas{$cid.'.last_cache'})<240) { - my $reply=&Apache::lonnet::reply('dump:'.$cdom.':'.$cnum. - ':resourcedata',$chome); - if ($reply!~/^error\:/) { - $courserdatas{$cid}=$reply; - $courserdatas{$cid.'.last_cache'}=time; - } - } - foreach (split(/\&/,$courserdatas{$cid})) { - my ($name,$value)=split(/\=/,$_); - $courseopt{$userprefix.&Apache::lonnet::unescape($name)}= - &Apache::lonnet::unescape($value); - } -# --------------------------------------------------- Get userdata (if present) - unless - ((time-$userrdatas{$uname.'___'.$udom.'.last_cache'})<240) { - my $reply= - &Apache::lonnet::reply('dump:'.$udom.':'.$uname.':resourcedata',$uhome); - if ($reply!~/^error\:/) { - $userrdatas{$uname.'___'.$udom}=$reply; - $userrdatas{$uname.'___'.$udom.'.last_cache'}=time; - } - } - foreach (split(/\&/,$userrdatas{$uname.'___'.$udom})) { - my ($name,$value)=split(/\=/,$_); - $useropt{$userprefix.&Apache::lonnet::unescape($name)}= - &Apache::lonnet::unescape($value); - } + # Get coursedata + unless + ((time-$courserdatas{$cid.'.last_cache'})<240) { + my $reply=&Apache::lonnet::reply('dump:'.$cdom.':'.$cnum. + ':resourcedata',$chome); + if ($reply!~/^error\:/) { + $courserdatas{$cid}=$reply; + $courserdatas{$cid.'.last_cache'}=time; + } + } + foreach (split(/\&/,$courserdatas{$cid})) { + my ($name,$value)=split(/\=/,$_); + $courseopt{$userprefix.&Apache::lonnet::unescape($name)}= + &Apache::lonnet::unescape($value); + } + # Get userdata (if present) + unless + ((time-$userrdatas{$uname.'___'.$udom.'.last_cache'})<240) { + my $reply= + &Apache::lonnet::reply('dump:'.$udom.':'.$uname.':resourcedata',$uhome); + if ($reply!~/^error\:/) { + $userrdatas{$uname.'___'.$udom}=$reply; + $userrdatas{$uname.'___'.$udom.'.last_cache'}=time; + } + } + foreach (split(/\&/,$userrdatas{$uname.'___'.$udom})) { + my ($name,$value)=split(/\=/,$_); + $useropt{$userprefix.&Apache::lonnet::unescape($name)}= + &Apache::lonnet::unescape($value); + } } -# ----------------- now courseopt, useropt initialized for this user and course -# (used by parmval) - -# -# Load keys for this assessment only -# + # now courseopt, useropt initialized for this user and course + # (used by parmval) + # + # Load keys for this assessment only + # my %thisassess=(); my ($symap,$syid,$srcf)=split(/\_\_\_/,$symb); - foreach (split(/\,/,&Apache::lonnet::metadata($srcf,'keys'))) { $thisassess{$_}=1; } -# -# Load parameters -# - my %c=(); - - if (tie(%parmhash,'GDBM_File', - &getcfn($safeeval).'_parms.db',&GDBM_READER,0640)) { - my %f=&getformulas($safeeval); - foreach (keys(%f)) { - if ($_=~/^A/) { - unless ($f{$_}=~/^\!/) { - if ($f{$_}=~/^parameter/) { - if ($thisassess{$f{$_}}) { - my $val=&parmval($f{$_},$safeeval); - $c{$_}=$val; - $c{$f{$_}}=$val; - } - } else { - my $key=$f{$_}; - my $ckey=$key; - $key=~s/^stores\_/resource\./; - $key=~s/\_/\./g; - $c{$_}=$returnhash{$key}; - $c{$ckey}=$returnhash{$key}; - } - } + # + # Load parameters + # + my %c=(); + if (tie(%parmhash,'GDBM_File', + &getcfn($safeeval).'_parms.db',&GDBM_READER(),0640)) { + my %f=&getformulas($safeeval); + foreach (keys(%f)) { + next if ($_!~/^A/); + next if ($f{$_}=~/^[\!\~\-]/); + if ($f{$_}=~/^parameter/) { + if ($thisassess{$f{$_}}) { + my $val=&parmval($f{$_},$safeeval); + $c{$_}=$val; + $c{$f{$_}}=$val; + } + } else { + my $key=$f{$_}; + my $ckey=$key; + $key=~s/^stores\_/resource\./; + $key=~s/\_/\./g; + $c{$_}=$returnhash{$key}; + $c{$ckey}=$returnhash{$key}; + } } + untie(%parmhash); } - untie(%parmhash); - } - &setconstants($safeeval,%c); + &setconstants($safeeval,%c); } # --------------------------------------------------------- Various form fields @@ -2121,7 +2145,7 @@ sub loadassessment { sub textfield { my ($title,$name,$value)=@_; return "\n<p><b>$title:</b><br>". - '<input type=text name="'.$name.'" size=80 value="'.$value.'">'; + '<input type=text name="'.$name.'" size=80 value="'.$value.'">'; } sub hiddenfield { @@ -2178,6 +2202,7 @@ sub checkthis { my ($keyname,$time)=@_; return ($time<$expiredates{$keyname}); } + sub forcedrecalc { my ($uname,$udom,$stype,$usymb)=@_; my $key=$uname.':'.$udom.':'.$stype.':'.$usymb; @@ -2209,131 +2234,122 @@ sub forcedrecalc { # sub exportsheet { - my ($uname,$udom,$stype,$usymb,$fn)=@_; - my @exportarr=(); - - if (($usymb=~/^\_(\w+)/) && (!$fn)) { - $fn='default_'.$1; - } - -# -# Check if cached -# - - my $key=$uname.':'.$udom.':'.$stype.':'.$usymb; - my $found=''; - - if ($oldsheets{$key}) { - foreach (split(/\_\_\_\&\_\_\_/,$oldsheets{$key})) { - my ($name,$value)=split(/\_\_\_\=\_\_\_/,$_); - if ($name eq $fn) { - $found=$value; - } - } - } - - unless ($found) { - &cachedssheets($uname,$udom,&Apache::lonnet::homeserver($uname,$udom)); - if ($oldsheets{$key}) { - foreach (split(/\_\_\_\&\_\_\_/,$oldsheets{$key})) { + my ($uname,$udom,$stype,$usymb,$fn)=@_; + my @exportarr=(); + if (($usymb=~/^\_(\w+)/) && (!$fn)) { + $fn='default_'.$1; + } + # + # Check if cached + # + my $key=$uname.':'.$udom.':'.$stype.':'.$usymb; + my $found=''; + if ($oldsheets{$key}) { + foreach (split(/\_\_\_\&\_\_\_/,$oldsheets{$key})) { my ($name,$value)=split(/\_\_\_\=\_\_\_/,$_); if ($name eq $fn) { - $found=$value; + $found=$value; } - } - } - } -# -# Check if still valid -# - if ($found) { - if (&forcedrecalc($uname,$udom,$stype,$usymb)) { - $found=''; - } - } - - if ($found) { -# -# Return what was cached -# - @exportarr=split(/\_\_\_\;\_\_\_/,$found); - - } else { -# -# Not cached -# - - my $thissheet=&makenewsheet($uname,$udom,$stype,$usymb); - &readsheet($thissheet,$fn); - &updatesheet($thissheet); - &loadrows($thissheet); - &calcsheet($thissheet); - @exportarr=&exportdata($thissheet); -# -# Store now -# - my $cid=$ENV{'request.course.id'}; - my $current=''; - if ($stype eq 'studentcalc') { - $current=&Apache::lonnet::reply('get:'. - $ENV{'course.'.$cid.'.domain'}.':'. - $ENV{'course.'.$cid.'.num'}. - ':nohist_calculatedsheets:'. - &Apache::lonnet::escape($key), - $ENV{'course.'.$cid.'.home'}); - } else { - $current=&Apache::lonnet::reply('get:'. - &getudom($thissheet).':'. - &getuname($thissheet). - ':nohist_calculatedsheets_'. - $ENV{'request.course.id'}.':'. - &Apache::lonnet::escape($key), - &getuhome($thissheet)); - + } } - my %currentlystored=(); - unless ($current=~/^error\:/) { - foreach (split(/\_\_\_\&\_\_\_/,&Apache::lonnet::unescape($current))) { - my ($name,$value)=split(/\_\_\_\=\_\_\_/,$_); - $currentlystored{$name}=$value; - } + unless ($found) { + &cachedssheets($uname,$udom,&Apache::lonnet::homeserver($uname,$udom)); + if ($oldsheets{$key}) { + foreach (split(/\_\_\_\&\_\_\_/,$oldsheets{$key})) { + my ($name,$value)=split(/\_\_\_\=\_\_\_/,$_); + if ($name eq $fn) { + $found=$value; + } + } + } } - $currentlystored{$fn}=join('___;___',@exportarr); - - my $newstore=''; - foreach (keys(%currentlystored)) { - if ($newstore) { $newstore.='___&___'; } - $newstore.=$_.'___=___'.$currentlystored{$_}; + # + # Check if still valid + # + if ($found) { + if (&forcedrecalc($uname,$udom,$stype,$usymb)) { + $found=''; + } + } + if ($found) { + # + # Return what was cached + # + @exportarr=split(/\_\_\_\;\_\_\_/,$found); + } else { + # + # Not cached + # + my $thissheet=&makenewsheet($uname,$udom,$stype,$usymb); + &readsheet($thissheet,$fn); + &updatesheet($thissheet); + &loadrows($thissheet); + &calcsheet($thissheet); + @exportarr=&exportdata($thissheet); + # + # Store now + # + my $cid=$ENV{'request.course.id'}; + my $current=''; + if ($stype eq 'studentcalc') { + $current=&Apache::lonnet::reply('get:'. + $ENV{'course.'.$cid.'.domain'}.':'. + $ENV{'course.'.$cid.'.num'}. + ':nohist_calculatedsheets:'. + &Apache::lonnet::escape($key), + $ENV{'course.'.$cid.'.home'}); + } else { + $current=&Apache::lonnet::reply('get:'. + &getudom($thissheet).':'. + &getuname($thissheet). + ':nohist_calculatedsheets_'. + $ENV{'request.course.id'}.':'. + &Apache::lonnet::escape($key), + &getuhome($thissheet)); + } + my %currentlystored=(); + unless ($current=~/^error\:/) { + foreach (split(/___&\___/,&Apache::lonnet::unescape($current))) { + my ($name,$value)=split(/___=___/,$_); + $currentlystored{$name}=$value; + } + } + $currentlystored{$fn}=join('___;___',@exportarr); + # + my $newstore=''; + foreach (keys(%currentlystored)) { + if ($newstore) { $newstore.='___&___'; } + $newstore.=$_.'___=___'.$currentlystored{$_}; + } + my $now=time; + if ($stype eq 'studentcalc') { + &Apache::lonnet::reply('put:'. + $ENV{'course.'.$cid.'.domain'}.':'. + $ENV{'course.'.$cid.'.num'}. + ':nohist_calculatedsheets:'. + &Apache::lonnet::escape($key).'='. + &Apache::lonnet::escape($newstore).'&'. + &Apache::lonnet::escape($key).'.time='.$now, + $ENV{'course.'.$cid.'.home'}); + } else { + &Apache::lonnet::reply('put:'. + &getudom($thissheet).':'. + &getuname($thissheet). + ':nohist_calculatedsheets_'. + $ENV{'request.course.id'}.':'. + &Apache::lonnet::escape($key).'='. + &Apache::lonnet::escape($newstore).'&'. + &Apache::lonnet::escape($key).'.time='.$now, + &getuhome($thissheet)); + } } - my $now=time; - if ($stype eq 'studentcalc') { - &Apache::lonnet::reply('put:'. - $ENV{'course.'.$cid.'.domain'}.':'. - $ENV{'course.'.$cid.'.num'}. - ':nohist_calculatedsheets:'. - &Apache::lonnet::escape($key).'='. - &Apache::lonnet::escape($newstore).'&'. - &Apache::lonnet::escape($key).'.time='.$now, - $ENV{'course.'.$cid.'.home'}); - } else { - &Apache::lonnet::reply('put:'. - &getudom($thissheet).':'. - &getuname($thissheet). - ':nohist_calculatedsheets_'. - $ENV{'request.course.id'}.':'. - &Apache::lonnet::escape($key).'='. - &Apache::lonnet::escape($newstore).'&'. - &Apache::lonnet::escape($key).'.time='.$now, - &getuhome($thissheet)); - } - } - return @exportarr; + return @exportarr; } + # ============================================================ Expiration Dates # # Load previously cached student spreadsheets for this course # - sub expirationdates { undef %expiredates; my $cid=$ENV{'request.course.id'}; @@ -2410,59 +2426,45 @@ sub cachedssheets { sub handler { my $r=shift; - if ($r->header_only) { - $r->content_type('text/html'); - $r->send_http_header; - return OK; - } - -# ---------------------------------------------------- Global directory configs - -$includedir=$r->dir_config('lonIncludes'); -$tmpdir=$r->dir_config('lonDaemons').'/tmp/'; - -# ----------------------------------------------------- Needs to be in a course - - if ($ENV{'request.course.fn'}) { - -# --------------------------- Get query string for limited number of parameters - - &Apache::loncommon::get_unprocessed_cgi($ENV{'QUERY_STRING'}, - ['uname','udom','usymb','ufn']); - - if (($ENV{'form.usymb'}=~/^\_(\w+)/) && (!$ENV{'form.ufn'})) { - $ENV{'form.ufn'}='default_'.$1; - } - -# -------------------------------------- Interactive loading of specific sheet? - if (($ENV{'form.load'}) && ($ENV{'form.loadthissheet'} ne 'Default')) { - $ENV{'form.ufn'}=$ENV{'form.loadthissheet'}; - } -# ------------------------------------------- Nothing there? Must be login user - - my $aname; - my $adom; - - unless ($ENV{'form.uname'}) { - $aname=$ENV{'user.name'}; - $adom=$ENV{'user.domain'}; - } else { - $aname=$ENV{'form.uname'}; - $adom=$ENV{'form.udom'}; - } - -# ------------------------------------------------------------------- Open page - - $r->content_type('text/html'); - $r->header_out('Cache-control','no-cache'); - $r->header_out('Pragma','no-cache'); - $r->send_http_header; - -# --------------------------------------------------------------- Screen output - - $r->print('<html><head><title>LON-CAPA Spreadsheet</title>'); - $r->print(<<ENDSCRIPT); + $r->content_type('text/html'); + $r->send_http_header; + return OK; + } + # Global directory configs + $includedir=$r->dir_config('lonIncludes'); + $tmpdir=$r->dir_config('lonDaemons').'/tmp/'; + # Needs to be in a course + if ($ENV{'request.course.fn'}) { + # Get query string for limited number of parameters + &Apache::loncommon::get_unprocessed_cgi + ($ENV{'QUERY_STRING'},['uname','udom','usymb','ufn']); + if (($ENV{'form.usymb'}=~/^\_(\w+)/) && (!$ENV{'form.ufn'})) { + $ENV{'form.ufn'}='default_'.$1; + } + # Interactive loading of specific sheet? + if (($ENV{'form.load'}) && ($ENV{'form.loadthissheet'} ne 'Default')) { + $ENV{'form.ufn'}=$ENV{'form.loadthissheet'}; + } + # Nothing there? Must be login user + my $aname; + my $adom; + + unless ($ENV{'form.uname'}) { + $aname=$ENV{'user.name'}; + $adom=$ENV{'user.domain'}; + } else { + $aname=$ENV{'form.uname'}; + $adom=$ENV{'form.udom'}; + } + # Open page + $r->content_type('text/html'); + $r->header_out('Cache-control','no-cache'); + $r->header_out('Pragma','no-cache'); + $r->send_http_header; + # Screen output + $r->print('<html><head><title>LON-CAPA Spreadsheet</title>'); + $r->print(<<ENDSCRIPT); <script language="JavaScript"> function celledit(cn,cf) { @@ -2488,194 +2490,155 @@ $tmpdir=$r->dir_config('lonDaemons').'/t </script> ENDSCRIPT - $r->print('</head><body bgcolor="#FFFFFF">'. - '<img align=right src=/adm/lonIcons/lonlogos.gif>'. - '<h1>LON-CAPA Spreadsheet</h1>'. - '<form action="'.$r->uri.'" name=sheet method=post>'. - &hiddenfield('uname',$ENV{'form.uname'}). - &hiddenfield('udom',$ENV{'form.udom'}). - &hiddenfield('usymb',$ENV{'form.usymb'}). - &hiddenfield('unewfield',''). - &hiddenfield('unewformula','')); - -# ---------------------- Make sure that this gets out, even if user hits "stop" - - $r->rflush(); - -# ---------------------------------------------------------------- Full recalc? - - - if ($ENV{'form.forcerecalc'}) { - $r->print('<h4>Completely Recalculating Sheet ...</h4>'); - undef %spreadsheets; - undef %courserdatas; - undef %userrdatas; - undef %defaultsheets; - undef %updatedata; - } - -# ---------------------------------------- Read new sheet or modified worksheet - - $r->uri=~/\/(\w+)$/; - - my $asheet=&makenewsheet($aname,$adom,$1,$ENV{'form.usymb'}); - -# ------------------------ If a new formula had been entered, go from work copy - - if ($ENV{'form.unewfield'}) { - $r->print('<h2>Modified Workcopy</h2>'); - $ENV{'form.unewformula'}=~s/\'/\"/g; - $r->print('<p>New formula: '.$ENV{'form.unewfield'}.'='. - $ENV{'form.unewformula'}.'<p>'); - &setfilename($asheet,$ENV{'form.ufn'}); - &tmpread($asheet, - $ENV{'form.unewfield'},$ENV{'form.unewformula'}); - - } elsif ($ENV{'form.saveas'}) { - &setfilename($asheet,$ENV{'form.ufn'}); - &tmpread($asheet); - } else { - &readsheet($asheet,$ENV{'form.ufn'}); - } - -# -------------------------------------------------- Print out user information - - unless (&gettype($asheet) eq 'classcalc') { - $r->print('<p><b>User:</b> '.&getuname($asheet). - '<br><b>Domain:</b> '.&getudom($asheet)); - if (&getcsec($asheet) eq '-1') { - $r->print('<h3><font color=red>'. - 'Not a student in this course</font></h3>'); + $r->print('</head>'.&Apache::loncommon::bodytag('Grades Spreadsheet'). + '<form action="'.$r->uri.'" name=sheet method=post>'. + &hiddenfield('uname',$ENV{'form.uname'}). + &hiddenfield('udom',$ENV{'form.udom'}). + &hiddenfield('usymb',$ENV{'form.usymb'}). + &hiddenfield('unewfield',''). + &hiddenfield('unewformula','')); + # Send this out right away + $r->rflush(); + # Full recalc? + if ($ENV{'form.forcerecalc'}) { + $r->print('<h4>Completely Recalculating Sheet ...</h4>'); + undef %spreadsheets; + undef %courserdatas; + undef %userrdatas; + undef %defaultsheets; + undef %updatedata; + } + # Read new sheet or modified worksheet + $r->uri=~/\/(\w+)$/; + my $asheet=&makenewsheet($aname,$adom,$1,$ENV{'form.usymb'}); + # If a new formula had been entered, go from work copy + if ($ENV{'form.unewfield'}) { + $r->print('<h2>Modified Workcopy</h2>'); + $ENV{'form.unewformula'}=~s/\'/\"/g; + $r->print('<p>New formula: '.$ENV{'form.unewfield'}.'='. + $ENV{'form.unewformula'}.'<p>'); + &setfilename($asheet,$ENV{'form.ufn'}); + &tmpread($asheet, + $ENV{'form.unewfield'},$ENV{'form.unewformula'}); + + } elsif ($ENV{'form.saveas'}) { + &setfilename($asheet,$ENV{'form.ufn'}); + &tmpread($asheet); } else { - $r->print('<br><b>Section/Group:</b> '.&getcsec($asheet)); + &readsheet($asheet,$ENV{'form.ufn'}); } - if ($ENV{'form.usymb'}) { - $r->print('<br><b>Assessment:</b> <tt>'.$ENV{'form.usymb'}.'</tt>'); + # Print out user information + unless (&gettype($asheet) eq 'classcalc') { + $r->print('<p><b>User:</b> '.&getuname($asheet). + '<br><b>Domain:</b> '.&getudom($asheet)); + if (&getcsec($asheet) eq '-1') { + $r->print('<h3><font color=red>'. + 'Not a student in this course</font></h3>'); + } else { + $r->print('<br><b>Section/Group:</b> '.&getcsec($asheet)); + } + if ($ENV{'form.usymb'}) { + $r->print('<br><b>Assessment:</b> <tt>'. + $ENV{'form.usymb'}.'</tt>'); + } } - } - -# ---------------------------------------------------------------- Course title - - $r->print('<h1>'. - $ENV{'course.'.$ENV{'request.course.id'}.'.description'}. - '</h1><h3>'.localtime().'</h3>'); - -# ---------------------------------------------------- See if user can see this - - if ((&gettype($asheet) eq 'classcalc') || - (&getuname($asheet) ne $ENV{'user.name'}) || - (&getudom($asheet) ne $ENV{'user.domain'})) { - unless (&Apache::lonnet::allowed('vgr',&getcid($asheet))) { - $r->print( - '<h1>Access Permission Denied</h1></form></body></html>'); - return OK; + # See if user can see this + if ((&gettype($asheet) eq 'classcalc') || + (&getuname($asheet) ne $ENV{'user.name'}) || + (&getudom($asheet) ne $ENV{'user.domain'})) { + unless (&Apache::lonnet::allowed('vgr',&getcid($asheet))) { + $r->print('<h1>Access Permission Denied</h1>'. + '</form></body></html>'); + return OK; + } } - } - -# ---------------------------------------------------------- Additional options - - $r->print( + # Additional options + $r->print( '<input type=submit name=forcerecalc value="Completely Recalculate Sheet"><p>' - ); - if (&gettype($asheet) eq 'assesscalc') { - $r->print ('<p><font size=+2><a href="/adm/studentcalc?uname='. - &getuname($asheet). - '&udom='.&getudom($asheet). - '">Level up: Student Sheet</a></font><p>'); - } - - if ((&gettype($asheet) eq 'studentcalc') && - (&Apache::lonnet::allowed('vgr',&getcid($asheet)))) { - $r->print ( - '<p><font size=+2><a href="/adm/classcalc">'. - 'Level up: Course Sheet</a></font><p>'); - } - - -# ----------------------------------------------------------------- Save dialog - - - if (&Apache::lonnet::allowed('opa',$ENV{'request.course.id'})) { - my $fname=$ENV{'form.ufn'}; - $fname=~s/\_[^\_]+$//; - if ($fname eq 'default') { $fname='course_default'; } - $r->print('<input type=submit name=saveas value="Save as ...">'. - '<input type=text size=20 name=newfn value="'.$fname. - '"> (make default: <input type=checkbox name="makedefufn">)<p>'); - } - - $r->print(&hiddenfield('ufn',&getfilename($asheet))); - -# ----------------------------------------------------------------- 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($asheet,&gettype($asheet))) { - $r->print('<option name="'.$_.'"'); - if ($ENV{'form.ufn'} eq $_) { - $r->print(' selected'); + ); + if (&gettype($asheet) eq 'assesscalc') { + $r->print ('<p><font size=+2><a href="/adm/studentcalc?uname='. + &getuname($asheet).'&udom='.&getudom($asheet).'">'. + 'Level up: Student Sheet</a></font><p>'); + } + if ((&gettype($asheet) eq 'studentcalc') && + (&Apache::lonnet::allowed('vgr',&getcid($asheet)))) { + $r->print ( + '<p><font size=+2><a href="/adm/classcalc">'. + 'Level up: Course Sheet</a></font><p>'); + } + # Save dialog + if (&Apache::lonnet::allowed('opa',$ENV{'request.course.id'})) { + my $fname=$ENV{'form.ufn'}; + $fname=~s/\_[^\_]+$//; + if ($fname eq 'default') { $fname='course_default'; } + $r->print + ('<input type=submit name=saveas value="Save as ...">'. + '<input type=text size=20 name=newfn value="'.$fname.'">'. + '(make default: <input type=checkbox name="makedefufn">)<p>'); + } + $r->print(&hiddenfield('ufn',&getfilename($asheet))); + # 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($asheet,&gettype($asheet))) { + $r->print('<option name="'.$_.'"'); + if ($ENV{'form.ufn'} eq $_) { + $r->print(' selected'); + } + $r->print('>'.$_.'</option>'); + } + $r->print('</select><p>'); + if (&gettype($asheet) eq 'studentcalc') { + &setothersheets($asheet,&othersheets($asheet,'assesscalc')); } - $r->print('>'.$_.'</option>'); - } - $r->print('</select><p>'); - if (&gettype($asheet) eq 'studentcalc') { - &setothersheets($asheet,&othersheets($asheet,'assesscalc')); } - } - -# --------------------------------------------------------------- Cached sheets - - &expirationdates(); - - undef %oldsheets; - undef %loadedcaches; - - if (&gettype($asheet) eq 'classcalc') { - $r->print("Loading previously calculated student sheets ...<br>\n"); + # Cached sheets + &expirationdates(); + undef %oldsheets; + undef %loadedcaches; + if (&gettype($asheet) eq 'classcalc') { + $r->print + ("Loading previously calculated student sheets ...<br>\n"); + $r->rflush(); + &cachedcsheets(); + } elsif (&gettype($asheet) eq 'studentcalc') { + $r->print + ("Loading previously calculated assessment sheets ...<br>\n"); + $r->rflush(); + &cachedssheets(&getuname($asheet),&getudom($asheet), + &getuhome($asheet)); + } + # Update sheet, load rows + $r->print("Loaded sheet(s), updating rows ...<br>\n"); $r->rflush(); - &cachedcsheets(); - } elsif (&gettype($asheet) eq 'studentcalc') { - $r->print("Loading previously calculated assessment sheets ...<br>\n"); + # + &updatesheet($asheet); + $r->print("Updated rows, loading row data ...<br>\n"); $r->rflush(); - &cachedssheets(&getuname($asheet),&getudom($asheet), - &getuhome($asheet)); - } - -# ----------------------------------------------------- Update sheet, load rows - - $r->print("Loaded sheet(s), updating rows ...<br>\n"); - $r->rflush(); - - &updatesheet($asheet); - - $r->print("Updated rows, loading row data ...<br>\n"); - $r->rflush(); - - &loadrows($asheet,$r); - - $r->print("Loaded row data, calculating sheet ...<br>\n"); - $r->rflush(); - - my $calcoutput=&calcsheet($asheet); - $r->print('<h3><font color=red>'.$calcoutput.'</h3></font>'); - -# ---------------------------------------------------- See if something to save - - if (&Apache::lonnet::allowed('opa',$ENV{'request.course.id'})) { - my $fname=''; - if ($ENV{'form.saveas'} && ($fname=$ENV{'form.newfn'})) { - $fname=~s/\W/\_/g; - if ($fname eq 'default') { $fname='course_default'; } - $fname.='_'.&gettype($asheet); - &setfilename($asheet,$fname); - $ENV{'form.ufn'}=$fname; - $r->print('<p>Saving spreadsheet: '. - &writesheet($asheet,$ENV{'form.makedefufn'}).'<p>'); - } - } - -# ------------------------------------------------ Write the modified worksheet + # + &loadrows($asheet,$r); + $r->print("Loaded row data, calculating sheet ...<br>\n"); + $r->rflush(); + # + my $calcoutput=&calcsheet($asheet); + $r->print('<h3><font color=red>'.$calcoutput.'</h3></font>'); + # See if something to save + if (&Apache::lonnet::allowed('opa',$ENV{'request.course.id'})) { + my $fname=''; + if ($ENV{'form.saveas'} && ($fname=$ENV{'form.newfn'})) { + $fname=~s/\W/\_/g; + if ($fname eq 'default') { $fname='course_default'; } + $fname.='_'.&gettype($asheet); + &setfilename($asheet,$fname); + $ENV{'form.ufn'}=$fname; + $r->print('<p>Saving spreadsheet: '. + &writesheet($asheet,$ENV{'form.makedefufn'}).'<p>'); + } + } + #Write the modified worksheet $r->print('<b>Current sheet:</b> '.&getfilename($asheet).'<p>'); @@ -2711,6 +2674,9 @@ ENDSCRIPT } # ------------------------------------------------------------------ Insertrows + $r->print(' Student Status: '. + &Apache::lonhtmlcommon::StatusOptions + ($ENV{'form.Status'},'sheet')); $r->print(<<ENDINSERTBUTTONS); <br>