--- rat/lonuserstate.pm 2000/07/18 17:32:32 1.1
+++ rat/lonuserstate.pm 2000/10/31 19:31:42 1.14
@@ -10,7 +10,8 @@
# 7/1 Gerd Kortemeyer)
# 7/1,7/3,7/4,7/7,7/8,7/10 Gerd Kortemeyer)
#
-# 7/15,7/17,7/18 Gerd Kortemeyer
+# 7/15,7/17,7/18,8/1,8/2,8/4,8/5,8/21,8/22,8/23,8/30,
+# 9/2,9/4,9/29,9/30,10/2,10/11,10/30,10/31 Gerd Kortemeyer
package Apache::lonuserstate;
@@ -20,6 +21,7 @@ use Apache::File;
use HTML::TokeParser;
use Apache::lonnet();
use GDBM_File;
+use Apache::lonmsg;
# ---------------------------------------------------- Globals for this package
@@ -41,8 +43,7 @@ sub loadmap {
my $fn='/home/httpd/html'.$uri;
- unless (($fn=~/\.course$/) ||
- ($fn=~/\.sequence$/) ||
+ unless (($fn=~/\.sequence$/) ||
($fn=~/\.page$/)) {
$errtext.="Invalid map: $fn\n";
return OK;
@@ -106,13 +107,19 @@ sub loadmap {
}
if ($token->[2]->{'type'}) {
$hash{'type_'.$rid}=$token->[2]->{'type'};
+ if ($token->[2]->{'type'} eq 'start') {
+ $hash{'map_start_'.$uri}="$rid";
+ }
+ if ($token->[2]->{'type'} eq 'finish') {
+ $hash{'map_finish_'.$uri}="$rid";
+ }
} else {
$hash{'type_'.$rid}='normal';
}
- if (($turi=~/\.course$/) ||
- ($turi=~/\.sequence$/) ||
+ if (($turi=~/\.sequence$/) ||
($turi=~/\.page$/)) {
+ $hash{'is_map_'.$rid}=1;
&loadmap($turi);
}
@@ -122,11 +129,12 @@ sub loadmap {
my $rid=$lpc.'.'.$token->[2]->{'id'};
$hash{'kind_'.$rid}='cond';
- $hash{'value_'.$rid}=$token->[2]->{'value'};
+ $cond[$#cond+1]=$token->[2]->{'value'};
+ $hash{'condid_'.$rid}=$#cond;
if ($token->[2]->{'type'}) {
- $hash{'type_'.$rid}=$token->[2]->{'type'};
+ $cond[$#cond].=':'.$token->[2]->{'type'};
} else {
- $hash{'type_'.$rid}='normal';
+ $cond[$#cond].=':normal';
}
} elsif ($token->[1] eq 'link') {
@@ -167,34 +175,185 @@ sub loadmap {
}
}
+# --------------------------------------------------------- Simplify expression
-# ---------------------------------------------------- Read map and all submaps
-
-sub readmap {
- my $uri=shift;
- @cond=();
- %hash=();
- $errtext='';
- $pc=0;
- loadmap($uri);
+sub simplify {
+ my $expression=shift;
+# (8)=8
+ $expression=~s/\((\d+)\)/$1/g;
+# 8&8=8
+ $expression=~s/(\D)(\d+)\&\2(\D)/$1$2$3/g;
+# 8|8=8
+ $expression=~s/(\D)(\d+)\|\2(\D)/$1$2$3/g;
+# (5&3)&4=5&3&4
+ $expression=~s/\((\d+)((?:\&\d+)+)\)\&(\d+\D)/$1$2\&$3/g;
+# (((5&3)|(4&6)))=((5&3)|(4&6))
+ $expression=~
+ s/\((\(\(\d+(?:\&\d+)*\)(?:\|\(\d+(?:\&\d+)*\))+\))\)/$1/g;
+# ((5&3)|(4&6))|(1&2)=(5&3)|(4&6)|(1&2)
+ $expression=~
+ s/\((\(\d+(?:\&\d+)*\))((?:\|\(\d+(?:\&\d+)*\))+)\)\|(\(\d+(?:\&\d+)*\))/\($1$2\|$3\)/g;
+ return $expression;
}
-sub handler {
- my $r = shift;
- $r->content_type('text/html');
- $r->send_http_header;
- return OK if $r->header_only;
- readmap('/res/msu/korte/foo.course');
- $r->print("
\n");
- my $hashkey;
- foreach $hashkey (keys %hash) {
- $r->print("$hashkey: $hash{$hashkey}
\n");
+# -------------------------------------------------------- Build condition hash
+
+sub traceroute {
+ my ($sofar,$rid,$beenhere)=@_;
+ $sofar=simplify($sofar);
+ unless ($beenhere=~/\&$rid\&/) {
+ $beenhere.=$rid.'&';
+ if (defined($hash{'conditions_'.$rid})) {
+ $hash{'conditions_'.$rid}=simplify(
+ '('.$hash{'conditions_'.$rid}.')|('.$sofar.')');
+ } else {
+ $hash{'conditions_'.$rid}=$sofar;
+ }
+ if (defined($hash{'is_map_'.$rid})) {
+ if (defined($hash{'map_start_'.$hash{'src_'.$rid}})) {
+ &traceroute($sofar,$hash{'map_start_'.$hash{'src_'.$rid}},'&');
+ if (defined($hash{'map_finish_'.$hash{'src_'.$rid}})) {
+ $sofar=
+ $hash{'conditions_'.$hash{'map_finish_'.$hash{'src_'.$rid}}};
+ }
+ }
+ }
+ if (defined($hash{'to_'.$rid})) {
+ map {
+ my $further=$sofar;
+ if ($hash{'undercond_'.$_}) {
+ if (defined($hash{'condid_'.$hash{'undercond_'.$_}})) {
+ $further=simplify('('.$further.')&('.
+ $hash{'condid_'.$hash{'undercond_'.$_}}.')');
+ } else {
+ $errtext.='Undefined condition ID: '
+ .$hash{'undercond_'.$_}.'. ';
+ }
+ }
+ &traceroute($further,$hash{'goesto_'.$_},$beenhere);
+ } split(/\,/,$hash{'to_'.$rid});
+ }
}
- $r->print("$errtext
\n");
- return OK;
}
-
+# ------------------------------------------ Cascading conditions, quick access
+
+sub accinit {
+ my ($uri,$short,$fn)=@_;
+ my %acchash=();
+ my %captured=();
+ my $condcounter=0;
+ $acchash{'acc.cond.'.$short.'.0'}=0;
+ map {
+ if ($_=~/^conditions/) {
+ my $expr=$hash{$_};
+ map {
+ my $sub=$_;
+ my $orig=$_;
+ $sub=~/\(\((\d+\&(:?\d+\&)*)(?:\d+\&*)+\)(?:\|\(\1(?:\d+\&*)+\))+\)/;
+ my $factor=$1;
+ $sub=~s/$factor//g;
+ $sub=~s/^\(/\($factor\(/;
+ $sub.=')';
+ $sub=simplify($sub);
+ $orig=~s/(\W)/\\$1/g;
+ $expr=~s/$orig/$sub/;
+ } ($expr=~m/(\(\(\d+(?:\&\d+)+\)(?:\|\(\d+(?:\&\d+)+\))+\))/g);
+ $hash{$_}=$expr;
+ unless (defined($captured{$expr})) {
+ $condcounter++;
+ $captured{$expr}=$condcounter;
+ $acchash{'acc.cond.'.$short.'.'.$condcounter}=$expr;
+ }
+ }
+ } keys %hash;
+ map {
+ if ($_=~/^ids/) {
+ map {
+ my $resid=$_;
+ my $uri=$hash{'src_'.$resid};
+ my @uriparts=split(/\//,$uri);
+ my $urifile=$uriparts[$#uriparts];
+ $#uriparts--;
+ my $uripath=join('/',@uriparts);
+ $uripath=~s/^\/res\///;
+ my $uricond='0';
+ if (defined($hash{'conditions_'.$resid})) {
+ $uricond=$captured{$hash{'conditions_'.$resid}};
+ }
+ if (defined($acchash{'acc.res.'.$short.'.'.$uripath})) {
+ if ($acchash{'acc.res.'.$short.'.'.$uripath}=~
+ /(\&$urifile\:[^\&]*)/) {
+ my $replace=$1;
+ $acchash{'acc.res.'.$short.'.'.$uripath}
+ =~s/$replace/$replace\|$uricond/;
+ } else {
+ $acchash{'acc.res.'.$short.'.'.$uripath}.=
+ $urifile.':'.$uricond.'&';
+ }
+ } else {
+ $acchash{'acc.res.'.$short.'.'.$uripath}=
+ '&'.$urifile.':'.$uricond.'&';
+ }
+ } split(/\,/,$hash{$_});
+ }
+ } keys %hash;
+ my $courseuri=$uri;
+ $courseuri=~s/^\/res\///;
+ &Apache::lonnet::delenv('(acc\.|httpref\.)');
+ &Apache::lonnet::appenv(%acchash,
+ "request.course.id" => $short,
+ "request.course.fn" => $fn,
+ "request.course.uri" => $courseuri);
+}
+
+# ---------------------------------------------------- Read map and all submaps
+
+sub readmap {
+ my $short=shift;
+ $short=~s/^\///;
+ my %cenv=&Apache::lonnet::coursedescription($short);
+ my $fn=$cenv{'fn'};
+ my $uri;
+ $short=~s/\//\_/g;
+ unless ($uri=$cenv{'url'}) {
+ &Apache::lonnet::logthis("WARNING: ".
+ "Could not load course $short.");
+ return 'No course data available.';
+ }
+ @cond=('true:normal');
+ unlink($fn.'.db');
+ unlink($fn.'_symb.db');
+ unlink($fn.'.state');
+ if (tie(%hash,'GDBM_File',"$fn.db",&GDBM_WRCREAT,0640)) {
+ %hash=();
+ $errtext='';
+ $pc=0;
+ loadmap($uri);
+ if (defined($hash{'map_start_'.$uri})) {
+ &traceroute('0',$hash{'map_start_'.$uri},'&');
+ &accinit($uri,$short,$fn);
+ }
+ unless (untie(%hash)) {
+ &Apache::lonnet::logthis("WARNING: ".
+ "Could not untie coursemap $fn for $uri.");
+ }
+ {
+ my $cfh;
+ if ($cfh=Apache::File->new(">$fn.state")) {
+ print $cfh join("\n",@cond);
+ } else {
+ &Apache::lonnet::logthis("WARNING: ".
+ "Could not write statemap $fn for $uri.");
+ }
+ }
+ } else {
+ &Apache::lonnet::logthis("WARNING: ".
+ "Could not tie coursemap $fn for $uri.");
+ }
+ &Apache::lonmsg::author_res_msg($ENV{'request.course.uri'},$errtext);
+ return $errtext;
+}
1;
__END__
500 Internal Server Error
Internal Server Error
The server encountered an internal error or
misconfiguration and was unable to complete
your request.
Please contact the server administrator at
root@localhost to inform them of the time this error occurred,
and the actions you performed just before this error.
More information about this error may be available
in the server error log.