Diff for /loncom/interface/lonnavmaps.pm between versions 1.51 and 1.55

version 1.51, 2002/09/24 01:18:50 version 1.55, 2002/09/26 16:56:21
Line 827  sub new_handle { Line 827  sub new_handle {
                         $ENV{"request.course.fn"}.".db",                          $ENV{"request.course.fn"}.".db",
                         $ENV{"request.course.fn"}."_parms.db", 1);                          $ENV{"request.course.fn"}."_parms.db", 1);
   
     # Grab a resource object so we have access to the constants; this  
     # is technically not proper, but should be harmless  
     my $res = $navmap->firstResource();  
   
     # Defines a status->color mapping, null string means don't color  
     my %colormap =   
     ( $res->NETWORK_FAILURE    => '',  
       $res->CORRECT            => '#BBFFBB',  
       $res->EXCUSED            => '#BBBBFF',  
       $res->PAST_DUE           => '#FFAA00',  
       $res->ANSWER_OPEN        => '#FF00AA',  
       $res->OPEN_LATER         => '',  
       $res->TRIES_LEFT         => '#FFFF00',  
       $res->INCORRECT          => '#FFAA00',  
       $res->OPEN               => '#FFFF88' );  
   
     if (!defined($navmap)) {      if (!defined($navmap)) {
         my $requrl = $r->uri;          my $requrl = $r->uri;
Line 849  sub new_handle { Line 834  sub new_handle {
         return HTTP_NOT_ACCEPTABLE;          return HTTP_NOT_ACCEPTABLE;
     }      }
   
       # Check that it's defined
       if (!($navmap->courseMapDefined())) {
           $r->print('<font size="+2" color="red">Coursemap undefined.</font>' .
                     '</body></html>');
           return OK;
       }
   
       # Grab a resource object so we have access to the constants; this
       # is technically not proper, but should be harmless
       my $res = $navmap->firstResource();
   
       # Defines a status->color mapping, null string means don't color
       my %colormap = 
       ( $res->NETWORK_FAILURE        => '',
         $res->CORRECT                => '#BBFFBB',
         $res->EXCUSED                => '#BBBBFF',
         $res->PAST_DUE_ANSWER_LATER  => '#FFAA00',
         $res->PAST_DUE_NO_ANSWER     => '#FFAA00',
         $res->ANSWER_OPEN            => '#FF00AA',
         $res->OPEN_LATER             => '',
         $res->TRIES_LEFT             => '#FFFF00',
         $res->INCORRECT              => '#FFAA00',
         $res->OPEN                   => '#FFFF88',
         $res->NOTHING_SET            => ''        );
   
     my %filterHash;      my %filterHash;
     # Figure out what we're not displaying      # Figure out what we're not displaying
     foreach (split(/\,/, $ENV{"form.filter"})) {      foreach (split(/\,/, $ENV{"form.filter"})) {
Line 863  sub new_handle { Line 873  sub new_handle {
   
     my $mapIterator = $navmap->getIterator(undef, undef, \%filterHash);      my $mapIterator = $navmap->getIterator(undef, undef, \%filterHash);
     my $curRes = $mapIterator->next();      my $curRes = $mapIterator->next();
       undef $res; # so we don't accidentally use it later
     my $indentLevel = -1;      my $indentLevel = -1;
     my $indentString = "&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;";      my $indentString = "&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;";
   
Line 870  sub new_handle { Line 881  sub new_handle {
   
     while ($curRes != $mapIterator->END_NAV_MAP) {      while ($curRes != $mapIterator->END_NAV_MAP) {
         if ($curRes == $mapIterator->BEGIN_MAP() ||          if ($curRes == $mapIterator->BEGIN_MAP() ||
     $curRes == $mapIterator->BEGIN_BRANCH()) {              $curRes == $mapIterator->BEGIN_BRANCH()) {
             $indentLevel++;              $indentLevel++;
         }          }
         if ($curRes == $mapIterator->END_MAP() ||          if ($curRes == $mapIterator->END_MAP() ||
     $curRes == $mapIterator->END_BRANCH()) {              $curRes == $mapIterator->END_BRANCH()) {
             $indentLevel--;              $indentLevel--;
         }          }
           if ($curRes == $mapIterator->BEGIN_BRANCH()) {
  if ($curRes == $mapIterator->BEGIN_BRANCH()) {              $isNewBranch = 1;
     $r->print("Begin branch<br/>");  
  }  
         if ($curRes == $mapIterator->END_BRANCH()) {  
             $r->print("End branch<br/>");  
         }          }
   
         if (ref($curRes) && $curRes->src()) {          if (ref($curRes) && $curRes->src()) {
Line 911  sub new_handle { Line 918  sub new_handle {
                     '"';                      '"';
                 my $title = $curRes->title();                  my $title = $curRes->title();
                 my $partLabel = "";                  my $partLabel = "";
                   my $newBranchText = "";
   
                   # If this is a new branch, label it so
                   # (temporary, this should be an icon w/ alt text)
                   if ($isNewBranch) {
                       $newBranchText = "NB -> ";
                       $isNewBranch = 0;
                   }
   
                 # links to open and close the folders                  # links to open and close the folders
                 my $linkopen = "<a href=\"$link\">";                  my $linkopen = "<a href=\"$link\">";
Line 927  sub new_handle { Line 942  sub new_handle {
                     my $nowOpen = !defined($filterHash{$mapId});                      my $nowOpen = !defined($filterHash{$mapId});
                     $icon = $nowOpen ?                      $icon = $nowOpen ?
                         "folder_opened.gif" : "folder_closed.gif";                          "folder_opened.gif" : "folder_closed.gif";
                     $linkopen = "<a href=\"/adm/navmaps?jtest=1&filter=";                      $linkopen = "<a href=\"/adm/navmaps?filter=";
                     $linkopen .= $nowOpen ?                       $linkopen .= $nowOpen ? 
                         addToFilter(\%filterHash, $mapId) :                          addToFilter(\%filterHash, $mapId) :
                         removeFromFilter(\%filterHash, $mapId);                          removeFromFilter(\%filterHash, $mapId);
Line 952  sub new_handle { Line 967  sub new_handle {
                     $r->print($indentString);                      $r->print($indentString);
                 }                  }
   
                 $r->print("  ${linkopen}<img border=\"0\" src=\"" .                  $r->print("  ${newBranchText}${linkopen}<img border=\"0\" src=\"" .
                           "/adm/lonIcons/$icon\" alt=\"\">${linkclose}\n");                            "/adm/lonIcons/$icon\" alt=\"\">${linkclose}\n");
   
                 if ($curRes->is_problem() && $part != "0") { $partLabel = " (Part $part)"; }                  if ($curRes->is_problem() && $part != "0") { $partLabel = " (Part $part)"; }
Line 962  sub new_handle { Line 977  sub new_handle {
                                   
                 if ($curRes->kind() eq "res" and                   if ($curRes->kind() eq "res" and 
                     $curRes->is_problem() ) {                      $curRes->is_problem() ) {
                     $r->print (" Due: " . localtime($curRes->duedate()));                      $r->print (getDescription($curRes, $part));
                 }                  }
             }              }
         }          }
Line 1020  sub getLinkForResource { Line 1035  sub getLinkForResource {
     return $res->src();      return $res->src();
 }  }
   
   # Convenience function: This seperates the logic of how to create
   # the problem text strings ("Due: DATE", "Open: DATE", "Not yet assigned",
   # etc.) into a seperate function. It takes a resource object as the
   # first parameter, and the part number of the resource as the second.
   # It's basically a big switch statement on the status of the resource.
   
   sub getDescription {
       my $res = shift;
       my $part = shift;
       my $status = $res->getDateStatus();
   
       if ($status == $res->NETWORK_FAILURE) { return ""; }
       if ($status == $res->NOTHING_SET) {
           return "Not currently assigned.";
       }
       if ($status == $res->OPEN_LATER) {
           return "Opens: " . timeToHumanString($res->opendate($part));
       }
       if ($status == $res->OPEN) {
           return "Due: $status " . timeToHumanString($res->duedate($part));
       }
       if ($status == $res->PAST_DUE_ANSWER_LATER) {
           return "Answer: " . timeToHumanString($res->answerdate($part));
       }
       if ($status == $res->PAST_DUE_NO_ANSWER) {
           return "Was Due: " . timeToHumanString($res->duedate($part));
       }
       if ($status == $res->ANSWER_OPEN) {
           return "Answer available";
       }
   }
   
   # I want to change this into something more human-friendly. For
   # now, this is a simple call to localtime. The final function
   # probably belongs in loncommon.
   sub timeToHumanString {
       return localtime(shift);
   }
   
 1;  1;
   
 package Apache::lonnavmaps::navmap;  package Apache::lonnavmaps::navmap;
Line 1044  You must obtain resource objects through Line 1098  You must obtain resource objects through
   
 =over 4  =over 4
   
 =item * B<new>(filename, parmHashFile, genCourseAndUserOptions): Binds a new navmap object to the compiled course representation and parmHashFile. genCourseAndUserOptions is a flag saying whether the course options and user options hash should be generated. This is for when you are using the parameters of the resources that require them; see documentation in resource object documentation. Returns the navmap object if this is successful, or B<undef> if not. You must check for undef; errors will occur when you try to use the other methods otherwise.  =item * B<new>(filename, parmHashFile, genCourseAndUserOptions, genMailDiscussStatus): Binds a new navmap object to the compiled course representation and parmHashFile. genCourseAndUserOptions is a flag saying whether the course options and user options hash should be generated. This is for when you are using the parameters of the resources that require them; see documentation in resource object documentation. genMailDiscussStatus causes the nav map to retreive information about the email and discussion status of resources. Returns the navmap object if this is successful, or B<undef> if not. You must check for undef; errors will occur when you try to use the other methods otherwise.
   
 =item * B<getIterator>(first, finish, filter, condition): See iterator documentation below.  =item * B<getIterator>(first, finish, filter, condition): See iterator documentation below.
   
Line 1062  sub new { Line 1116  sub new {
     $self->{NAV_HASH_FILE} = shift;      $self->{NAV_HASH_FILE} = shift;
     $self->{PARM_HASH_FILE} = shift;      $self->{PARM_HASH_FILE} = shift;
     $self->{GENERATE_COURSE_USER_OPT} = shift;      $self->{GENERATE_COURSE_USER_OPT} = shift;
       $self->{GENERATE_EMAIL_DISCUSS_STATUS} = shift;
   
     # Resource cache stores navmapresource's as we reference them. We generate      # Resource cache stores navmapresource's as we reference them. We generate
     # them on-demand so we don't pay for creating resources unless we use them.      # them on-demand so we don't pay for creating resources unless we use them.
Line 1139  sub new { Line 1194  sub new {
                 $useropt{$userprefix.&Apache::lonnet::unescape($name)}=                  $useropt{$userprefix.&Apache::lonnet::unescape($name)}=
                     &Apache::lonnet::unescape($value);                      &Apache::lonnet::unescape($value);
             }              }
         $self->{COURSE_OPT} = \%courseopt;              $self->{COURSE_OPT} = \%courseopt;
         $self->{USER_OPT} = \%useropt;              $self->{USER_OPT} = \%useropt;
         }          }
     }         }   
   
       if ($self->{GENERATE_EMAIL_DISCUSS_STATUS}) {
           my $cid=$ENV{'request.course.id'};
           my ($cdom,$cnum)=split(/\_/,$cid);
           
           my %emailstatus = &Apache::lonnet::dump('email_status');
           my logoutTime = $emailstatus{'logout'};
           my courseLeaveTime = $emailstatus{'logout_'.$ENV{'request.course.id'}};
           $self->{LAST_CHECK} = ($courseLeaveTime > $logoutTime ?
                                  $courseLeaveTime : $logoutTime);
           my %discussiontime = &Apache::lonnet::dump{'discussiontimes', 
                                                      $cdom, $cnum);
           my %feedback=();
           my %error=();
           my $keys = &Apache::lonnet::reply('keys:'.
                                             $ENV{'user.domain'}.':'.
                                             $ENV{'user.name'}.':nohist_email',
                                             $ENV{'user.home'});
   
           foreach my $msgid (split(/\&/, $keys)) {
               $msgid=&Apache::lonnet::unescape($msgid);
               my $plain=&Apache::lonnet::unescape(&Apache::lonnet::unescape($msgid));
               if ($plain=~/(Error|Feedback) \[([^\]]+)\]/) {
                   my ($what,$url)=($1,$2);
                   my %status=
                       &Apache::lonnet::get('email_status',[$msgid]);
                   if ($status{$msgid}=~/^error\:/) { 
                       $status{$msgid}=''; 
                   }
                   
                   if (($status{$msgid} eq 'new') || 
                       (!$status{$msgid})) { 
                       if ($what eq 'Error') {
                           $error{$url}.=','.$msgid; 
                       } else {
                           $feedback{$url}.=','.$msgid;
                       }
                   }
               }
           }
           
           $self->{FEEDBACK} = \%feedback;
           $self->{ERROR_MSG} = \%error; # what is this? JB
           $self->{DISCUSSION_TIME} = \%discussiontime;
           $self->{EMAIL_STATUS} = \%emailstatus;
           
       }    
       
     bless($self);      bless($self);
           
     return $self;      return $self;
 }  }
   
   # Checks to see if coursemap is defined, matching test in old lonnavmaps
   sub courseMapDefined {
       my $self = shift;
       my $uri = &Apache::lonnet::clutter($ENV{'request.course.uri'});
   
       my $firstres = $self->{NAV_HASH}->{'map_start_$uri'};
       my $lastres = $self->{NAV_HASH}->{'map_finish_$uri'};
       return $firstres && $lastres;
   }
   
 sub getIterator {  sub getIterator {
     my $self = shift;      my $self = shift;
     my $iterator = Apache::lonnavmaps::iterator->new($self, shift, shift,      my $iterator = Apache::lonnavmaps::iterator->new($self, shift, shift,
Line 1460  sub next { Line 1572  sub next {
     if (scalar(@{$self->{BRANCH_STACK}}) == 0) {      if (scalar(@{$self->{BRANCH_STACK}}) == 0) {
         if ($self->{BRANCH_DEPTH} > 0) {          if ($self->{BRANCH_DEPTH} > 0) {
             $self->{FORCE_NEXT} = $self->END_MAP();              $self->{FORCE_NEXT} = $self->END_MAP();
     $self->{BRANCH_DEPTH}--;              $self->{BRANCH_DEPTH}--;
             return $self->END_BRANCH();              return $self->END_BRANCH();
         } else {          } else {
             return $self->END_MAP();              return $self->END_MAP();
Line 1479  sub next { Line 1591  sub next {
     # to start a new one. (We know because we already checked to see      # to start a new one. (We know because we already checked to see
     # if the stack was empty.)      # if the stack was empty.)
     if ( scalar (@{$self->{BRANCH_STACK}}) < $self->{BRANCH_STACK_SIZE}) {      if ( scalar (@{$self->{BRANCH_STACK}}) < $self->{BRANCH_STACK_SIZE}) {
  $self->{BRANCH_STACK_SIZE} = scalar(@{$self->{BRANCH_STACK}});          $self->{BRANCH_STACK_SIZE} = scalar(@{$self->{BRANCH_STACK}});
  $self->{BRANCH_DEPTH}++;          $self->{BRANCH_DEPTH}++;
  return $self->BEGIN_BRANCH();          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      # Get the next resource in the branch
     $self->{HERE} = pop @{$self->{BRANCH_STACK}};      $self->{HERE} = pop @{$self->{BRANCH_STACK}};
   
       # Are we at the right depth? If not, close a branch and return
       # the current resource onto the branch stack
       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      # We always return it after this point and never before
     # (proof: look at just the return statements), so we      # (proof: look at just the return statements), so we
     # remember that we've seen this.      # remember that we've seen this.
Line 1493  sub next { Line 1624  sub next {
           
     # Are we at the utter end? If so, return the END_NAV_MAP marker.      # Are we at the utter end? If so, return the END_NAV_MAP marker.
     if ($self->{HERE} == $self->{NAV_MAP}->finishResource() ) {      if ($self->{HERE} == $self->{NAV_MAP}->finishResource() ) {
  $self->{FORCE_NEXT} = $self->END_NAV_MAP;          $self->{FORCE_NEXT} = $self->END_NAV_MAP;
         return $self->{HERE};          return $self->{HERE};
     }      }
           
     # Remember the size for comparision next time.  
     $self->{BRANCH_STACK_SIZE} = scalar(@{$self->{BRANCH_STACK}});  
   
     # Get the next possible resources      # Get the next possible resources
     my $nextUnfiltered = $self->{HERE}->getNext();      my $nextUnfiltered = $self->{HERE}->getNext();
     my $next = [];      my $next = [];
   
     # filter the next possibilities to remove things we've       # filter the next possibilities to remove things we've 
     # already seen      # already seen. Also, remember what branch depth they should
       # be displayed at, since there's no other reliable way to tell.
     foreach (@$nextUnfiltered) {      foreach (@$nextUnfiltered) {
  if (!defined($self->{ALREADY_SEEN}->{$_->{ID}})) {          if (!defined($self->{ALREADY_SEEN}->{$_->{ID}})) {
     push @$next, $_;              push @$next, $_;
  }              $_->{DATA}->{ITERATOR_DEPTH} = 
                   $self->{BRANCH_DEPTH} + 1;
           }
     }      }
   
     # Handle branch cases:      # Handle branch cases:
Line 1518  sub next { Line 1649  sub next {
     # 2+ things next: have some branches      # 2+ things next: have some branches
     my $nextCount = scalar(@$next);      my $nextCount = scalar(@$next);
     if ($nextCount == 0) {      if ($nextCount == 0) {
  # Return this and on the next run, close the branch up if we're           # Return this and on the next run, close the branch up if we're 
  # in a branch          # in a branch
  if ($self->{BRANCH_DEPTH} > 0 ) {          if ($self->{BRANCH_DEPTH} > 0 ) {
     $self->{FORCE_NEXT} = $self->END_BRANCH();              $self->{FORCE_NEXT} = $self->END_BRANCH();
     $self->{BRANCH_DEPTH}--;              $self->{BRANCH_DEPTH}--;
  }          }
         return $self->{HERE};          return $self->{HERE};
     }      }
           
     while (@$next) {      while (@$next) {
         # copy the next possibilities over to the branch stack          # copy the next possibilities over to the branch stack
         # in the right order          # in the right order
  push @{$self->{BRANCH_STACK}}, shift @$next;          push @{$self->{BRANCH_STACK}}, shift @$next;
     }      }
   
     if ($nextCount >= 2) {      if ($nextCount >= 2) {
  $self->{FORCE_NEXT} = $self->BEGIN_BRANCH();          $self->{FORCE_NEXT} = $self->BEGIN_BRANCH();
  $self->{BRANCH_DEPTH}++;          $self->{BRANCH_DEPTH}++;
         return $self->{HERE};           return $self->{HERE}; 
     }      }
   
Line 1552  sub next { Line 1683  sub next {
         $self->{RECURSIVE_ITERATOR} =          $self->{RECURSIVE_ITERATOR} =
           Apache::lonnavmaps::iterator->new ($self->{NAV_MAP}, $firstResource,             Apache::lonnavmaps::iterator->new ($self->{NAV_MAP}, $firstResource, 
                      $finishResource, $self->{FILTER}, $self->{ALREADY_SEEN});                       $finishResource, $self->{FILTER}, $self->{ALREADY_SEEN});
  # prime the new iterator with the first resource          # prime the new iterator with the first resource
  #push @{$self->{RECURSIVE_ITERATOR}->{BRANCH_STACK}}, $firstResource;          #push @{$self->{RECURSIVE_ITERATOR}->{BRANCH_STACK}}, $firstResource;
     }      }
   
     return $self->{HERE};      return $self->{HERE};
Line 1962  B<Date Codes> Line 2093  B<Date Codes>
   
 =item * B<OPEN>: Open and not yet due.  =item * B<OPEN>: Open and not yet due.
   
 =item * B<PAST_DUE>: The due date has passed, but the answer date has not yet arrived.  =item * B<PAST_DUE_ANSWER_LATER>: The due date has passed, but the answer date has not yet arrived.
   
   =item * B<PAST_DUE_NO_ANSWER>: The due date has passed and there is no answer opening date set.
   
 =item * B<ANSWER_OPEN>: The answer date is here.  =item * B<ANSWER_OPEN>: The answer date is here.
   
Line 1973  B<Date Codes> Line 2106  B<Date Codes>
 =cut  =cut
   
 # Apparently the compiler optimizes these into constants automatically  # Apparently the compiler optimizes these into constants automatically
 sub OPEN_LATER      { return 0; }  sub OPEN_LATER             { return 0; }
 sub OPEN            { return 1; }  sub OPEN                   { return 1; }
 sub PAST_DUE        { return 2; }  sub PAST_DUE_NO_ANSWER     { return 2; }
 sub ANSWER_OPEN     { return 3; }  sub PAST_DUE_ANSWER_LATER  { return 3; }
 sub NETWORK_FAILURE { return 100; }  sub ANSWER_OPEN            { return 4; }
   sub NOTHING_SET            { return 5; } 
   sub NETWORK_FAILURE        { return 100; }
   
   # getDateStatus gets the date status for a given problem part. 
   # Because answer date, due date, and open date are fully independent
   # (i.e., it is perfectly possible to *only* have an answer date), 
   # we have to completely cover the 3x3 maxtrix of (answer, due, open) x
   # (past, future, none given). This function handles this with a decision
   # tree. Read the comments to follow the decision tree.
   
 sub getDateStatus {  sub getDateStatus {
     my $self = shift;      my $self = shift;
     my $part = shift;      my $part = shift;
     $part = "0" if (!defined($part));      $part = "0" if (!defined($part));
   
       # Always return network failure if there was one.
     return $self->NETWORK_FAILURE if ($self->{NAV_MAP}->{NETWORK_FAILURE});      return $self->NETWORK_FAILURE if ($self->{NAV_MAP}->{NETWORK_FAILURE});
   
     my $now = time();      my $now = time();
   
     my $o = $now - $self->opendate($part);      my $open = $self->opendate($part);
     my $d = $now - $self->duedate($part);      my $due = $self->duedate($part);
     my $a = $now - $self->answerdate($part);      my $answer = $self->answerdate($part);
   
     if ($o < 0) {return $self->OPEN_LATER};      if (!$open && !$due && !$answer) {
     if ($d < 0) {return $self->OPEN};          # no data on the problem at all
     if ($a < 0) {return $self->PAST_DUE};          # should this be the same as "open later"? think multipart.
     return $self->ANSWER_OPEN;          return $self->NOTHING_SET;
       }
       if (!$open || $now < $open) {return $self->OPEN_LATER};
       if (!$due || $now < $due) {return $self->OPEN};
       if ($answer && $now < $answer) {return $self->PAST_DUE_ANSWER_LATER};
       if ($answer) { return $self->ANSWER_OPEN; };
       return PAST_DUE_NO_ANSWER;
 }  }
   
 =pod  =pod
Line 2029  B<Completion Codes> Line 2179  B<Completion Codes>
   
 =cut  =cut
   
 sub NOT_ATTEMPTED         { return 0; }  sub NOT_ATTEMPTED         { return 10; }
 sub INCORRECT             { return 1; }  sub INCORRECT             { return 11; }
 sub INCORRECT_BY_OVERRIDE { return 2; }  sub INCORRECT_BY_OVERRIDE { return 12; }
 sub CORRECT               { return 3; }  sub CORRECT               { return 13; }
 sub CORRECT_BY_OVERRIDE   { return 4; }  sub CORRECT_BY_OVERRIDE   { return 14; }
 sub EXCUSED               { return 5; }  sub EXCUSED               { return 15; }
   
 sub getCompletionStatus {  sub getCompletionStatus {
     my $self = shift;      my $self = shift;
Line 2066  Along with directly returning the date o Line 2216  Along with directly returning the date o
   
 =item * NETWORK_FAILURE: The network has failed and the information is not available.  =item * NETWORK_FAILURE: The network has failed and the information is not available.
   
   =item * NOTHING_SET: No dates have been set for this problem (part) at all. (Because only certain parts of a multi-part problem may be assigned, this can not be collapsed into "open later", as we don't know a given part will EVER be opened.)
   
 =item * CORRECT: For any reason at all, the part is considered correct.  =item * CORRECT: For any reason at all, the part is considered correct.
   
 =item * EXCUSED: For any reason at all, the problem is excused.  =item * EXCUSED: For any reason at all, the problem is excused.
   
 =item * PAST_DUE: The problem is past due, and not considered correct.  =item * PAST_DUE_NO_ANSWER: The problem is past due, not considered correct, and no answer date is set.
   
   =item * PAST_DUE_ANSWER_LATER: The problem is past due, not considered correct, and an answer date in the future is set.
   
 =item * ANSWER_OPEN: The problem is past due, not correct, and the answer is now available.  =item * ANSWER_OPEN: The problem is past due, not correct, and the answer is now available.
   
Line 2097  sub status { Line 2251  sub status {
   
     # What we have is a two-dimensional matrix with 4 entries on one      # What we have is a two-dimensional matrix with 4 entries on one
     # dimension and 5 entries on the other, which we want to colorize,      # dimension and 5 entries on the other, which we want to colorize,
     # plus network failure.      # plus network failure and "no date data at all".
   
     # Don't colorize on network failure.      if ($completionStatus == NETWORK_FAILURE) { return NETWORK_FAILURE; }
     if ($completionStatus == NETWORK_FAILURE()) { return $self->NETWORK_FAILURE(); }  
   
     # There are a few whole rows we can dispose of:      # There are a few whole rows we can dispose of:
     # If the problem is CORRECT, color it green no matter what      if ($completionStatus == CORRECT ||
     if ($completionStatus == CORRECT() ||          $completionStatus == CORRECT_BY_OVERRIDE ) {
         $completionStatus == CORRECT_BY_OVERRIDE() ) {          return CORRECT(); 
         return $self->CORRECT(); # Return a nice green.      }
   
       # If it's EXCUSED, then return that no matter what
       if ($completionStatus == EXCUSED) {
           return EXCUSED; 
     }      }
   
     # If it's EXCUSED, then return something no matter what      if ($dateStatus == NOTHING_SET) {
     if ($completionStatus == EXCUSED()) {          return NOTHING_SET;
         return $self->EXCUSED(); # return a nice blue  
     }      }
   
     # Now we're down to a 3 (incorrect, incorrect_override, not_attempted)      # Now we're down to a 3 (incorrect, incorrect_override, not_attempted)
     # by 4 matrix (date status).      # by 4 matrix (date status).
   
     # If it's Past Due and we didn't bail earlier because it's correct,      if ($dateStatus == PAST_DUE_ANSWER_LATER ||
     # color it orange. (Red is sort inappropriate; too drastic a color          $dateStatus == PAST_DUE_NO_ANSWER) {
     # for something the student can't fix.          return $dateStatus; 
     if ($dateStatus == PAST_DUE()) {  
         return $self->PAST_DUE(); # return orange  
     }      }
   
     if ($dateStatus == ANSWER_OPEN()) {      if ($dateStatus == ANSWER_OPEN) {
         return $self->ANSWER_OPEN();          return ANSWER_OPEN;
     }      }
   
     # Now: (incorrect, incorrect_override, not_attempted) x       # Now: (incorrect, incorrect_override, not_attempted) x 
     # (open_later), (open)      # (open_later), (open)
           
     # If it's open later, then don't colorize      if ($dateStatus == OPEN_LATER) {
     if ($dateStatus == OPEN_LATER()) {          return OPEN_LATER;
         return $self->OPEN_LATER();  
     }      }
   
     # 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() < $self->maxtries()) {
             return $self->TRIES_LEFT(); # return red: The student can fix this              return TRIES_LEFT;
         }          }
         return $self->INCORRECT(); # otherwise, return orange; student can't fix this          return INCORRECT; # otherwise, return orange; student can't fix this
     }      }
   
     # Otherwise, it's untried and open      # Otherwise, it's untried and open
     return $self->OPEN(); # Light yellow      return OPEN; 
 }  }
   
 =pod  =pod

Removed from v.1.51  
changed lines
  Added in v.1.55


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