[LON-CAPA-cvs] cvs: loncom /interface lonnavmaps.pm

bowersj2 lon-capa-cvs@mail.lon-capa.org
Fri, 08 Nov 2002 18:35:37 -0000


This is a MIME encoded message

--bowersj21036780537
Content-Type: text/plain

bowersj2		Fri Nov  8 13:35:37 2002 EDT

  Modified files:              
    /loncom/interface	lonnavmaps.pm 
  Log:
  The new, improved iterator, which should now show structure on branch
  thingies more appropriately. Lightly tested, but the things on which it
  was tested are pretty seriously convoluted maps.
  
  Still need to talk to someone about conditions; I can't get them to work
  properly and it is ill-defined how they should behave for people in my
  mind.
  
  
  
--bowersj21036780537
Content-Type: text/plain
Content-Disposition: attachment; filename="bowersj2-20021108133537.txt"

Index: loncom/interface/lonnavmaps.pm
diff -u loncom/interface/lonnavmaps.pm:1.97 loncom/interface/lonnavmaps.pm:1.98
--- loncom/interface/lonnavmaps.pm:1.97	Sun Nov  3 16:05:03 2002
+++ loncom/interface/lonnavmaps.pm	Fri Nov  8 13:35:37 2002
@@ -2,7 +2,7 @@
 # The LearningOnline Network with CAPA
 # Navigate Maps Handler
 #
-# $Id: lonnavmaps.pm,v 1.97 2002/11/03 21:05:03 bowersj2 Exp $
+# $Id: lonnavmaps.pm,v 1.98 2002/11/08 18:35:37 bowersj2 Exp $
 #
 # Copyright Michigan State University Board of Trustees
 #
@@ -958,8 +958,8 @@
     # Preprocess the map: Look for current URL, force inlined maps to display
 
     # This currently does very little...
-    my $mapEventualIterator = Apache::lonnavmaps::iterator->new($navmap, undef, undef, {},
-                                                                undef, $condition);
+    #my $mapEventualIterator = Apache::lonnavmaps::iterator->new($navmap, undef, undef, {},
+    #undef, $condition);
 
     my $mapIterator = $navmap->getIterator(undef, undef, {}, 1);
     my $found = 0;
@@ -1290,9 +1290,9 @@
                 }
 
                 $r->print("  $curMarkerBegin<a href=\"$link\">$title$partLabel</a> $curMarkerEnd $nonLinkedText");
