--- loncom/interface/Attic/lonspreadsheet.pm 2000/12/12 16:48:21 1.15 +++ loncom/interface/Attic/lonspreadsheet.pm 2000/12/30 21:33:11 1.22 @@ -2,7 +2,7 @@ # Spreadsheet/Grades Display Handler # # 11/11,11/15,11/27,12/04,12/05,12/06,12/07, -# 12/08,12/09,12/11,12/12 Gerd Kortemeyer +# 12/08,12/09,12/11,12/12,12/15,12/16,12/18,12/19,12/30 Gerd Kortemeyer package Apache::lonspreadsheet; @@ -12,8 +12,8 @@ use Safe::Hole; use Opcode; use Apache::lonnet; use Apache::Constants qw(:common :http); -use HTML::TokeParser; use GDBM_File; +use HTML::TokeParser; # # These cache hashes need to be independent of user, resource and course @@ -260,9 +260,34 @@ sub SUMMIN { sub sett { %t=(); + my $pattern=''; + if ($sheettype eq 'assesscalc') { + $pattern='A'; + } else { + $pattern='[A-Z]'; + } + map { + if ($_=~/template\_(\w)/) { + my $col=$1; + unless ($col=~/^$pattern/) { + map { + if ($_=~/A(\d+)/) { + my $trow=$1; + if ($trow) { + my $lb=$col.$trow; + $t{$lb}=$f{'template_'.$col}; + $t{$lb}=~s/\#/$trow/g; + $t{$lb}=~s/\.\.+/\,/g; + $t{$lb}=~s/(^|[^\"\'])([A-Za-z]\d+)/$1\$v\{\'$2\'\}/g; + } + } + } keys %f; + } + } + } keys %f; map { - if ($f{$_}) { - if ($_=~/^A/) { + if (($f{$_}) && ($_!~/template\_/)) { + if ($_=~/^$pattern/) { unless ($f{$_}=~/^\!/) { $t{$_}=$c{$_}; } @@ -273,6 +298,9 @@ sub sett { } } } keys %f; + $t{'A0'}=$f{'A0'}; + $t{'A0'}=~s/\.\.+/\,/g; + $t{'A0'}=~s/(^|[^\"\'])([A-Za-z]\d+)/$1\$v\{\'$2\'\}/g; } sub calc { @@ -300,6 +328,39 @@ sub calc { return ''; } +sub templaterow { + my @cols=(); + $cols[0]='Template'; + map { + my $fm=$f{'template_'.$_}; + $fm=~s/[\'\"]/\&\#34;/g; + $cols[$#cols+1]="'template_$_','$fm'".'___eq___'.$fm; + } ('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'); + return @cols; +} + +sub outrowassess { + my $n=shift; + my @cols=(); + if ($n) { + $cols[0]=$rl{$f{'A'.$n}}; + } else { + $cols[0]='Export'; + } + map { + my $fm=$f{$_.$n}; + $fm=~s/[\'\"]/\&\#34;/g; + $cols[$#cols+1]="'$_$n','$fm'".'___eq___'.$v{$_.$n}; + } ('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'); + return @cols; +} + sub outrow { my $n=shift; my @cols=(); @@ -322,10 +383,10 @@ sub outrow { sub exportrowa { my $rowa=''; map { - $rowa.=$v{$_.'0'}."','"; + $rowa.=$v{$_.'0'}."___;___"; } ('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'); - $rowa=~s/\'\,\'$//; + $rowa=~s/\_\_\_\;\_\_\_$//; return $rowa; } @@ -433,16 +494,31 @@ sub exportrow { sub rown { my ($safeeval,$n)=@_; - my $defaultbg=((($n-1)/5)==int(($n-1)/5))?'#E0E0':'#FFFF'; + my $defaultbg; + unless ($n eq '-') { + $defaultbg=((($n-1)/5)==int(($n-1)/5))?'#E0E0':'#FFFF'; + } else { + $defaultbg='#E0FF'; + } my $rowdata="\n$n"; my $showf=0; + my $proc; + my $maxred; + if (&gettype($safeeval) eq 'assesscalc') { + $proc='&outrowassess'; + $maxred=1; + } else { + $proc='&outrow'; + $maxred=26; + } + if ($n eq '-') { $proc='&templaterow'; $n=-1; } map { my $bgcolor=$defaultbg.((($showf-1)/5==int(($showf-1)/5))?'99':'DD'); my ($fm,$vl)=split(/\_\_\_eq\_\_\_/,$_); if ($showf==0) { $vl=$_; } - if ($showf<=1) { $bgcolor='#FFDDDD'; } + if ($showf<=$maxred) { $bgcolor='#FFDDDD'; } if (($n==0) && ($showf<=26)) { $bgcolor='#CCCCFF'; } - if ($showf>1) { + if (($showf>$maxred) || ((!$n) && ($showf>0))) { if ($vl eq '') { $vl='#'; } @@ -453,7 +529,7 @@ sub rown { $rowdata.=' '.$vl.' '; } $showf++; - } $safeeval->reval('&outrow('.$n.')'); + } $safeeval->reval($proc.'('.$n.')'); return $rowdata.''; } @@ -461,17 +537,42 @@ sub rown { sub outsheet { my $safeeval=shift; - my $tabledata=''. - ''; + my $maxred; + my $realm; + if (&gettype($safeeval) eq 'assesscalc') { + $maxred=1; + $realm='Assessment'; + } elsif (&gettype($safeeval) eq 'studentcalc') { + $maxred=26; + $realm='User'; + } else { + $maxred=26; + $realm='Course'; + } + my $maxyellow=52-$maxred; + my $tabledata='
 A Import
