[LON-CAPA-cvs] cvs: loncom /html/adm/help/tex Navmap_Host_Down.tex /interface lonnavmaps.pm doc/loncapafiles loncapafiles.lpml

bowersj2 lon-capa-cvs@mail.lon-capa.org
Fri, 04 Oct 2002 20:34:04 -0000


This is a MIME encoded message

--bowersj21033763644
Content-Type: text/plain

bowersj2		Fri Oct  4 16:34:04 2002 EDT

  Added files:                 
    /loncom/html/adm/help/tex	Navmap_Host_Down.tex 

  Modified files:              
    /doc/loncapafiles	loncapafiles.lpml 
    /loncom/interface	lonnavmaps.pm 
  Log:
  * Added Show all resources link.
  * Part counts now show on condensed multipart problems.
  * Detects and handles case where problem resource is not currently accessible.
  * Assorted table tag fixes for better aesthetics.
  
  
--bowersj21033763644
Content-Type: text/plain
Content-Disposition: attachment; filename="bowersj2-20021004163404.txt"

Index: doc/loncapafiles/loncapafiles.lpml
diff -u doc/loncapafiles/loncapafiles.lpml:1.177 doc/loncapafiles/loncapafiles.lpml:1.178
--- doc/loncapafiles/loncapafiles.lpml:1.177	Tue Oct  1 15:15:22 2002
+++ doc/loncapafiles/loncapafiles.lpml	Fri Oct  4 16:34:04 2002
@@ -3,7 +3,7 @@
 <!-- loncapafiles.lpml -->
 <!-- Scott Harrison -->
 
-<!-- $Id: loncapafiles.lpml,v 1.177 2002/10/01 19:15:22 bowersj2 Exp $ -->
+<!-- $Id: loncapafiles.lpml,v 1.178 2002/10/04 20:34:04 bowersj2 Exp $ -->
 
 <!--
 
@@ -1654,6 +1654,7 @@
 Latex_Header.tex;
 Login_To_LON-CAPA.tex;
 Metadata_Description.tex;
+Navmap_Host_Down.tex;
 Numerical_Response_Advanced_Example.tex;
 Numerical_Response_Format.tex;
 Numerical_Response_Intro.tex;
Index: loncom/interface/lonnavmaps.pm
diff -u loncom/interface/lonnavmaps.pm:1.65 loncom/interface/lonnavmaps.pm:1.66
--- loncom/interface/lonnavmaps.pm:1.65	Fri Oct  4 11:38:22 2002
+++ loncom/interface/lonnavmaps.pm	Fri Oct  4 16:34:04 2002
@@ -1,7 +1,7 @@
 # The LearningOnline Network with CAPA
 # Navigate Maps Handler
 #
-# $Id: lonnavmaps.pm,v 1.65 2002/10/04 15:38:22 bowersj2 Exp $
+# $Id: lonnavmaps.pm,v 1.66 2002/10/04 20:34:04 bowersj2 Exp $
 #
 # Copyright Michigan State University Board of Trustees
 #
@@ -841,12 +841,12 @@
     $r->print("<h3>$date</h3>\n");
     $r->rflush();
     if ($navmap->{LAST_CHECK}) {
-	$r->print('<img src="/adm/lonMisc/chat.gif"> New discussion since '.
-		  timeToHumanString($navmap->{LAST_CHECK}).
-		  '<br><img src="/adm/lonMisc/feedback.gif"> New message (click to open)<p>'); 
+        $r->print('<img src="/adm/lonMisc/chat.gif"> New discussion since '.
+                  timeToHumanString($navmap->{LAST_CHECK}).
+                  '<br><img src="/adm/lonMisc/feedback.gif"> New message (click to open)<p>'); 
     } else {
-	$r->print('<img src="/adm/lonMisc/chat.gif"> Discussions'.
-		  '<br><img src="/adm/lonMisc/feedback.gif"> New message (click to open)<p>'); 
+        $r->print('<img src="/adm/lonMisc/chat.gif"> Discussions'.
+                  '<br><img src="/adm/lonMisc/feedback.gif"> New message (click to open)<p>'); 
     }
     #if (($currenturl=~/^\/res/) &&
     #    ($currenturl!~/^\/res\/adm/)) {
