--- rat/lonuserstate.pm 2007/06/08 19:33:06 1.118.2.1 +++ rat/lonuserstate.pm 2007/10/16 21:14:53 1.125 @@ -1,7 +1,7 @@ # The LearningOnline Network with CAPA # Construct and maintain state and binary representation of course for user # -# $Id: lonuserstate.pm,v 1.118.2.1 2007/06/08 19:33:06 albertel Exp $ +# $Id: lonuserstate.pm,v 1.125 2007/10/16 21:14:53 albertel Exp $ # # Copyright Michigan State University Board of Trustees # @@ -56,6 +56,7 @@ my $retfrid; # variable with the very fi my $retfurl; # first URL my %randompick; # randomly picked resources my %randompickseed; # optional seed for randomly picking resources +my %randomorder; # maps to order contents randomly my %encurl; # URLs in this folder are supposed to be encrypted my %hiddenurl; # this URL (or complete folder) is supposed to be hidden @@ -106,9 +107,11 @@ sub processversionfile { # --------------------------------------------------------- Loads map from disk sub loadmap { - my $uri=shift; + my ($uri,$parent_rid)=@_; if ($hash{'map_pc_'.$uri}) { - $errtext.=&mt('
Multiple use of sequence/page [_1]! The course will not function properly.',$uri); + $errtext.='

'. + &mt('Multiple use of sequence/page [_1]! The course will not function properly.',''.$uri.''). + '

