--- loncom/interface/lonnavmaps.pm 2002/09/24 03:48:18 1.53 +++ loncom/interface/lonnavmaps.pm 2002/09/26 16:56:21 1.55 @@ -1,7 +1,7 @@ # The LearningOnline Network with CAPA # Navigate Maps Handler # -# $Id: lonnavmaps.pm,v 1.53 2002/09/24 03:48:18 bowersj2 Exp $ +# $Id: lonnavmaps.pm,v 1.55 2002/09/26 16:56:21 bowersj2 Exp $ # # Copyright Michigan State University Board of Trustees # @@ -827,22 +827,6 @@ sub new_handle { $ENV{"request.course.fn"}.".db", $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', - $res->NOTHING_SET => '' ); if (!defined($navmap)) { my $requrl = $r->uri; @@ -850,6 +834,31 @@ sub new_handle { return HTTP_NOT_ACCEPTABLE; } + # Check that it's defined + if (!($navmap->courseMapDefined())) { + $r->print('Coursemap undefined.' . + ''); + 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; # Figure out what we're not displaying foreach (split(/\,/, $ENV{"form.filter"})) { @@ -1045,15 +1054,17 @@ sub getDescription { return "Opens: " . timeToHumanString($res->opendate($part)); } if ($status == $res->OPEN) { - return "Due: " . timeToHumanString($res->duedate($part)); + 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) { - return "Answer: " . timeToHumanString($res->duedate($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 @@ -1087,7 +1098,7 @@ You must obtain resource objects through =over 4 -=item * B(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 if not. You must check for undef; errors will occur when you try to use the other methods otherwise. +=item * B(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 if not. You must check for undef; errors will occur when you try to use the other methods otherwise. =item * B(first, finish, filter, condition): See iterator documentation below. @@ -1105,6 +1116,7 @@ sub new { $self->{NAV_HASH_FILE} = shift; $self->{PARM_HASH_FILE} = shift; $self->{GENERATE_COURSE_USER_OPT} = shift; + $self->{GENERATE_EMAIL_DISCUSS_STATUS} = shift; # 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. @@ -1182,16 +1194,73 @@ sub new { $useropt{$userprefix.&Apache::lonnet::unescape($name)}= &Apache::lonnet::unescape($value); } - $self->{COURSE_OPT} = \%courseopt; - $self->{USER_OPT} = \%useropt; + $self->{COURSE_OPT} = \%courseopt; + $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); - + 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 { my $self = shift; my $iterator = Apache::lonnavmaps::iterator->new($self, shift, shift, @@ -2024,7 +2093,9 @@ B =item * B: Open and not yet due. -=item * B: The due date has passed, but the answer date has not yet arrived. +=item * B: The due date has passed, but the answer date has not yet arrived. + +=item * B: The due date has passed and there is no answer opening date set. =item * B: The answer date is here. @@ -2035,17 +2106,27 @@ B =cut # Apparently the compiler optimizes these into constants automatically -sub OPEN_LATER { return 0; } -sub OPEN { return 1; } -sub PAST_DUE { return 2; } -sub ANSWER_OPEN { return 3; } -sub NOTHING_SET { return 4; } -sub NETWORK_FAILURE { return 100; } +sub OPEN_LATER { return 0; } +sub OPEN { return 1; } +sub PAST_DUE_NO_ANSWER { return 2; } +sub PAST_DUE_ANSWER_LATER { return 3; } +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 { my $self = shift; my $part = shift; $part = "0" if (!defined($part)); + + # Always return network failure if there was one. return $self->NETWORK_FAILURE if ($self->{NAV_MAP}->{NETWORK_FAILURE}); my $now = time(); @@ -2054,15 +2135,16 @@ sub getDateStatus { my $due = $self->duedate($part); my $answer = $self->answerdate($part); - if ($open && $now < $open) {return $self->OPEN_LATER}; - if ($due && $now < $due) {return $self->OPEN}; - if ($answer && $now < $answer) {return $self->PAST_DUE}; if (!$open && !$due && !$answer) { # no data on the problem at all # should this be the same as "open later"? think multipart. return $self->NOTHING_SET; } - return $self->ANSWER_OPEN; + 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 @@ -2140,7 +2222,9 @@ Along with directly returning the date o =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. @@ -2167,7 +2251,7 @@ sub status { # 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, - # plus network failure and "no date data". + # plus network failure and "no date data at all". if ($completionStatus == NETWORK_FAILURE) { return NETWORK_FAILURE; } @@ -2189,8 +2273,9 @@ sub status { # Now we're down to a 3 (incorrect, incorrect_override, not_attempted) # by 4 matrix (date status). - if ($dateStatus == PAST_DUE) { - return PAST_DUE; + if ($dateStatus == PAST_DUE_ANSWER_LATER || + $dateStatus == PAST_DUE_NO_ANSWER) { + return $dateStatus; } if ($dateStatus == ANSWER_OPEN) {