@@ -882,22 +882,22 @@
     my $hurryUpColor = "#FFCCCC";
 
     my %statusIconMap = 
-	( $res->NETWORK_FAILURE    => '',
-	  $res->NOTHING_SET        => '',
-	  $res->CORRECT            => 'navmap.correct.gif',
-	  $res->EXCUSED            => 'navmap.correct.gif',
-	  $res->PAST_DUE_NO_ANSWER => 'navmap.wrong.gif',
-	  $res->PAST_DUE_ANSWER_LATER => 'navmap.wrong.gif',
-	  $res->ANSWER_OPEN        => 'navmap.wrong.gif',
-	  $res->OPEN_LATER         => '',
-	  $res->TRIES_LEFT         => 'navmap.open.gif',
-	  $res->INCORRECT          => 'navmap.wrong.gif',
-	  $res->OPEN               => 'navmap.open.gif' );
+        ( $res->NETWORK_FAILURE    => '',
+          $res->NOTHING_SET        => '',
+          $res->CORRECT            => 'navmap.correct.gif',
+          $res->EXCUSED            => 'navmap.correct.gif',
+          $res->PAST_DUE_NO_ANSWER => 'navmap.wrong.gif',
+          $res->PAST_DUE_ANSWER_LATER => 'navmap.wrong.gif',
+          $res->ANSWER_OPEN        => 'navmap.wrong.gif',
+          $res->OPEN_LATER         => '',
+          $res->TRIES_LEFT         => 'navmap.open.gif',
+          $res->INCORRECT          => 'navmap.wrong.gif',
+          $res->OPEN               => 'navmap.open.gif' );
 
     my %condenseStatuses =
-	( $res->NETWORK_FAILURE    => 1,
-	  $res->NOTHING_SET        => 1,
-	  $res->CORRECT            => 1 );
+        ( $res->NETWORK_FAILURE    => 1,
+          $res->NOTHING_SET        => 1,
+          $res->CORRECT            => 1 );
 
     my %filterHash;
     # Figure out what we're not displaying
@@ -912,14 +912,18 @@
     $currenturl=~s/^[^\/]+//;
     my $queryAdd = "postdata=" . &Apache::lonnet::escape($currenturl);
 
-    $r->print("$currenturl<br/>");
-    
+    $r->print('<a href="navmaps?condition=1&filter=">Show All Resources</a><br /><br />');
 
     # Begin the HTML table
     # four cols: resource + indent, chat+feedback, icon, text string
     $r->print('<table cellspacing="3" cellpadding="0" bgcolor="#FFFFFF">' ."\n");
 
-    my $mapIterator = $navmap->getIterator(undef, undef, \%filterHash, 0);
+    my $condition = 0;
+    if ($ENV{'form.condition'}) {
+	$condition = 1;
+    }
+
+    my $mapIterator = $navmap->getIterator(undef, undef, \%filterHash, $condition);
     my $curRes = $mapIterator->next();
     undef $res; # so we don't accidentally use it later
     my $indentLevel = -1;
