Diff for /loncom/interface/lonnavmaps.pm between versions 1.74 and 1.88

version 1.74, 2002/10/11 21:29:18 version 1.88, 2002/10/28 19:10:35
Line 823  sub new_handle { Line 823  sub new_handle {
     # Initialize the nav map      # Initialize the nav map
     my $navmap = Apache::lonnavmaps::navmap->new(      my $navmap = Apache::lonnavmaps::navmap->new(
                         $ENV{"request.course.fn"}.".db",                          $ENV{"request.course.fn"}.".db",
                         $ENV{"request.course.fn"}."_parms.db", 1);                          $ENV{"request.course.fn"}."_parms.db", 1, 1);
   
   
     if (!defined($navmap)) {      if (!defined($navmap)) {
Line 849  sub new_handle { Line 849  sub new_handle {
         $r->print('<img src="/adm/lonMisc/chat.gif"> Discussions'.          $r->print('<img src="/adm/lonMisc/chat.gif"> Discussions'.
                   '<br><img src="/adm/lonMisc/feedback.gif"> New message (click to open)<p>');                     '<br><img src="/adm/lonMisc/feedback.gif"> New message (click to open)<p>'); 
     }      }
     #if (($currenturl=~/^\/res/) &&  
     #    ($currenturl!~/^\/res\/adm/)) {  
     #    $r->print('<a href="#curloc">Current Location</a><p>');  
     #}  
   
     # Check that it's defined      # Check that it's defined
     if (!($navmap->courseMapDefined())) {      if (!($navmap->courseMapDefined())) {
Line 880  sub new_handle { Line 876  sub new_handle {
       $res->NOTHING_SET            => ''        );        $res->NOTHING_SET            => ''        );
     # And a special case in the nav map; what to do when the assignment      # And a special case in the nav map; what to do when the assignment
     # is not yet done and due in less then 24 hours      # is not yet done and due in less then 24 hours
     my $hurryUpColor = "#FFCCCC";      my $hurryUpColor = "#FF0000";
   
     my %statusIconMap =       my %statusIconMap = 
         ( $res->NETWORK_FAILURE    => '',          ( $res->NETWORK_FAILURE    => '',
Line 894  sub new_handle { Line 890  sub new_handle {
           $res->TRIES_LEFT         => 'navmap.open.gif',            $res->TRIES_LEFT         => 'navmap.open.gif',
           $res->INCORRECT          => 'navmap.wrong.gif',            $res->INCORRECT          => 'navmap.wrong.gif',
           $res->OPEN               => 'navmap.open.gif',            $res->OPEN               => 'navmap.open.gif',
           $res->ATTEMPTED          => '' );            $res->ATTEMPTED          => 'navmap.open.gif' );
   
     my %iconAltTags =       my %iconAltTags = 
         ( 'navmap.correct.gif' => 'Correct',          ( 'navmap.correct.gif' => 'Correct',
Line 914  sub new_handle { Line 910  sub new_handle {
         }          }
     }      }
   
       # Is this a new-style course? If so, we want to suppress showing the top-level
       # maps in their own folders, in favor of "inlining" them.
       my $topResource = $navmap->getById("0.0");
       my $inlineTopLevelMaps = $topResource->src() =~ m|^/uploaded/.*default\.sequence$|;
   
     my $currenturl = $ENV{'form.postdata'};      my $currenturl = $ENV{'form.postdata'};
     $currenturl=~s/^http\:\/\///;      $currenturl=~s/^http\:\/\///;
     $currenturl=~s/^[^\/]+//;      $currenturl=~s/^[^\/]+//;
     my $queryAdd = "postdata=" . &Apache::lonnet::escape($currenturl);      # alreadyHere allows us to only open the maps necessary to view
       # the current location once, while at the same time remembering
       # the current location. Without that check, the user would never
       # be able to close those maps; the user would close it, and the
       # currenturl scan would re-open it.
       my $queryAdd = "postdata=" . &Apache::lonnet::escape($currenturl) .
           "&alreadyHere=1";
   
     $r->print('<a href="navmaps?condition=1&filter=">Show All Resources</a><br /><br />');      $r->print('<a href="navmaps?condition=1&filter=">Show All Resources</a><br /><br />');
   
     # Begin the HTML table      # Begin the HTML table
     # four cols: resource + indent, chat+feedback, icon, text string      # four cols: resource + indent, chat+feedback, icon, text string
     $r->print('<table cellspacing="3" cellpadding="0" bgcolor="#FFFFFF">' ."\n");      $r->print('<table cellspacing="0" cellpadding="3" border="0" bgcolor="#FFFFFF">' ."\n");
   
     my $condition = 0;      my $condition = 0;
     if ($ENV{'form.condition'}) {      if ($ENV{'form.condition'}) {
Line 934  sub new_handle { Line 941  sub new_handle {
     # instead of uris. The changes to this and the main rendering      # instead of uris. The changes to this and the main rendering
     # loop should be obvious.      # loop should be obvious.
     # Here's a simple example of the iterator.      # Here's a simple example of the iterator.
     # If there is a current resource      # Preprocess the map: Look for current URL, force inlined maps to display
     if ($currenturl) {  
         # Give me every resource...      my $mapIterator = $navmap->getIterator(undef, undef, {}, 1);
         my $mapIterator = $navmap->getIterator(undef, undef, {}, 1);      my $found = 0;
         my $found != 0;      my $depth = 1;
         my $depth = 1;      $mapIterator->next(); # discard the first BEGIN_MAP
         $mapIterator->next(); # discard the first BEGIN_MAP      my $curRes = $mapIterator->next();
         my $curRes = $mapIterator->next();      
               while ($depth > 0) {
         while ($depth > 0 && !$found) {          if ($curRes == $mapIterator->BEGIN_MAP()) {
             if (ref($curRes) && $curRes->src() eq $currenturl) {              $depth++;
                 # If this is the correct resource, be sure to           }
                 # show it by making sure the containing maps          if ($curRes == $mapIterator->END_MAP()) {
                 # are open.              $depth--;
           }
                 my $mapStack = $mapIterator->getStack();  
                 for my $map (@{$mapStack}) {          my $mapStack = $mapIterator->getStack();
                     if ($condition) {          if ($currenturl && !$ENV{'form.alreadyHere'} && ref($curRes) && 
                         undef $filterHash{$map->map_pc()};              $curRes->src() eq $currenturl) {
                     } else {              # If this is the correct resource, be sure to 
                         $filterHash{$map->map_pc()} = 1;              # show it by making sure the containing maps
                     }              # are open.
               
               for my $map (@{$mapStack}) {
                   if ($condition) {
                       undef $filterHash{$map->map_pc()};
                   } else {
                       $filterHash{$map->map_pc()} = 1;
                 }                  }
                 $found = 1;  
             }              }
             $curRes = $mapIterator->next();              $ENV{'form.alreadyHere'} = 1;
           }
               
           # Preprocessing: If we're inlining nav maps into the top-level display,
           # make sure we show this map!
           if ($inlineTopLevelMaps && ref($curRes) && $curRes->is_map && 
               scalar(@{$mapStack}) == 1) {
               if ($condition) {
                   undef $filterHash{$curRes->map_pc()};
               } else {
                   $filterHash{$curRes->map_pc()} = 1;
               }
         }          }
     }  
   
           $curRes = $mapIterator->next();
       }
       
     undef $res; # so we don't accidentally use it later      undef $res; # so we don't accidentally use it later
     my $indentLevel = 0;      my $indentLevel = 0;
     my $indentString = "<img src=\"/adm/lonIcons/whitespace1.gif\" width=\"25\" height=\"1\" alt=\"\" border=\"0\" />";      my $indentString = "<img src=\"/adm/lonIcons/whitespace1.gif\" width=\"25\" height=\"1\" alt=\"\" border=\"0\" />";
Line 971  sub new_handle { Line 996  sub new_handle {
     my $now = time();      my $now = time();
     my $in24Hours = $now + 24 * 60 * 60;      my $in24Hours = $now + 24 * 60 * 60;
     my $depth = 1;      my $depth = 1;
       my $displayedHereMarker = 0;
       
     # We know the first thing is a BEGIN_MAP (see "$self->{STARTED}"      # We know the first thing is a BEGIN_MAP (see "$self->{STARTED}"
     # code in iterator->next), so ignore the first one      # code in iterator->next), so ignore the first one
     my $mapIterator = $navmap->getIterator(undef, undef, \%filterHash,      my $mapIterator = $navmap->getIterator(undef, undef, \%filterHash,
                                            $condition);                                             $condition);
     $mapIterator->next();      $mapIterator->next();
     my $curRes = $mapIterator->next();      my $curRes = $mapIterator->next();
       my $deltadepth = 0;
   
       my @backgroundColors = ("#FFFFFF", "#F6F6F6");
       my $rowNum = 0;
   
     while ($depth > 0) {      while ($depth > 0) {
           # If we're in a new style course, and this is a BEGIN_MAP, END_MAP, or
           # map resource and the stack depth is only one, just plain ignore this resource
           # entirely. (This has the effect of inlining the resources in that map
           # in the nav map.)
           if ($inlineTopLevelMaps && scalar(@{$mapIterator->getStack()}) == 1 &&
               ref($curRes) && $curRes->is_map()) {
               # We let the normal depth stuff occur, but we need to shift everything
               # over by one to the left to make it look right.
               $deltadepth = -1;
               $curRes = $mapIterator->next();
               next;
           }
   
         if ($curRes == $mapIterator->BEGIN_MAP() ||          if ($curRes == $mapIterator->BEGIN_MAP() ||
             $curRes == $mapIterator->BEGIN_BRANCH()) {              $curRes == $mapIterator->BEGIN_BRANCH()) {
             $indentLevel++;              $indentLevel++;
Line 998  sub new_handle { Line 1041  sub new_handle {
             $depth--;              $depth--;
         }          }
   
           if ($depth == 1) { $deltadepth = 0; } # we're done shifting, because we're
                                                 # out of the inlined map
   
         # Is this resource being blotted out?          # Is this resource being blotted out?
         if (ref($curRes) && !advancedUser() && $curRes->randomout()) {          if (ref($curRes) && !advancedUser() && $curRes->randomout()) {
             $curRes = $mapIterator->next();              $curRes = $mapIterator->next();
Line 1068  sub new_handle { Line 1114  sub new_handle {
                 }                  }
   
             } else {              } else {
                 @parts[0] = "0"; # this is to get past foreach loop below                  $parts[0] = "0"; # this is to get past foreach loop below
                  # you can consider a non-problem resource as a resource                   # you can consider a non-problem resource as a resource
                  # with only one part without loss                    # with only one part without loss
               }
   
               # Is it a multipart problem with a single part, now in 
               # @parts with "0" filtered out? If so, forget it's a multi-part
               # problem and treat it like a single-part problem.
               if ( scalar(@parts) == 1 ) {
                   $multipart = 0;
             }              }
   
             # Display one part, in event of network error.              # Display one part, in event of network error.
Line 1097  sub new_handle { Line 1150  sub new_handle {
                     'symb='.&Apache::lonnet::escape($curRes->symb()).                      'symb='.&Apache::lonnet::escape($curRes->symb()).
                     '"';                      '"';
                 my $title = $curRes->title();                  my $title = $curRes->title();
                   if (!$title) {
                       $title = $curRes->src();
                       $title = substr ($title, rindex($title, "/") + 1);
                   }
                 my $partLabel = "";                  my $partLabel = "";
                 my $newBranchText = "";                  my $newBranchText = "";
   
Line 1124  sub new_handle { Line 1181  sub new_handle {
                 # Display the correct icon, link to open or shut map                  # Display the correct icon, link to open or shut map
                 if ($curRes->is_map()) {                   if ($curRes->is_map()) { 
                     my $mapId = $curRes->map_pc();                      my $mapId = $curRes->map_pc();
                     my $nowOpen = !defined($filterHash{$mapId});                      my $nowOpen = (!defined($filterHash{$mapId}));
                       if ($condition) {$nowOpen = !$nowOpen;}
                     $icon = $nowOpen ?                      $icon = $nowOpen ?
                         "folder_closed.gif" : "folder_opened.gif";                          "navmap.folder.closed.gif" : "navmap.folder.open.gif";
                     $icon = "<img src=\"/adm/lonIcons/$icon\" alt=\"\" border=\"0\" />";                      $icon = "<img src=\"/adm/lonIcons/$icon\" alt=\"\" border=\"0\" />";
                     $linkopen = "<a href=\"/adm/navmaps?filter=";                      $linkopen = "<a href=\"/adm/navmaps?filter=";
                     $linkopen .= ($nowOpen xor $condition) ?                       $linkopen .= ($nowOpen xor $condition) ? 
Line 1138  sub new_handle { Line 1196  sub new_handle {
                 }                  }
                                   
                 my $colorizer = "";                  my $colorizer = "";
                   my $color;
                 if ($curRes->is_problem()) {                  if ($curRes->is_problem()) {
                     my $status = $curRes->status($part);                      my $status = $curRes->status($part);
                     my $color = $colormap{$status};                      $color = $colormap{$status};
   
                     # Special case in the navmaps: If in less then                      # Special case in the navmaps: If in less then
                     # 24 hours, give it a bit of urgency                      # 24 hours, give it a bit of urgency
                     if ($status == $curRes->OPEN() &&                      if (($status == $curRes->OPEN() || $status == $curRes->ATTEMPTED() ||
                         $curRes->duedate() < time()+(24*60*60)) {                           $status == $curRes->TRIES_LEFT())
                           && $curRes->duedate() &&
                           $curRes->duedate() < time()+(24*60*60) && 
                           $curRes->duedate() > time()) {
                           $color = $hurryUpColor;
                       }
                       # Special case: If this is the last try, and there is
                       # more then one available, and it's not due yet, give a bit of urgency
                       my $tries = $curRes->tries($part);
                       my $maxtries = $curRes->maxtries($part);
                       if ($tries && $maxtries && $maxtries > 1 &&
                           $maxtries - $tries == 1 && $curRes->duedate() &&
                           $curRes->duedate() > time()) {
                         $color = $hurryUpColor;                          $color = $hurryUpColor;
                     }                      }
                     if ($color ne "") {                      if ($color ne "") {
Line 1157  sub new_handle { Line 1228  sub new_handle {
                     $nonLinkedText .= ' <i>(hidden)</i> ';                      $nonLinkedText .= ' <i>(hidden)</i> ';
                 }                  }
   
                   $rowNum++;
                   my $backgroundColor = $backgroundColors[$rowNum % scalar(@backgroundColors)];
   
                 # FIRST COL: The resource indentation, branch icon, and name                  # FIRST COL: The resource indentation, branch icon, and name
                 $r->print("  <tr><td align=\"left\" valign=\"bottom\">\n");                  $r->print("  <tr bgcolor=\"$backgroundColor\"><td align=\"left\" valign=\"center\" width=\"60%\">\n");
   
                 # print indentation                  # print indentation
                 for (my $i = 0; $i < $indentLevel - $deltalevel; $i++) {                  for (my $i = 0; $i < $indentLevel - $deltalevel + $deltadepth; $i++) {
                     $r->print($indentString);                      $r->print($indentString);
                 }                  }
   
Line 1171  sub new_handle { Line 1245  sub new_handle {
                 my $curMarkerEnd = "";                  my $curMarkerEnd = "";
   
                 # Is this the current resource?                  # Is this the current resource?
                 if ($curRes->src() eq $currenturl) {                  if ($curRes->src() eq $currenturl && !$displayedHereMarker) {
                     $curMarkerBegin = '<a name="curloc" /><font color="red" size="+2">&gt; </font>';                      $curMarkerBegin = '<a name="curloc" /><font color="red" size="+2">&gt; </font>';
                     $curMarkerEnd = '<font color="red" size="+2"> &lt;</font>';                      $curMarkerEnd = '<font color="red" size="+2"> &lt;</font>';
                       $displayedHereMarker = 1;
                 }                  }
   
                 if ($curRes->is_problem() && $part ne "0" && !$condensed) {                   if ($curRes->is_problem() && $part ne "0" && !$condensed) { 
Line 1188  sub new_handle { Line 1263  sub new_handle {
   
                 if ($curRes->{RESOURCE_ERROR}) {                  if ($curRes->{RESOURCE_ERROR}) {
                     $r->print(&Apache::loncommon::help_open_topic ("Navmap_Host_Down",                      $r->print(&Apache::loncommon::help_open_topic ("Navmap_Host_Down",
                                                   '<font size="-1">Host down</font>'));                                                '<font size="-1">Host down</font>'));
                     }                      }
   
                 my $discussionHTML = ""; my $feedbackHTML = "";                  my $discussionHTML = ""; my $feedbackHTML = "";
   
                 # SECOND COL: Is there text or feedback?                  # SECOND COL: Is there text, feedback, errors??
                 if ($curRes->hasDiscussion()) {                  if ($curRes->hasDiscussion()) {
                     $discussionHTML = $linkopen .                      $discussionHTML = $linkopen .
                         '<img border="0" src="/adm/lonMisc/chat.gif" />' .                          '<img border="0" src="/adm/lonMisc/chat.gif" />' .
Line 1212  sub new_handle { Line 1287  sub new_handle {
                     }                      }
                 }                  }
   
                 $r->print("<td align=\"left\" valign=\"bottom\">$discussionHTML$feedbackHTML</td>");                  $r->print("<td width=\"75\" align=\"left\" valign=\"center\">$discussionHTML$feedbackHTML&nbsp;</td>");
   
                 # Is this the first displayed part of a multi-part problem                  # Is this the first displayed part of a multi-part problem
                 # that has not been condensed, so we should suppress these two                  # that has not been condensed, so we should suppress these two
Line 1225  sub new_handle { Line 1300  sub new_handle {
                     my $icon = $statusIconMap{$curRes->status($part)};                      my $icon = $statusIconMap{$curRes->status($part)};
                     my $alt = $iconAltTags{$icon};                      my $alt = $iconAltTags{$icon};
                     if ($icon) {                      if ($icon) {
                         $r->print("<td valign=\"bottom\" width=\"50\" align=\"right\">$linkopen<img src=\"/adm/lonIcons/$icon\" border=\"0\" alt=\"$alt\" />$linkclose</td>\n");                          $r->print("<td width=\"30\" valign=\"center\" width=\"50\" align=\"right\">$linkopen<img width=\"25\" height=\"25\" src=\"/adm/lonIcons/$icon\" border=\"0\" alt=\"$alt\" />$linkclose</td>\n");
                     } else {                      } else {
                         $r->print("<td></td>\n");                          $r->print("<td width=\"30\">&nbsp;</td>\n");
                     }                      }
                 } else { # not problem, no icon                  } else { # not problem, no icon
                     $r->print("<td></td>\n");                      $r->print("<td width=\"30\">&nbsp;</td>\n");
                 }                  }
   
                 # FOURTH COL: Text description                  # FOURTH COL: Text description
                 $r->print("<td $colorizer align=\"right\" valign=\"bottom\">\n");                  #$r->print("<td $colorizer align=\"right\" valign=\"center\">\n");
                   $r->print("<td align=\"right\" valign=\"center\">\n");
                                   
                 if ($curRes->kind() eq "res" &&                  if ($curRes->kind() eq "res" &&
                     $curRes->is_problem() &&                      $curRes->is_problem() &&
                     !$firstDisplayed) {                      !$firstDisplayed) {
                       $r->print ("<font color=\"$color\"><b>") if ($color);
                     $r->print (getDescription($curRes, $part));                      $r->print (getDescription($curRes, $part));
                       $r->print ("</b></font>") if ($color);
                 }                  }
                 if ($curRes->is_map() && advancedUser() && $curRes->randompick()) {                  if ($curRes->is_map() && advancedUser() && $curRes->randompick()) {
                     $r->print('(randomly select ' . $curRes->randompick() .')');                      $r->print('(randomly select ' . $curRes->randompick() .')');
                 }                  }
   
                 $r->print("</td></tr>\n");                  $r->print("&nbsp;</td></tr>\n");
             }              }
         }          }
         $curRes = $mapIterator->next();          $curRes = $mapIterator->next();
Line 1323  sub getDescription { Line 1401  sub getDescription {
         return "Open " . timeToHumanString($res->opendate($part));          return "Open " . timeToHumanString($res->opendate($part));
     }      }
     if ($status == $res->OPEN) {      if ($status == $res->OPEN) {
         if ($res->duedate()) {          if ($res->duedate($part)) {
             return "Due " . timeToHumanString($res->duedate($part));              return "Due " . timeToHumanString($res->duedate($part));
         } else {          } else {
             return "Open, no due date";              return "Open, no due date";
Line 1345  sub getDescription { Line 1423  sub getDescription {
         return "Not yet graded.";          return "Not yet graded.";
     }      }
     if ($status == $res->TRIES_LEFT) {      if ($status == $res->TRIES_LEFT) {
         my $tries = $res->tries();          my $tries = $res->tries($part);
         my $maxtries = $res->maxtries();          my $maxtries = $res->maxtries($part);
         my $triesString = "($tries of $maxtries tries used)";          my $triesString = "";
           if ($tries && $maxtries) {
               $triesString = "<font size=\"-1\"><i>($tries of $maxtries tries used)</i></font>";
               if ($maxtries > 1 && $maxtries - $tries == 1) {
                   $triesString = "<b>$triesString</b>";
               }
           }
         if ($res->duedate()) {          if ($res->duedate()) {
             return "Due " . timeToHumanString($res->duedate($part)) .              return "Due " . timeToHumanString($res->duedate($part)) .
                 " $triesString";                  " $triesString";
Line 1442  sub timeToHumanString { Line 1526  sub timeToHumanString {
         # Less then 5 days away, display day of the week and          # Less then 5 days away, display day of the week and
         # HH:MM          # HH:MM
         if ( $delta < $day * 5 ) {          if ( $delta < $day * 5 ) {
             my $timeStr = strftime("%A at %I:%M %P", localtime($time));              my $timeStr = strftime("%A, %b %e at %I:%M %P", localtime($time));
             $timeStr =~ s/12:00 am/midnight/;              $timeStr =~ s/12:00 am/midnight/;
             $timeStr =~ s/12:00 pm/noon/;              $timeStr =~ s/12:00 pm/noon/;
             return ($inPast ? "last " : "next ") .              return ($inPast ? "last " : "next ") .
Line 1634  sub new { Line 1718  sub new {
         $self->{EMAIL_STATUS} = \%emailstatus;          $self->{EMAIL_STATUS} = \%emailstatus;
                   
     }          }    
   
       $self->{PARM_CACHE} = {};
           
     bless($self);      bless($self);
                   
Line 1755  sub finishResource { Line 1841  sub finishResource {
 sub parmval {  sub parmval {
     my $self = shift;      my $self = shift;
     my ($what,$symb)=@_;      my ($what,$symb)=@_;
       my $hashkey = $what."|||".$symb;
   
       if (defined($self->{PARM_CACHE}->{$hashkey})) {
           return $self->{PARM_CACHE}->{$hashkey};
       }
   
       my $result = $self->parmval_real($what, $symb);
       $self->{PARM_CACHE}->{$hashkey} = $result;
       return $result;
   }
   
   sub parmval_real {
       my $self = shift;
       my ($what,$symb) = @_;
   
     my $cid=$ENV{'request.course.id'};      my $cid=$ENV{'request.course.id'};
     my $csec=$ENV{'request.course.sec'};      my $csec=$ENV{'request.course.sec'};
     my $uname=$ENV{'user.name'};      my $uname=$ENV{'user.name'};
Line 2120  sub populateStack { Line 2221  sub populateStack {
     my $self=shift;      my $self=shift;
     my $stack = shift;      my $stack = shift;
   
     push @$stack, $self->{HERE};      push @$stack, $self->{HERE} if ($self->{HERE});
   
     if ($self->{RECURSIVE_ITERATOR_FLAG}) {      if ($self->{RECURSIVE_ITERATOR_FLAG}) {
         $self->{RECURSIVE_ITERATOR}->populateStack($stack);          $self->{RECURSIVE_ITERATOR}->populateStack($stack);
Line 2216  These are methods that help you retrieve Line 2317  These are methods that help you retrieve
   
 =item * B<to>: Returns the "to" value from the compiled nav map. (It is likely you want to use B<getNext> instead.)  =item * B<to>: Returns the "to" value from the compiled nav map. (It is likely you want to use B<getNext> instead.)
   
 =item * B<type>: Returns the type of the resource, "start", "normal", or "finish".   
   
 =back  =back
   
 =cut  =cut
   
 # These info functions can be used directly, as they don't return  # These info functions can be used directly, as they don't return
 # resource information.  # resource information.
   sub comesfrom { my $self=shift; return $self->navHash("comesfrom_", 1); }
 sub ext { my $self=shift; return $self->navHash("ext_", 1) eq 'true:'; }  sub ext { my $self=shift; return $self->navHash("ext_", 1) eq 'true:'; }
   sub from { my $self=shift; return $self->navHash("from_", 1); }
 sub goesto { my $self=shift; return $self->navHash("goesto_", 1); }  sub goesto { my $self=shift; return $self->navHash("goesto_", 1); }
 sub kind { my $self=shift; return $self->navHash("kind_", 1); }  sub kind { my $self=shift; return $self->navHash("kind_", 1); }
 sub randomout { my $self=shift; return $self->navHash("randomout_", 1); }  sub randomout { my $self=shift; return $self->navHash("randomout_", 1); }
Line 2247  sub symb { Line 2348  sub symb {
 }  }
 sub title { my $self=shift; return $self->navHash("title_", 1); }  sub title { my $self=shift; return $self->navHash("title_", 1); }
 sub to { my $self=shift; return $self->navHash("to_", 1); }  sub to { my $self=shift; return $self->navHash("to_", 1); }
 sub type { my $self=shift; return $self->navHash("type_", 1); }  
   
 =pod  =pod
   
Line 2463  sub getReturnHash { Line 2563  sub getReturnHash {
     my $self = shift;      my $self = shift;
           
     if (!defined($self->{RETURN_HASH})) {      if (!defined($self->{RETURN_HASH})) {
         my %tmpHash = &Apache::lonnet::restore($self->symb());          my %tmpHash  = &Apache::lonnet::restore($self->symb());
         $self->{RETURN_HASH} = \%tmpHash;          $self->{RETURN_HASH} = \%tmpHash;
     }      }
 }         }       
Line 2509  sub hasDiscussion { Line 2609  sub hasDiscussion {
   
 sub getFeedback {  sub getFeedback {
     my $self = shift;      my $self = shift;
     return $self->{NAV_MAP}->getFeedback($self->symb());      return $self->{NAV_MAP}->getFeedback($self->src());
 }  }
   
 =pod  =pod
Line 2554  sub extractParts { Line 2654  sub extractParts {
   
     $self->{PARTS} = [];      $self->{PARTS} = [];
   
     # Retrieve part count      # Retrieve part count, if this is a problem
     my $metadata = &Apache::lonnet::metadata($self->src(), 'allpossiblekeys');      if ($self->is_problem()) {
     if (!$metadata) {          my $metadata = &Apache::lonnet::metadata($self->src(), 'allpossiblekeys');
         $self->{RESOURCE_ERROR} = 1;          if (!$metadata) {
         $self->{PARTS} = [];              $self->{RESOURCE_ERROR} = 1;
         return;              $self->{PARTS} = [];
     }              return;
   
     foreach (split(/\,/,$metadata)) {  
         if ($_ =~ /^parameter\_(.*)\_opendate$/) {  
             push @{$self->{PARTS}}, $1;  
         }          }
           
           foreach (split(/\,/,$metadata)) {
               if ($_ =~ /^parameter\_(.*)\_opendate$/) {
                   push @{$self->{PARTS}}, $1;
               }
           }
           
           
           # Is this possible to do in one line? - Jeremy
           my @sortedParts = sort @{$self->{PARTS}};
           $self->{PARTS} = \@sortedParts;
     }      }
   
       
     # Is this possible to do in one line? - Jeremy  
     my @sortedParts = sort @{$self->{PARTS}};  
     $self->{PARTS} = \@sortedParts;  
   
     return;      return;
 }  }
   
Line 2821  sub status { Line 2923  sub status {
     # If it's WRONG...      # If it's WRONG...
     if ($completionStatus == INCORRECT || $completionStatus == INCORRECT_BY_OVERRIDE) {      if ($completionStatus == INCORRECT || $completionStatus == INCORRECT_BY_OVERRIDE) {
         # and there are TRIES LEFT:          # and there are TRIES LEFT:
         if ($self->tries() < $self->maxtries()) {          if ($self->tries($part) < $self->maxtries($part) || !$self->maxtries($part)) {
             return TRIES_LEFT;              return TRIES_LEFT;
         }          }
         return INCORRECT; # otherwise, return orange; student can't fix this          return INCORRECT; # otherwise, return orange; student can't fix this
Line 2837  sub status { Line 2939  sub status {
   
 =over 4  =over 4
   
 =item * B<getNext>(): Gets the next resource in the navmap after this one.  =item * B<getNext>($alreadySeenHashRef): Retreive an array of the possible next resources after this one. Always returns an array, even in the one- or zero-element case. The "alreadySeenHashRef" is an optional parameter that can be passed in to the method. If $$alreadySeenHashRef{$res->id()} is true in that hash, getNext will not return it in the list. In other words, you can use it to suppress resources you've already seen in the getNext method directly.
   
 =cut  =item * B<getPrevious>($alreadySeenHashRef): Retreive an array of the possible previous resources from this one. Always returns an array, even in the one- or zero-element case. $alreadySeenHashRef is the same as in getNext.
   
 # For the simple single-link case, to get from a resource to the next  =cut
 # resource, you need to look up the "to_" link in the nav hash, then  
 # follow that with the "goesto_" link.  
   
 sub getNext {  sub getNext {
     my $self = shift;      my $self = shift;
     my $alreadySeenHash = shift;      my $alreadySeenHash = shift;
     my @branches;      my @branches;
     my $to = $self->to();      my $to = $self->to();
     foreach my $branch ( split(/\,/, $to) ) {      foreach my $branch ( split(/,/, $to) ) {
         my $choice = $self->{NAV_MAP}->getById($branch);          my $choice = $self->{NAV_MAP}->getById($branch);
         my $next = $choice->goesto();          my $next = $choice->goesto();
         $next = $self->{NAV_MAP}->getById($next);          $next = $self->{NAV_MAP}->getById($next);
Line 2866  sub getNext { Line 2966  sub getNext {
     }      }
     return \@branches;      return \@branches;
 }  }
   
   sub getPrevious {
       my $self = shift;
       my $alreadySeenHash = shift;
       my @branches;
       my $from = $self->from();
       foreach my $branch ( split /,/, $from) {
           my $choice = $self->{NAV_MAP}->getById($branch);
           my $prev = $choice->comesfrom();
           $prev = $self->{NAV_MAP}->getById($prev);
   
           # Skip it if we've already seen it or the user doesn't have
           # browse privs
           my $browsePriv = &Apache::lonnet::allowed('bre', $self->src);
           if (!defined($alreadySeenHash) ||
               !defined($alreadySeenHash->{$prev->{ID}}) ||
               ($browsePriv ne '2' && $browsePriv ne 'F')) {
               push @branches, $prev;
           }
       }
       return \@branches;
   }
   
 =pod  =pod
   

Removed from v.1.74  
changed lines
  Added in v.1.88


FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>