--- loncom/interface/lonnavmaps.pm 2002/11/08 18:44:02 1.99 +++ loncom/interface/lonnavmaps.pm 2002/11/08 19:10:58 1.100 @@ -2,7 +2,7 @@ # The LearningOnline Network with CAPA # Navigate Maps Handler # -# $Id: lonnavmaps.pm,v 1.99 2002/11/08 18:44:02 bowersj2 Exp $ +# $Id: lonnavmaps.pm,v 1.100 2002/11/08 19:10:58 bowersj2 Exp $ # # Copyright Michigan State University Board of Trustees # @@ -1371,16 +1371,6 @@ sub new { } } } - if (ref($curRes) && $curRes->is_map() && $direction == FORWARD()) { - my $firstResource = $curRes->map_start(); - my $finishResource = $curRes->map_finish(); - my $newIterator = Apache::lonnavmaps::iterator->new($self->{NAV_MAP}, - $firstResource, - $finishResource, - $self->{FILTER}, - $self->{ALREADY_SEEN}, - $self->{CONDITION}); - } # Assign the final val if (ref($curRes) && $direction == BACKWARD()) { @@ -1549,29 +1539,24 @@ sub populateStack { package Apache::lonnavmaps::DFSiterator; -# UNDOCUMENTED: This is a private library, it should not generally be used -# by the outside world. What it does is walk through the nav map in a -# depth-first fashion. This is not appropriate for most uses, but it is -# used by the main iterator for pre-processing. It also is able to isolate -# much of the complexity of the main iterator, so the main iterator is much -# simpler. -# There is no real benefit in merging the main iterator and this one into one class... -# all the logic in DFSiterator would need to be replicated, you gain no performance, -# at best, you just make one massively complicated iterator in place of two -# somewhat complicated ones. ;-) - Jeremy - -# Here are the tokens for the iterator, replicated from iterator for convenience: +# Not documented in the perldoc: This is a simple iterator that just walks +# through the nav map and presents the resources in a depth-first search +# fashion, ignorant of conditionals, randomized resources, etc. It presents +# BEGIN_MAP and END_MAP, but does not understand branches at all. It is +# useful for pre-processing of some kind, and is in fact used by the main +# iterator that way, but that's about it. +# One could imagine merging this into the init routine of the main iterator, +# but this might as well be left seperate, since it is possible some other +# use might be found for it. - Jeremy sub BEGIN_MAP { return 1; } # begining of a new map sub END_MAP { return 2; } # end of the map -sub BEGIN_BRANCH { return 3; } # beginning of a branch -sub END_BRANCH { return 4; } # end of a branch sub FORWARD { return 1; } # go forward sub BACKWARD { return 2; } -# Params: nav map, start resource, end resource, filter, condition, -# already seen hash ref - +# Params: Nav map ref, first resource id/ref, finish resource id/ref, +# filter hash ref (or undef), already seen hash or undef, condition +# (as in main iterator), direction FORWARD or BACKWARD (undef->forward). sub new { # magic invocation to create a class instance my $proto = shift; @@ -1581,7 +1566,6 @@ sub new { $self->{NAV_MAP} = shift; return undef unless ($self->{NAV_MAP}); - # Handle the parameters $self->{FIRST_RESOURCE} = shift || $self->{NAV_MAP}->firstResource(); $self->{FINISH_RESOURCE} = shift || $self->{NAV_MAP}->finishResource(); @@ -1600,7 +1584,7 @@ sub new { $self->{CONDITION} = shift; $self->{DIRECTION} = shift || FORWARD(); - # Flag: Have we started yet? If not, the first action is to return BEGIN_MAP. + # Flag: Have we started yet? $self->{STARTED} = 0; # Should we continue calling the recursive iterator, if any? @@ -1614,34 +1598,22 @@ sub new { $self->{RECURSIVE_DEPTH} = 0; # For keeping track of our branches, we maintain our own stack - $self->{BRANCH_STACK} = []; - # If the size shrinks, we exhausted a branch - $self->{BRANCH_STACK_SIZE} = 0; - $self->{BRANCH_DEPTH} = 0; - - # For returning two things in a forced sequence - $self->{FORCE_NEXT} = undef; + $self->{STACK} = []; # Start with the first resource if ($self->{DIRECTION} == FORWARD) { - push @{$self->{BRANCH_STACK}}, $self->{FIRST_RESOURCE}; + push @{$self->{STACK}}, $self->{FIRST_RESOURCE}; } else { - push @{$self->{BRANCH_STACK}}, $self->{FINISH_RESOURCE}; + push @{$self->{STACK}}, $self->{FINISH_RESOURCE}; } - $self->{BRANCH_STACK_SIZE} = 1; bless($self); return $self; } -# Note... this function is *touchy*. I strongly recommend tracing -# through it with the debugger a few times on a non-trivial map before -# modifying it. Order is *everything*. sub next { my $self = shift; - # Iterator logic goes here - # Are we using a recursive iterator? If so, pull from that and # watch the depth; we want to resume our level at the correct time. if ($self->{RECURSIVE_ITERATOR_FLAG}) { @@ -1660,23 +1632,10 @@ sub next { return $next; } - # Is this return value pre-determined? - if (defined($self->{FORCE_NEXT})) { - my $tmp = $self->{FORCE_NEXT}; - $self->{FORCE_NEXT} = undef; - return $tmp; - } - # Is there a current resource to grab? If not, then return - # END_BRANCH and END_MAP in succession. - if (scalar(@{$self->{BRANCH_STACK}}) == 0) { - if ($self->{BRANCH_DEPTH} > 0) { - $self->{FORCE_NEXT} = $self->END_MAP(); - $self->{BRANCH_DEPTH}--; - return $self->END_BRANCH(); - } else { - return $self->END_MAP(); - } + # END_MAP, which will end the iterator. + if (scalar(@{$self->{STACK}}) == 0) { + return $self->END_MAP(); } # Have we not yet begun? If not, return BEGIN_MAP and @@ -1686,42 +1645,10 @@ sub next { return $self->BEGIN_MAP; } - # Did the branch stack shrink since last run? If so, - # we exhausted a branch last time, therefore, we're about - # to start a new one. (We know because we already checked to see - # if the stack was empty.) - if ( scalar (@{$self->{BRANCH_STACK}}) < $self->{BRANCH_STACK_SIZE}) { - $self->{BRANCH_STACK_SIZE} = scalar(@{$self->{BRANCH_STACK}}); - $self->{BRANCH_DEPTH}++; - return $self->BEGIN_BRANCH(); - } - - # Remember the size for comparision next time. - $self->{BRANCH_STACK_SIZE} = scalar(@{$self->{BRANCH_STACK}}); - - # If the next resource we mean to return is going to need - # a lower branch level, terminate branches until we get - # there. - # Get the next resource in the branch - $self->{HERE} = pop @{$self->{BRANCH_STACK}}; + $self->{HERE} = pop @{$self->{STACK}}; - # Are we at the right depth? If not, close a branch and return - # the current resource onto the branch stack - # Note: There seems to be some bugs here, so don't rely - # on this, use the real iterator instead. - if (defined($self->{HERE}->{DATA}->{ITERATOR_DEPTH}) - && $self->{HERE}->{DATA}->{ITERATOR_DEPTH} < - $self->{BRANCH_DEPTH} ) { - $self->{BRANCH_DEPTH}--; - # return it so we can pick it up eventually - push @{$self->{BRANCH_STACK}}, $self->{HERE}; - return $self->END_BRANCH(); - } - - # We always return it after this point and never before - # (proof: look at just the return statements), so we - # remember that we've seen this. + # remember that we've seen this, so we don't return it again later $self->{ALREADY_SEEN}->{$self->{HERE}->{ID}} = 1; # Get the next possible resources @@ -1734,40 +1661,16 @@ sub next { my $next = []; # filter the next possibilities to remove things we've - # already seen. Also, remember what branch depth they should - # be displayed at, since there's no other reliable way to tell. + # already seen. foreach (@$nextUnfiltered) { if (!defined($self->{ALREADY_SEEN}->{$_->{ID}})) { push @$next, $_; - $_->{DATA}->{ITERATOR_DEPTH} = - $self->{BRANCH_DEPTH} + 1; } } - # Handle branch cases: - # Nothing is available next: BRANCH_END - # 1 thing next: standard non-branch - # 2+ things next: have some branches - my $nextCount = scalar(@$next); - if ($nextCount == 0) { - # Return this and on the next run, close the branch up if we're - # in a branch - if ($self->{BRANCH_DEPTH} > 0 ) { - $self->{FORCE_NEXT} = $self->END_BRANCH(); - $self->{BRANCH_DEPTH}--; - } - } - while (@$next) { - # copy the next possibilities over to the branch stack - # in the right order - push @{$self->{BRANCH_STACK}}, shift @$next; - } - - if ($nextCount >= 2) { - $self->{FORCE_NEXT} = $self->BEGIN_BRANCH(); - $self->{BRANCH_DEPTH}++; - return $self->{HERE}; + # copy the next possibilities over to the stack + push @{$self->{STACK}}, shift @$next; } # If this is a map and we want to recurse down it... (not filtered out) @@ -1786,28 +1689,6 @@ sub next { return $self->{HERE}; } -sub getStack { - my $self=shift; - - my @stack; - - $self->populateStack(\@stack); - - return \@stack; -} - -# Private method: Calls the iterators recursively to populate the stack. -sub populateStack { - my $self=shift; - my $stack = shift; - - push @$stack, $self->{HERE} if ($self->{HERE}); - - if ($self->{RECURSIVE_ITERATOR_FLAG}) { - $self->{RECURSIVE_ITERATOR}->populateStack($stack); - } -} - 1; package Apache::lonnavmaps::resource;