@@ -944,65 +948,66 @@
 
         if (ref($curRes) && $curRes->src()) {
 
-	    # Step one: Decide which parts to show
-	    my @parts = @{$curRes->parts()};
-	    my $multipart = scalar(@parts) > 1;
-	    my $condensed = 0;
-		
+            # Step one: Decide which parts to show
+            my @parts = @{$curRes->parts()};
+            my $multipart = scalar(@parts) > 1;
+            my $condensed = 0;
+                
             if ($curRes->is_problem()) {
-		# Is it multipart?
+                # Is it multipart?
 
-		if ($multipart) {
-		    # If it's multipart, see if part 0 is "open"
-		    # if it is, display all parts, if it isn't,
-		    # just display first
-		    if (!$curRes->opendate("0")) {
-			@parts = ("0"); # just display the zero-th part
-		    } else {
-			# Otherwise, only display part 0 if we want to 
-			# attach feedback or email information to it
-			if ($curRes->hasDiscussion() || $curRes->getFeedback()) {
-			    shift @parts;
-			} else {
-			    # If there's discussion or feedback, that counts
-			    # as a difference, so display the parts.
-			    
-			    # Now, we decide whether to condense the
-			    # parts due to similarity
-			    my $status = $curRes->status($parts[1]);
-			    my $due = $curRes->duedate($parts[1]);
-			    my $open = $curRes->opendate($parts[1]);
-			    my $statusAllSame = 1;
-			    my $dueAllSame = 1;
-			    my $openAllSame = 1;
-			    for (my $i = 2; $i < scalar(@parts); $i++) {
-				if ($curRes->status($parts[$i]) != $status){
-				    $statusAllSame = 0;
-				}
-				if ($curRes->duedate($parts[$i]) != $due ) {
-				    $dueAllSame = 0;
-				}
-				if ($curRes->opendate($parts[$i]) != $open) {
-				    $openAllSame = 0;
-				}
-			    }
-			    
-			    # $allSame is true if all the statuses were
-			    # the same. Now, if they are all the same and
-			    # match one of the statuses to condense, or they
-			    # are all open with the same due date, or they are
-			    # all OPEN_LATER with the same open date, display the
-			    # status of the first non-zero part (to get the 'correct'
-			    # status right, since 0 is never 'correct' or 'open').
-			    if (($statusAllSame && defined($condenseStatuses{$status})) ||
-				($dueAllSame && $status == $curRes->OPEN && $statusAllSame)||
-				($openAllSame && $status == $curRes->OPEN_LATER && $statusAllSame) ){
-				@parts = ($parts[1]);
-				$condensed = 1;
-			    }
-			}
-		    }
-		}
+                if ($multipart) {
+                    # If it's multipart, see if part 0 is "open"
+                    # if it is, display all parts, if it isn't,
+                    # just display first
+                    if (!$curRes->opendate("0")) {
+                        @parts = ("0"); # just display the zero-th part
+			$condensed = 1;
+                    } else {
+                        # Otherwise, only display part 0 if we want to 
+                        # attach feedback or email information to it
+                        if ($curRes->hasDiscussion() || $curRes->getFeedback()) {
+                            shift @parts;
+                        } else {
+                            # If there's discussion or feedback, that counts
+                            # as a difference, so display the parts.
+                            
+                            # Now, we decide whether to condense the
+                            # parts due to similarity
+                            my $status = $curRes->status($parts[1]);
+                            my $due = $curRes->duedate($parts[1]);
+                            my $open = $curRes->opendate($parts[1]);
+                            my $statusAllSame = 1;
+                            my $dueAllSame = 1;
+                            my $openAllSame = 1;
+                            for (my $i = 2; $i < scalar(@parts); $i++) {
+                                if ($curRes->status($parts[$i]) != $status){
+                                    $statusAllSame = 0;
+                                }
+                                if ($curRes->duedate($parts[$i]) != $due ) {
+                                    $dueAllSame = 0;
+                                }
+                                if ($curRes->opendate($parts[$i]) != $open) {
+                                    $openAllSame = 0;
+                                }
+                            }
+                            
+                            # $allSame is true if all the statuses were
+                            # the same. Now, if they are all the same and
+                            # match one of the statuses to condense, or they
+                            # are all open with the same due date, or they are
+                            # all OPEN_LATER with the same open date, display the
+                            # status of the first non-zero part (to get the 'correct'
+                            # status right, since 0 is never 'correct' or 'open').
+                            if (($statusAllSame && defined($condenseStatuses{$status})) ||
+                                ($dueAllSame && $status == $curRes->OPEN && $statusAllSame)||
+                                ($openAllSame && $status == $curRes->OPEN_LATER && $statusAllSame) ){
+                                @parts = ($parts[1]);
+                                $condensed = 1;
+                            }
+                        }
+                    }
+                }
 
             } else {
                 @parts[0] = "0"; # this is to get past foreach loop below
@@ -1010,10 +1015,17 @@
                  # with only one part without loss
             }
 
-	    # Step two: Show the parts
+            # Display one part, in event of network error.
+            # If this is a single part, we can at least show the correct
+            # status, but if it's multipart, we're lost.
+            if ($curRes->{RESOURCE_ERROR}) {
+                @parts = ("0");
+            }
+
+            # Step two: Show the parts
             foreach my $part (@parts) {
 
-		my $deltalevel = 0; # for inserting the branch icon
+                my $deltalevel = 0; # for inserting the branch icon
                 
                 # For each thing we're displaying...
 
@@ -1034,7 +1046,7 @@
                 if ($isNewBranch) {
                     $newBranchText = "<img src=\"/adm/lonIcons/branch.gif\" border=\"0\">";
                     $isNewBranch = 0;
-		    $deltalevel = 1;
+                    $deltalevel = 1;
                 }
 
                 # links to open and close the folders
@@ -1043,11 +1055,11 @@
 
                 my $icon = "<img src=\"/adm/lonIcons/html.gif\" alt=\"\" border=\"0\" />";
                 if ($curRes->is_problem()) { 
-		    if ($part eq "0" || $condensed) {
-			$icon = '<img src="/adm/lonIcons/problem.gif" alt="" border=\"0\" />'; 
-		    } else {
-			$icon = $indentString;
-		    }
+                    if ($part eq "0" || $condensed) {
+                        $icon = '<img src="/adm/lonIcons/problem.gif" alt="" border=\"0\" />'; 
+                    } else {
+                        $icon = $indentString;
+                    }
                 }
 
                 # Display the correct icon, link to open or shut map
@@ -1056,12 +1068,12 @@
                     my $nowOpen = !defined($filterHash{$mapId});
                     $icon = $nowOpen ?
                         "folder_closed.gif" : "folder_opened.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 .= $nowOpen ? 
+                    $linkopen .= ($nowOpen xor $condition) ? 
                         addToFilter(\%filterHash, $mapId) :
                         removeFromFilter(\%filterHash, $mapId);
-                    $linkopen .= "&$queryAdd\">";
+                    $linkopen .= "&condition=$condition&$queryAdd\">";
                     $linkclose = "</a>";
                     
                 }
@@ -1075,8 +1087,8 @@
                     }
                 }
 