-                $r->print(" TDV:" . $curRes->{DATA}->{TOP_DOWN_VAL}); # temp
-                $r->print(" BUV:" . $curRes->{DATA}->{BOT_UP_VAL}); # temp
-                $r->print(" DD:" . $curRes->{DATA}->{DISPLAY_DEPTH}); # temp
+                #$r->print(" TDV:" . $curRes->{DATA}->{TOP_DOWN_VAL}); # temp
+                #$r->print(" BUV:" . $curRes->{DATA}->{BOT_UP_VAL}); # temp
+                #$r->print(" DD:" . $curRes->{DATA}->{DISPLAY_DEPTH}); # temp
 
                 if ($curRes->{RESOURCE_ERROR}) {
                     $r->print(&Apache::loncommon::help_open_topic ("Navmap_Host_Down",
@@ -1775,7 +1775,7 @@
 
 sub getIterator {
     my $self = shift;
-    my $iterator = Apache::lonnavmaps::DFSiterator->new($self, shift, shift,
+    my $iterator = Apache::lonnavmaps::iterator->new($self, shift, shift,
                                                      shift, undef, shift, 
                                                      $ENV{'form.direction'});
     return $iterator;
@@ -2079,6 +2079,8 @@
                        [BACKWARD(), 'BOT_UP_VAL', 'getPrevious', 
                         'FINISH_RESOURCE'] );
 
+    my $maxDepth = 0; # tracks max depth
+
     foreach my $pass (@iterations) {
         my $direction = $pass->[0];
         my $valName = $pass->[1];
@@ -2092,10 +2094,10 @@
     
         # prime the recursion
         $self->{$firstResourceName}->{DATA}->{$valName} = 0;
-        my $depth = 1;
+        my $depth = 0;
         $iterator->next();
         my $curRes = $iterator->next();
-        while ($depth > 0) {
+        while ($depth > -1) {
             if ($curRes == $iterator->BEGIN_MAP()) { $depth++; }
             if ($curRes == $iterator->END_MAP()) { $depth--; }
         
@@ -2129,14 +2131,165 @@
             
             # Assign the final val
             if (ref($curRes) && $direction == BACKWARD()) {
-                $curRes->{DATA}->{DISPLAY_DEPTH} = min($curRes->{DATA}->{TOP_DOWN_VAL},
-                                                       $curRes->{DATA}->{BOT_UP_VAL});
-            }
+                my $finalDepth = min($curRes->{DATA}->{TOP_DOWN_VAL},
+                                     $curRes->{DATA}->{BOT_UP_VAL});
+                
+                $curRes->{DATA}->{DISPLAY_DEPTH} = $finalDepth;
+                if ($finalDepth > $maxDepth) {$maxDepth = $finalDepth;}
+                }
             $curRes = $iterator->next();
         }
     }
 
-    # Now we're ready to start iterating.
+    # Set up some bookkeeping information.
+    $self->{CURRENT_DEPTH} = 0;
+    $self->{MAX_DEPTH} = $maxDepth;
+    $self->{STACK} = [];
+    $self->{RECURSIVE_ITERATOR_FLAG} = 0;
+
+    for (my $i = 0; $i <= $self->{MAX_DEPTH}; $i++) {
+        push @{$self->{STACK}}, [];
+    }
+
+    # Prime the recursion w/ the first resource
+    push @{$self->{STACK}->[0]}, $self->{FIRST_RESOURCE};
+    $self->{ALREADY_SEEN}->{$self->{FIRST_RESOURCE}->{ID}} = 1;
+
+    bless ($self);
+
+    return $self;
+}
+
+sub next {
+    my $self = shift;
+
+    if ($self->{RECURSIVE_ITERATOR_FLAG}) {
+        # grab the next from the recursive iterator 
+        my $next = $self->{RECURSIVE_ITERATOR}->next();
+
+        # is it a begin or end map? If so, update the depth
+        if ($next == BEGIN_MAP() ) { $self->{RECURSIVE_DEPTH}++; }
+        if ($next == END_MAP() ) { $self->{RECURSIVE_DEPTH}--; }
+
+        # Are we back at depth 0? If so, stop recursing
+        if ($self->{RECURSIVE_DEPTH} == 0) {
+            $self->{RECURSIVE_ITERATOR_FLAG} = 0;
+        }
+
+        return $next;
+    }
+
+    if (defined($self->{FORCE_NEXT})) {
+        my $tmp = $self->{FORCE_NEXT};
+        $self->{FORCE_NEXT} = undef;
+        return $tmp;
+    }
+
+    # Have we not yet begun? If not, return BEGIN_MAP and
+    # remember we've started.
+    if ( !$self->{STARTED} ) { 
+        $self->{STARTED} = 1;
+        return $self->BEGIN_MAP();
+    }
+
+    # Here's the guts of the iterator.
+    
+    # Find the next resource, if any.
+    my $found = 0;
+    my $i = $self->{MAX_DEPTH};
+    my $newDepth;
+    my $here;
+    while ( $i >= 0 && !$found ) {
+        if ( scalar(@{$self->{STACK}->[$i]}) > 0 ) {
+            $here = $self->{HERE} = shift @{$self->{STACK}->[$i]};
+            $found = 1;
+            $newDepth = $i;
+        }
+        $i--;
+    }
+
+    # If we still didn't find anything, we're done.
+    if ( !$found ) {
+        # We need to get back down to the correct branch depth
+        if ( $self->{CURRENT_DEPTH} > 0 ) {
+            $self->{CURRENT_DEPTH}--;
+            return END_BRANCH();
+        } else {
+            return END_MAP();
+        }
+    }
+
+    # Get to the right level
+    if ( $self->{CURRENT_DEPTH} > $newDepth ) {
+        push @{$self->{STACK}->[$newDepth]}, $here;
+        $self->{CURRENT_DEPTH}--;
+        return END_BRANCH();
+    }
+    if ( $self->{CURRENT_DEPTH} < $newDepth) {
+        push @{$self->{STACK}->[$newDepth]}, $here;
+        $self->{CURRENT_DEPTH}++;
+        return BEGIN_BRANCH();
+    }
+
+    # If we made it here, we have the next resource, and we're at the
+    # right branch level. So let's examine the resource for where
+    # we can get to from here.
+
+    # So we need to look at all the resources we can get to from here,
+    # categorize them if we haven't seen them, remember if we have a new
+    my $nextUnfiltered = $here->getNext();
+
+    for (@$nextUnfiltered) {
+        if (!defined($self->{ALREADY_SEEN}->{$_->{ID}})) {
+            push @{$self->{STACK}->[$_->{DATA}->{DISPLAY_DEPTH}]}, $_;
+            $self->{ALREADY_SEEN}->{$_->{ID}} = 1;
+        }
+    }
+    
+    # That ends the main iterator logic. Now, do we want to recurse
+    # down this map (if this resource is a map)?
+    if ($self->{HERE}->is_map() &&
+        (defined($self->{FILTER}->{$self->{HERE}->map_pc()}) xor $self->{CONDITION})) {
+        $self->{RECURSIVE_ITERATOR_FLAG} = 1;
+        my $firstResource = $self->{HERE}->map_start();
+        my $finishResource = $self->{HERE}->map_finish();
+
+        $self->{RECURSIVE_ITERATOR} = 
+            Apache::lonnavmaps::iterator->new($self->{NAV_MAP}, $firstResource,
+                                              $finishResource, $self->{FILTER},
+                                              $self->{ALREADY_SEEN}, $self->{CONDITION});
+    }
+
+    return $self->{HERE};
+
+}
+
+=pod
+
+The other method available on the iterator is B<getStack>, which returns an array populated with the current 'stack' of maps, as references to the resource objects. Example: This is useful when making the navigation map, as we need to check whether we are under a page map to see if we need to link directly to the resource, or to the page. The first elements in the array will correspond to the top of the stack (most inclusive map).
+
+=cut
+
+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;
@@ -2238,8 +2391,7 @@
 
     # 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})
-    {
+    if ($self->{RECURSIVE_ITERATOR_FLAG}) {
         # grab the next from the recursive iterator
         my $next = $self->{RECURSIVE_ITERATOR}->next();
         
@@ -2303,6 +2455,8 @@
 
     # 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} ) {
@@ -2378,12 +2532,6 @@
 
     return $self->{HERE};
 }
-
-=pod
-
-The other method available on the iterator is B<getStack>, which returns an array populated with the current 'stack' of maps, as references to the resource objects. Example: This is useful when making the navigation map, as we need to check whether we are under a page map to see if we need to link directly to the resource, or to the page. The first elements in the array will correspond to the top of the stack (most inclusive map).
-
-=cut
 
 sub getStack {
     my $self=shift;

--bowersj21036780537--