'. + ''. + ''; + my $showf=0; map { - $tabledata.=""; - } ('B','C','D','E','F','G','H','I','J','K','L','M', + $showf++; + if ($showf<=$maxred) { + $tabledata.='"; + } ('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'); $tabledata.=''; my $row; my $maxrow=&getmaxrow($safeeval); + $tabledata.=&rown($safeeval,'-'); for ($row=0;$row<=$maxrow;$row++) { $tabledata.=&rown($safeeval,$row); } @@ -480,43 +581,95 @@ sub outsheet { -# --------------------------------------- Read spreadsheet formulas from a file +# ------------------------------------- Read spreadsheet formulas from a course sub readsheet { - my ($safeeval,$fn)=@_; - &setfilename($safeeval,$fn); - $fn=~/\.(\w+)/; - &settype($safeeval,$1); + my ($safeeval,$fn,$r)=@_; my %f=(); - unless ($spreadsheets{$fn}) { - $spreadsheets{$fn}=''; + if (($fn eq '') || ($fn=~/^default\_/)) { + my $sheetxml=''; { my $fh; - if ($fh=Apache::File->new($fn)) { - $spreadsheets{$fn}=join('',<$fh>); - } + if ($fh=Apache::File->new($r->dir_config('lonIncludes'). + '/default.'.&gettype($safeeval))) { + $sheetxml=join('',<$fh>); + } } + my $parser=HTML::TokeParser->new(\$sheetxml); + 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'); + } + if ($token->[1] eq 'template') { + $f{'template_'.$token->[2]->{'col'}}= + $parser->get_text('/template'); + } + } + } + &setfilename($safeeval,'default_'.&gettype($safeeval)); + } else { + &setfilename($safeeval,$fn); + unless ($spreadsheets{$fn}) { + $spreadsheets{$fn}=''; + my $reply=&Apache::lonnet::reply('dump:'. + $ENV{'course.'.$ENV{'request.course.id'}.'.domain'}.':'. + $ENV{'course.'.$ENV{'request.course.id'}.'.num'}.':'.$fn, + $ENV{'course.'.$ENV{'request.course.id'}.'.home'}); + unless ($reply=~/^error\:/) { + $spreadsheets{$fn}=$reply; + } + } + map { + my ($name,$value)=split(/\=/,$_); + $f{&Apache::lonnet::unescape($name)}= + &Apache::lonnet::unescape($value); + } split(/\&/,$spreadsheets{$fn}); } - { - my $parser=HTML::TokeParser->new(\$spreadsheets{$fn}); - 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); } +# ------------------------------------------------------------ Save spreadsheet + +sub writesheet { + my $safeeval=shift; + if (&Apache::lonnet::allowed('opa',$ENV{'request.course.id'})) { + my %f=&getformulas($safeeval); + my $sheetdata=''; + map { + $sheetdata.=&Apache::lonnet::escape($_).'='. + &Apache::lonnet::escape($f{$_}).'&'; + } keys %f; + $sheetdata=~s/\&$//; + my $reply=&Apache::lonnet::reply('put:'. + $ENV{'course.'.$ENV{'request.course.id'}.'.domain'}.':'. + $ENV{'course.'.$ENV{'request.course.id'}.'.num'}.':'. + &getfilename($safeeval).':'. + $sheetdata, + $ENV{'course.'.$ENV{'request.course.id'}.'.home'}); + if ($reply eq 'ok') { + return &Apache::lonnet::reply('put:'. + $ENV{'course.'.$ENV{'request.course.id'}.'.domain'}.':'. + $ENV{'course.'.$ENV{'request.course.id'}.'.num'}.':'. + &gettype($safeeval).'_spreadsheets:'. + &Apache::lonnet::escape(&getfilename($safeeval)).'='. + $ENV{'user.name'}, + $ENV{'course.'.$ENV{'request.course.id'}.'.home'}); + } else { + return $reply; + } + } + return 'unauthorized'; +} + # ----------------------------------------------- Make a temp copy of the sheet sub tmpwrite { my ($safeeval,$tmpdir,$symb)=@_; - my $fn=$uname.'_'.$udom.'_spreadsheet_'.&getfilename($safeeval); + my $fn=$uname.'_'.$udom.'_spreadsheet_'.$symb.'_'.&getfilename($safeeval); $fn=~s/\W/\_/g; $fn=$tmpdir.$fn.'.tmp'; my $fh; @@ -529,7 +682,7 @@ sub tmpwrite { sub tmpread { my ($safeeval,$tmpdir,$symb,$nfield,$nform)=@_; - my $fn=$uname.'_'.$udom.'_spreadsheet_'.&getfilename($safeeval); + my $fn=$uname.'_'.$udom.'_spreadsheet_'.$symb.'_'.&getfilename($safeeval); $fn=~s/\W/\_/g; $fn=$tmpdir.$fn.'.tmp'; my $fh; @@ -543,7 +696,7 @@ sub tmpread { $fo{$name}=$value; } } - $fo{$nfield}=$nform; + if ($nfield) { $fo{$nfield}=$nform; } &setformulas($safeeval,%fo); } @@ -722,7 +875,7 @@ sub updaterows { if ($_=~/^A(\d+)/) { $maxrow=($1>$maxrow)?$1:$maxrow; $existing{$f{$_}}=1; - unless (defined($current{$f{$_}})) { + unless ((defined($current{$f{$_}})) || (!$1)) { $f{$_}='!!! Obsolete'; $changed=1; } @@ -749,6 +902,40 @@ sub updaterows { } } +# --------------------------------------------------- Load data for one student + +sub rowazstudent { + my $safeeval=shift; + my %c=(); + my %f=&getformulas($safeeval); + map { + if ($_=~/^A(\d+)/) { + my $row=$1; + unless ($f{$_}=~/^\!/) { + my @assessdata=split(/\_\_\_\;\_\_\_/, + &Apache::lonnet::ssi( + '/res/msu/korte/junk.assesscalc',('utarget' => 'export', + 'uname' => $uname, + 'udom' => $udom, + 'usymb' => $f{$_}))); + my $index=0; + map { + if ($assessdata[$index]) { + $c{$_.$row}=$assessdata[$index]; + unless ($_ eq 'A') { + $f{$_.$row}='import'; + } + } + $index++; + } ('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'); + } + } + } keys %f; + &setformulas($safeeval,%f); + &setconstants($safeeval,%c); +} + # ------------------------------------------------ Load data for one assessment sub rowaassess { @@ -881,11 +1068,13 @@ sub handler { ($ENV{'request.state'} eq 'construct')) { # --------------------------- Get query string for limited number of parameters + map { my ($name, $value) = split(/=/,$_); $value =~ tr/+/ /; $value =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C",hex($1))/eg; - if (($name eq 'uname') || ($name eq 'udom') || ($name eq 'usymb')) { + if (($name eq 'uname') || ($name eq 'udom') || + ($name eq 'usymb') || ($name eq 'ufn')) { unless ($ENV{'form.'.$name}) { $ENV{'form.'.$name}=$value; } @@ -893,7 +1082,6 @@ sub handler { } (split(/&/,$ENV{'QUERY_STRING'})); # ------------------------------------------- Nothing there? Must be login user - unless ($ENV{'form.uname'}) { $uname=$ENV{'user.name'}; $udom=$ENV{'user.domain'}; @@ -903,7 +1091,7 @@ sub handler { } # ----------------------------------------------------------- Change of target? - my $reroute=($ENV{'utarget'} eq 'export'); + my $reroute=($ENV{'form.utarget'} eq 'export'); # ------------------------------------------------------------------- Open page @@ -931,6 +1119,8 @@ sub handler { ENDSCRIPT $r->print(''. + ''. + '

LON-CAPA Spreadsheet

'. ''. &hiddenfield('uname',$ENV{'form.uname'}). &hiddenfield('udom',$ENV{'form.udom'}). @@ -942,19 +1132,24 @@ ENDSCRIPT # ---------------------------------------- Read new sheet or modified worksheet my $sheetone=initsheet(); + $r->uri=~/\/(\w+)$/; + &settype($sheetone,$1); if ($ENV{'form.unewfield'}) { $r->print('

Modified Workcopy

'); $ENV{'form.unewformula'}=~s/\'/\"/g; - $r->print('New formula: '.$ENV{'form.unewfield'}.'='. - $ENV{'form.unewformula'}.'
'); + $r->print('

New formula: '.$ENV{'form.unewfield'}.'='. + $ENV{'form.unewformula'}.'

'); + &setfilename($sheetone,$ENV{'form.ufn'}); &tmpread($sheetone,$r->dir_config('lonDaemons').'/tmp/', $ENV{'form.usymb'}, $ENV{'form.unewfield'},$ENV{'form.unewformula'}); - &setfilename($sheetone,$r->filename); - $r->filename=~/\.(\w+)/; - &settype($sheetone,$1); + } elsif ($ENV{'form.saveas'}) { + &setfilename($sheetone,$ENV{'form.ufn'}); + &tmpread($sheetone,$r->dir_config('lonDaemons').'/tmp/', + $ENV{'form.usymb'}); } else { - &readsheet($sheetone,$r->filename); + &readsheet($sheetone,$ENV{'form.ufn'},$r); + $ENV{'form.ufn'}=&getfilename($sheetone); } # --------------------------------------------- See if all import rows uptodate @@ -972,7 +1167,21 @@ ENDSCRIPT $r->print('

'. 'Could not initialize import fields (not in a course)

'); } - +# ---------------------------------------------------- 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($sheetone); + &setfilename($sheetone,$fname); + $ENV{'form.ufn'}=$fname; + my $reply=&writesheet($sheetone); + unless ($reroute) { + $r->print('

Saving spreadsheet: '.$reply.'

'); + } + } + } # ------------------------------------------------ Write the modified worksheet &tmpwrite($sheetone,$r->dir_config('lonDaemons').'/tmp/', @@ -980,7 +1189,15 @@ ENDSCRIPT # ----------------------------------------------------- Print user, course, etc unless ($reroute) { - $r->print("User '$uname' at domain '$udom' for '". + 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(''. + '

'); + } + $r->print(&hiddenfield('ufn',$ENV{'form.ufn'}). + "User '$uname' at domain '$udom' for '". $ENV{'course.'.$ENV{'request.course.id'}.'.description'}."'"); if ($csec) { $r->print(", group/section '$csec'"); @@ -991,8 +1208,13 @@ ENDSCRIPT if (&gettype($sheetone) eq 'assesscalc') { &rowaassess($sheetone,$ENV{'form.usymb'}); + } elsif (&gettype($sheetone) eq 'studentcalc') { + &rowazstudent($sheetone); + } + my $calcoutput=&calcsheet($sheetone); + unless ($reroute) { + $r->print('

'.$calcoutput.'

'); } - &calcsheet($sheetone); # ------------------------------------------------------- Print or export sheet unless ($reroute) { @@ -1000,7 +1222,7 @@ ENDSCRIPT $r->print(''); } else { - $r->print(&exportrow($sheetone)); + $r->print(&exportrow($sheetone)); } # ------------------------------------------------------------------------ Done } else {
'. + $realm.'ImportCalculations
$_'; + } else { + $tabledata.=''; + } + $tabledata.="$_