-		# FIRST ROW: The resource indentation, branch icon, and name
-                $r->print("  <tr><td align=\"left\" valign=\"top\">\n");
+                # FIRST COL: The resource indentation, branch icon, and name
+                $r->print("  <tr><td align=\"left\" valign=\"bottom\">\n");
 
                 # print indentation
                 for (my $i = 0; $i < $indentLevel - $deltalevel; $i++) {
@@ -1085,64 +1097,74 @@
 
                 $r->print("  ${newBranchText}${linkopen}$icon${linkclose}\n");
 
+		my $nonLinkedText = "";
+		
                 if ($curRes->is_problem() && $part != "0" && !$condensed) { 
-		    $partLabel = " (Part $part)"; 
-		    $title = "";
-		}
-
-                $r->print("  <a href=\"$link\">$title$partLabel</a></td>");
-
-		my $discussionHTML = ""; my $feedbackHTML = "";
-
-		# SECOND ROW: Is there text or feedback?
-		if ($curRes->hasDiscussion()) {
-		    $discussionHTML = $linkopen .
-			'<img border="0" src="/adm/lonMisc/chat.gif" />' .
-			$linkclose;
-		}
-
-		if ($curRes->getFeedback()) {
-		    my $feedback = $curRes->getFeedback();
-		    foreach (split(/\,/, $feedback)) {
-			if ($_) {
-			    $feedbackHTML .= '&nbsp;<a href="/adm/email?display='
-				. &Apache::lonnet::escape($_) . '">'
-				. '<img src="/adm/lonMisc/feedback.gif" '
-				. 'border="0" /></a>';
-			}
-		    }
-		}
-
-		$r->print("<td align=\"left\">$discussionHTML$feedbackHTML</td>");
-
-		# Is this the first displayed part of a multi-part problem
-		# that has not been condensed, so we should suppress these two
-		# columns?
-		my $firstDisplayed = !$condensed && $multipart && $part eq "0";
-
-		# THIRD ROW: Problem status icon
-		if ($curRes->is_problem() &&
-		    !$firstDisplayed) {
-		    my $icon = $statusIconMap{$curRes->status($part)};
-		    if ($icon) {
-			$r->print("<td width=\"50\" align=\"right\">$linkopen<img src=\"/adm/lonIcons/$icon\" border=\"0\" />$linkclose</td>\n");
-		    } else {
-			$r->print("<td></td>\n");
-		    }
-		} else { # not problem, no icon
-		    $r->print("<td></td>\n");
-		}
+                    $partLabel = " (Part $part)"; 
+                    $title = "";
+                }
+                if ($multipart && $condensed) {
+                    $nonLinkedText = ' (' . $curRes->countParts() . ' parts)';
+                }
 
