--- loncom/interface/Attic/lonspreadsheet.pm 2000/11/15 10:37:27 1.1 +++ loncom/interface/Attic/lonspreadsheet.pm 2000/12/05 15:09:22 1.5 @@ -1,22 +1,44 @@ # The LearningOnline Network with CAPA # Spreadsheet/Grades Display Handler # -# 11/11,11/15 Gerd Kortemeyer +# 11/11,11/15,11/27,12/04,12/05 Gerd Kortemeyer package Apache::lonspreadsheet; use strict; use Safe; +use Safe::Hole; use Opcode; -use vars qw(%v %t %f); use Apache::lonnet; use Apache::Constants qw(:common); +use HTML::TokeParser; -sub deffunc { - my $safeeval=shift; +# ============================================================================= +# ===================================== Implements an instance of a spreadsheet + +sub initsheet { + my $safeeval = new Safe; + my $safehole = new Safe::Hole; + $safeeval->permit("entereval"); + $safeeval->permit(":base_math"); + $safeeval->permit("sort"); + $safeeval->deny(":base_io"); + $safehole->wrap(\&Apache::lonnet::EXT,$safeeval,'&EXT'); my $code=<<'ENDDEFS'; # ---------------------------------------------------- Inside of the safe space +# +# f: formulas +# t: intermediate format (variable references expanded) +# v: output values +# + +%v=(); +%t=(); +%f=(); +$sheettype=''; +$filename=''; + sub mask { my ($lower,$upper)=@_; @@ -81,10 +103,9 @@ sub mask { } } } - return '^'.$alpha.$num.'$'; + return '^'.$alpha.$num."\$"; } - sub NUM { my $mask=mask(@_); my $num=0; @@ -205,12 +226,6 @@ sub SUMMIN { return $sum; } - -# ------------------------------------------- End of "Inside of the safe space" -ENDDEFS - $safeeval->reval($code); -} - sub sett { %t=(); map { @@ -222,16 +237,16 @@ sub sett { } keys %f; } -sub calcv { - my $safeeval=shift; +sub calc { %v=(); + &sett(); my $notfinished=1; my $depth=0; while ($notfinished) { $notfinished=0; map { my $old=$v{$_}; - $v{$_}=$safeeval->reval($t{$_}); + $v{$_}=eval($t{$_}); if ($@) { %v=(); return $@; @@ -247,41 +262,221 @@ sub calcv { return ''; } +# ------------------------------------------- End of "Inside of the safe space" +ENDDEFS + $safeeval->reval($code); + return $safeeval; +} + +# ------------------------------------------------ Add or change formula values + +sub setformulas { + my ($safeeval,@f)=@_; + $safeeval->reval('%f=(%f,'."('".join("','",@f)."'));"); +} + +# ------------------------------------------------------- Calculate spreadsheet + +sub calcsheet { + my $safeeval=shift; + $safeeval->reval('&calc();'); +} + +# ------------------------------------------------------------------ Get values + +sub getvalues { + my $safeeval=shift; + return $safeeval->reval('%v'); +} + +# ---------------------------------------------------------------- Get formulas + +sub getformulas { + my $safeeval=shift; + return $safeeval->reval('%f'); +} + +# -------------------------------------------------------------------- Set type + +sub settype { + my ($safeeval,$type)=@_; + $safeeval->reval('$sheettype='.$type.';'); +} + +# -------------------------------------------------------------------- Get type + +sub gettype { + my $safeeval=shift; + return $safeeval->reval('$sheettype'); +} + +# -------------------------------------------------------------------- Set type + +sub setfilename { + my ($safeeval,$fn)=@_; + $safeeval->reval('$filename='.$fn.';'); +} + +# -------------------------------------------------------------------- Get type + +sub getfilename { + my $safeeval=shift; + return $safeeval->reval('$filename'); +} + +# ========================================================== End of Spreadsheet +# ============================================================================= + + + +# --------------------------------------- Read spreadsheet formulas from a file + +sub readsheet { + my ($safeeval,$fn)=shift; + &setfilename($safeeval,$fn); + $fn=~/\.(\w+)/; + &settype($safeeval,$1); + my %f=(); + my $content; + { + my $fh=Apache::File->new($fn); + $content=join('',<$fh>); + } + { + my $parser=HTML::TokeParser->new(\$content); + my $token; + while ($token=$parser->get_token) { + if ($token->[0] eq 'S') { + if ($token->[1] eq 'field') { + $f{$token->[2]->{'col'}.$token->[2]->{'row'}}= + $parser->get_text('/field'); + } + } + } + } + &setformulas($safeeval,%f); +} + +# --------------------------------------------------------------- Read metadata + +sub readmeta { + my $fn=shift; + unless ($fn=~/\.meta$/) { $fn.='meta'; } + my $content; + my %returnhash=(); + { + my $fh=Apache::File->new($fn); + $content=join('',<$fh>); + } + my $parser=HTML::TokeParser->new(\$content); + my $token; + while ($token=$parser->get_token) { + if ($token->[0] eq 'S') { + my $entry=$token->[1]; + if (($entry eq 'stores') || ($entry eq 'parameter')) { + my $unikey=$entry; + $unikey.='_'.$token->[2]->{'part'}; + $unikey.='_'.$token->[2]->{'name'}; + $returnhash{$unikey}=$token->[2]->{'display'}; + } + } + } + return %returnhash; +} + +# ----------------------------------------------------------------- Update rows + +sub updaterows { + my $safeeval=shift; + my %bighash; +# -------------------------------------------------------------------- Tie hash + if (tie(%bighash,'GDBM_File',$ENV{'request.course.fn'}.'.db', + &GDBM_READER,0640)) { +# --------------------------------------------------------- Get all assessments + + my %allkeys=(); + my %allassess=(); + + my $stype=&gettype($safeeval); + + map { + 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}=$bighash{'title_'.$id}; + if ($stype eq 'assesssheet') { + map { + if ($_=~/^stores\_(.*)/) { + my $key=$_; + my $display= + &Apache::lonnet::metadata($srcf,$key.'.display'); + unless ($display) { + $display= + &Apache::lonnet::metadata($srcf,$key.'.name'); + } + $allkeys{$key}=$display; + } + } split(/\,/,&Apache::lonnet::metadata($srcf,'keys')); + } + } + } + } keys %bighash; + untie(%bighash); + +# +# %allkeys has a list of storage displays by unikey +# %allassess has a list of all resource displays by symb +# +# -------------------- Find discrepancies between the course row table and this +# + my %f=&getformulas($safeeval); + map { + if ($_=~/^A/) { + if ($stype eq 'assesssheet') { + } elsif ($stype eq 'coursesheet') { + } + } + } keys %f; +# ------------------------------------------------ Find new and obsolete values + + } else { + return 'Could not access course data'; + } +} + +# ----------------------------------------------------------------------------- + sub handler { - %v=(); - %t=(); - %f=(); - my $safeeval = new Safe; - $safeeval->permit("entereval"); - $safeeval->permit(":base_math"); - $safeeval->permit("sort"); - $safeeval->deny(":base_io"); -# $safeeval->share_from('Apache::lonnet',['&EXT']); - $safeeval->share('%v','%t','%f'); - &deffunc($safeeval); - $f{'A3'}=5; - $f{'A4'}=3; - $f{'A5'}=8; - $f{'E100'}=5; - $f{'C3'}='A3+6'; - $f{'B4'}='8+int(C3/3)'; - $f{'C7'}='A3+B4'; - $f{'G8'}='MEAN("E*")'; - $f{'G5'}='A3+SUMMIN(2,"A*")'; - $f{'G6'}='A3+SUM("A*")'; - $f{'G7'}='STDDEV("A*")'; - $f{'G9'}='NUM("G*")'; - $f{'H10'}='MEAN("E*")'; - $f{'G10'}='BIN(3,5,"A*")'; - &sett(); - print &calcv($safeeval)."\n"; - print $v{'C7'}."\n"; - print $t{'G5'}.' - '.$v{'G5'}."\n"; - print $t{'G6'}.' - '.$v{'G6'}."\n"; - print $t{'G7'}.' - '.$v{'G7'}."\n"; - print $t{'G8'}.' - '.$v{'G8'}."\n"; - print $t{'G9'}.' - '.$v{'G9'}."\n"; - print $t{'G10'}.' - '.$v{'G10'}."\n"; + + my $r=shift; + + $r->content_type('text/html'); + $r->send_http_header; + + $r->print('LON-CAPA Spreadsheet'); + $r->print(''); + + my $sheetone=initsheet(); + + &setformulas($sheetone,('A1' => '5', 'B2' => '6', 'C4' => 'A1+B2')); + $r->print(&calcsheet($sheetone)); + my %output=&getformulas($sheetone); + + $r->print('FORM:'.$output{'A1'}.' '.$output{'B2'}.' '.$output{'C4'}); + + my %output=&getvalues($sheetone); + + $r->print('
OUT:'.$output{'A1'}.' '.$output{'B2'}.' '.$output{'C4'}); + + $r->print(''); + return OK; } 1;