'; return; } $pc++; @@ -138,6 +141,16 @@ sub loadmap { my $parser = HTML::TokeParser->new(\$instr); $parser->attr_encoded(1); + # first get all parameters + while (my $token = $parser->get_token) { + next if ($token->[0] ne 'S'); + if ($token->[1] eq 'param') { + &parse_param($token,$lpc); + } + } + #reset parser + $parser = HTML::TokeParser->new(\$instr); + $parser->attr_encoded(1); my $linkpc=0; @@ -145,7 +158,8 @@ sub loadmap { $hash{'map_type_'.$lpc}=$1; - my $randomize=1; + my $randomize = ($randomorder{$parent_rid} =~ /^yes$/i); + my @map_ids; while (my $token = $parser->get_token) { next if ($token->[0] ne 'S'); @@ -158,13 +172,27 @@ sub loadmap { $token->[2]->{'condition'}); } elsif ($token->[1] eq 'condition' && !$randomize) { &parse_condition($token,$lpc); - } elsif ($token->[1] eq 'param') { - &parse_param($token,$lpc); - } + } } if ($randomize) { - my @map_ids=&Math::Random::random_permutation(@map_ids); + if (!$env{'request.role.adv'}) { + my $seed; + if (defined($randompickseed{$parent_rid})) { + $seed = $randompickseed{$parent_rid}; + } else { + my ($mapid,$resid)=split(/\./,$parent_rid); + my $symb= + &Apache::lonnet::encode_symb($hash{'map_id_'.$mapid}, + $resid,$hash{'src_'.$parent_rid}); + + $seed = $symb; + } + + my $rndseed=&Apache::lonnet::rndseed($seed); + &Apache::lonnet::setup_random_from_rndseed($rndseed); + @map_ids=&Math::Random::random_permutation(@map_ids); + } my $from = shift(@map_ids); my $from_rid = $lpc.'.'.$from; $hash{'map_start_'.$uri} = $from_rid; @@ -181,6 +209,17 @@ sub loadmap { $hash{'map_finish_'.$uri}= $from_rid; $hash{'type_'.$from_rid}='finish'; } + + my $parser = HTML::TokeParser->new(\$instr); + $parser->attr_encoded(1); + # last parse out the mapalias params so as to ignore anything + # refering to non-existant resources + while (my $token = $parser->get_token) { + next if ($token->[0] ne 'S'); + if ($token->[1] eq 'param') { + &parse_mapalias_param($token,$lpc); + } + } } @@ -265,7 +304,7 @@ sub parse_resource { if (($turi=~/\.sequence$/) || ($turi=~/\.page$/)) { $hash{'is_map_'.$rid}=1; - &loadmap($turi); + &loadmap($turi,$rid); } return $token->[2]->{'id'}; } @@ -304,7 +343,10 @@ sub parse_condition { my $rid=$lpc.'.'.$token->[2]->{'id'}; $hash{'kind_'.$rid}='cond'; - $cond[$#cond+1]=$token->[2]->{'value'}; + + my $condition = $token->[2]->{'value'}; + $condition =~ s/[\n\r]+/ /gs; + push(@cond, $condition); $hash{'condid_'.$rid}=$#cond; if ($token->[2]->{'type'}) { $cond[$#cond].=':'.$token->[2]->{'type'}; @@ -335,14 +377,14 @@ sub parse_param { } else { $hash{'param_'.$referid}=''.$newparam; } - if ($token->[2]->{'name'}=~/^parameter_(0_)*mapalias$/) { - $hash{'mapalias_'.$token->[2]->{'value'}}=$referid; - } if ($token->[2]->{'name'}=~/^parameter_(0_)*randompick$/) { $randompick{$referid}=$token->[2]->{'value'}; } if ($token->[2]->{'name'}=~/^parameter_(0_)*randompickseed$/) { - $randompick{$referid}=$token->[2]->{'value'}; + $randompickseed{$referid}=$token->[2]->{'value'}; + } + if ($token->[2]->{'name'}=~/^parameter_(0_)*randomorder$/) { + $randomorder{$referid}=$token->[2]->{'value'}; } if ($token->[2]->{'name'}=~/^parameter_(0_)*encrypturl$/) { if ($token->[2]->{'value'}=~/^yes$/i) { @@ -356,6 +398,17 @@ sub parse_param { } } +sub parse_mapalias_param { + my ($token,$lpc) = @_; + my $referid=$lpc.'.'.$token->[2]->{'to'}; + return if (!exists($hash{'src_'.$referid})); + + if ($token->[2]->{'name'}=~/^parameter_(0_)*mapalias$/) { + &count_mapalias($token->[2]->{'value'},$referid); + $hash{'mapalias_'.$token->[2]->{'value'}}=$referid; + } +} + # --------------------------------------------------------- Simplify expression sub simplify { @@ -384,7 +437,7 @@ sub simplify { sub traceroute { my ($sofar,$rid,$beenhere,$encflag,$hdnflag)=@_; my $newsofar=$sofar=simplify($sofar); - unless ($beenhere=~/\&$rid\&/) { + unless ($beenhere=~/\&\Q$rid\E\&/) { $beenhere.=$rid.'&'; my ($mapid,$resid)=split(/\./,$rid); my $symb=&Apache::lonnet::encode_symb($hash{'map_id_'.$mapid},$resid,$hash{'src_'.$rid}); @@ -615,13 +668,14 @@ sub readmap { %parmhash=(); $errtext=''; $pc=0; + &clear_mapalias_count(); &processversionfile(%cenv); my $furi=&Apache::lonnet::clutter($uri); $hash{'src_0.0'}=&versiontrack($furi); $hash{'title_0.0'}=&Apache::lonnet::metadata($uri,'title'); $hash{'ids_'.$furi}='0.0'; $hash{'is_map_0.0'}=1; - loadmap($uri); + loadmap($uri,'0.0'); if (defined($hash{'map_start_'.$uri})) { &Apache::lonnet::appenv("request.course.id" => $short, "request.course.fn" => $fn, @@ -631,6 +685,7 @@ sub readmap { &accinit($uri,$short,$fn); &hiddenurls(); } + $errtext .= &get_mapalias_errors(); # ------------------------------------------------------- Put versions into src foreach my $key (keys(%hash)) { if ($key=~/^src_/) { @@ -762,6 +817,43 @@ sub evalstate { return $state; } +{ + my %mapalias_cache; + sub count_mapalias { + my ($value,$resid) = @_; + push(@{ $mapalias_cache{$value} }, $resid); + } + + sub get_mapalias_errors { + my $error_text; + foreach my $mapalias (sort(keys(%mapalias_cache))) { + next if (scalar(@{ $mapalias_cache{$mapalias} } ) == 1); + my $count; + my $which = + join('
  • ', + map { + my $id = $_; + if (exists($hash{'src_'.$id})) { + $count++; + } + my ($mapid) = split(/\./,$id); + &mt('Resource "[_1]"
    in Map "[_2]"', + $hash{'title_'.$id}, + $hash{'title_'.$hash{'ids_'.$hash{'map_id_'.$mapid}}}); + } (@{ $mapalias_cache{$mapalias} })); + next if ($count < 2); + $error_text .= '
    '. + &mt('Error: Found the mapalias "[_1]" defined multiple times.', + $mapalias). + '
    '; + } + &clear_mapalias_count(); + return $error_text; + } + sub clear_mapalias_count { + undef(%mapalias_cache); + } +} 1; __END__