- 		# FOURTH ROW: Text description
-		$r->print("<td $colorizer align=\"right\">\n");
+                $r->print("  <a href=\"$link\">$title$partLabel</a> $nonLinkedText");
+
+                if ($curRes->{RESOURCE_ERROR}) {
+                    $r->print(&Apache::loncommon::help_open_topic ("Navmap_Host_Down",
+                                                  '<font size="-1">Host down</font>'));
+                    }
+
+                my $discussionHTML = ""; my $feedbackHTML = "";
+
+                # SECOND COL: Is there text or feedback?
+                if ($curRes->hasDiscussion()) {
+                    $discussionHTML = $linkopen .
+                        '<img border="0" src="/adm/lonMisc/chat.gif" />' .
+                        $linkclose;
+                }
+
+                if ($curRes->getFeedback()) {
+                    my $feedback = $curRes->getFeedback();
+                    foreach (split(/\,/, $feedback)) {
+                        if ($_) {
+                            $feedbackHTML .= '&nbsp;<a href="/adm/email?display='
+                                . &Apache::lonnet::escape($_) . '">'
+                                . '<img src="/adm/lonMisc/feedback.gif" '
+                                . 'border="0" /></a>';
+                        }
+                    }
+                }
+
+                $r->print("<td align=\"left\" valign=\"bottom\">$discussionHTML$feedbackHTML</td>");
+
+                # Is this the first displayed part of a multi-part problem
+                # that has not been condensed, so we should suppress these two
+                # columns?
+                my $firstDisplayed = !$condensed && $multipart && $part eq "0";
+
+                # THIRD ROW: Problem status icon
+                if ($curRes->is_problem() &&
+                    !$firstDisplayed) {
+                    my $icon = $statusIconMap{$curRes->status($part)};
+                    if ($icon) {
+                        $r->print("<td valign=\"bottom\" width=\"50\" align=\"right\">$linkopen<img src=\"/adm/lonIcons/$icon\" border=\"0\" />$linkclose</td>\n");
+                    } else {
+                        $r->print("<td></td>\n");
+                    }
+                } else { # not problem, no icon
+                    $r->print("<td></td>\n");
+                }
+
+                # FOURTH ROW: Text description
+                $r->print("<td $colorizer align=\"right\" valign=\"bottom\">\n");
                 
                 if ($curRes->kind() eq "res" &&
                     $curRes->is_problem() &&
-		    !$firstDisplayed) {
+                    !$firstDisplayed) {
                     $r->print (getDescription($curRes, $part));
                 }
 
-		$r->print("</td></tr>\n");
+                $r->print("</td></tr>\n");
             }
         }
         $curRes = $mapIterator->next();
@@ -1220,11 +1242,11 @@
         return "Opens: " . timeToHumanString($res->opendate($part));
     }
     if ($status == $res->OPEN) {
-	if ($res->duedate()) {
-	    return "Due: $status " . timeToHumanString($res->duedate($part));
-	} else {
-	    return "Open, no due date";
-	}
+        if ($res->duedate()) {
+            return "Due: $status " . timeToHumanString($res->duedate($part));
+        } else {
+            return "Open, no due date";
+        }
     }
     if ($status == $res->PAST_DUE_ANSWER_LATER) {
         return "Answer opens: " . timeToHumanString($res->answerdate($part));
@@ -1236,18 +1258,18 @@
         return "Answer available";
     }
     if ($status == $res->EXCUSED) {
-	return "Excused by instructor";
+        return "Excused by instructor";
     }
     if ($status == $res->TRIES_LEFT) {
-	my $tries = $res->tries();
-	my $maxtries = $res->maxtries();
-	my $triesString = "($tries of $maxtries tries used)";
-	if ($res->duedate()) {
-	    return "Due: $status " . timeToHumanString($res->duedate($part)) .
-		" $triesString";
-	} else {
-	    return "No due date $triesString";
-	}
+        my $tries = $res->tries();
+        my $maxtries = $res->maxtries();
+        my $triesString = "($tries of $maxtries tries used)";
+        if ($res->duedate()) {
+            return "Due: $status " . timeToHumanString($res->duedate($part)) .
+                " $triesString";
+        } else {
+            return "No due date $triesString";
+        }
     }
 }
 
@@ -1258,9 +1280,9 @@
     my ($time) = @_;
     # zero, '0' and blank are bad times
     if ($time) {
-	return localtime($time);
+        return localtime($time);
     } else {
-	return 'Never';
+        return 'Never';
     }
 }
 
@@ -1328,7 +1350,7 @@
     if (!(tie(%parmhash, 'GDBM_File', $self->{PARM_HASH_FILE},
               &GDBM_READER(), 0640)))
     {
-	untie $self->{PARM_HASH};
+        untie $self->{PARM_HASH};
         return undef;
     }
     $self->{PARM_HASH} = \%parmhash;
@@ -1481,7 +1503,7 @@
     if (!defined($self->{DISCUSSION_TIME})) { return 0; }
 
     return $self->{DISCUSSION_TIME}->{$symb} >
-	   $self->{LAST_CHECK};
+           $self->{LAST_CHECK};
 }
 
 # Private function: Does the given resource (as a symb string) have
@@ -1898,7 +1920,7 @@
         $self->{RECURSIVE_ITERATOR} =
           Apache::lonnavmaps::iterator->new ($self->{NAV_MAP}, $firstResource, 
                      $finishResource, $self->{FILTER}, $self->{ALREADY_SEEN},
-					     $self->{CONDITION});
+                                             $self->{CONDITION});
     }
 
     return $self->{HERE};
@@ -1971,6 +1993,7 @@
 
     # Store this new resource in the parent nav map's cache.
     $self->{NAV_MAP}->{RESOURCE_CACHE}->{$self->{ID}} = $self;
+    $self->{RESOURCE_ERROR} = 0;
 
     # A hash that can be used by two-pass algorithms to store data
     # about this resource in. Not used by the resource object
@@ -2271,8 +2294,12 @@
     my $self = shift;
     
     my $parts = $self->parts();
-    
-    if (scalar(@{$parts}) == 1) { return 1;}
+
+    if ($self->{RESOURCE_ERROR}) {
+        return 0;
+    }
+
+    if (scalar(@{$parts}) < 2) { return 1;}
 
     return scalar(@{$parts}) - 1;
 }
@@ -2286,12 +2313,19 @@
     $self->{PARTS} = [];
 
     # Retrieve part count
-    foreach (split(/\,/,&Apache::lonnet::metadata($self->src(), 
-                                                  'allpossiblekeys'))) {
+    my $metadata = &Apache::lonnet::metadata($self->src(), 'allpossiblekeys');
+    if (!$metadata) {
+        $self->{RESOURCE_ERROR} = 1;
+        $self->{PARTS} = [];
+        return;
+    }
+
+    foreach (split(/\,/,$metadata)) {
         if ($_ =~ /^parameter\_(.*)\_opendate$/) {
             push @{$self->{PARTS}}, $1;
         }
     }
+
     
     # Is this possible to do in one line? - Jeremy
     my @sortedParts = sort @{$self->{PARTS}};
@@ -2566,11 +2600,11 @@
         $next = $self->{NAV_MAP}->getById($next);
 
         # Don't remember it if we've already seen it or if
-	# the student doesn't have browse priviledges
-	my $browsePriv = &Apache::lonnet::allowed('bre', $self->src);
+        # the student doesn't have browse priviledges
+        my $browsePriv = &Apache::lonnet::allowed('bre', $self->src);
         if (!defined($alreadySeenHash) ||
             !defined($alreadySeenHash->{$next->{ID}}) ||
-	    ($browsePriv ne '2' && $browsePriv ne 'F')) {
+            ($browsePriv ne '2' && $browsePriv ne 'F')) {
                 push @branches, $next;
             }
     }

Index: loncom/html/adm/help/tex/Navmap_Host_Down.tex
+++ loncom/html/adm/help/tex/Navmap_Host_Down.tex
When you see a \emph{Host Down} error on your nav map, that means the
server that hosts that resource by default is currently not responding.
That means we can't find out anything about the problem from that server
right now.

LON-CAPA will try to display the correct status for the resource, but
if the problem had multiple parts, it will not succeed. However, your
information about the problem is not lost; if you completed it before, 
the system still knows it is completed. If you tried it before, the
system still know it is tried, and so on.

If this problem persists, please contact your instructor.

--bowersj21033763644--