--- loncom/interface/lonnavmaps.pm 2003/10/09 21:02:11 1.239
+++ loncom/interface/lonnavmaps.pm 2004/10/07 19:55:52 1.267.2.8
@@ -1,7 +1,7 @@
# The LearningOnline Network with CAPA
# Navigate Maps Handler
#
-# $Id: lonnavmaps.pm,v 1.239 2003/10/09 21:02:11 bowersj2 Exp $
+# $Id: lonnavmaps.pm,v 1.267.2.8 2004/10/07 19:55:52 albertel Exp $
#
# Copyright Michigan State University Board of Trustees
#
@@ -25,20 +25,7 @@
#
# http://www.lon-capa.org/
#
-# (Page Handler
-#
-# (TeX Content Handler
-#
-# 05/29/00,05/30 Gerd Kortemeyer)
-# 08/30,08/31,09/06,09/14,09/15,09/16,09/19,09/20,09/21,09/23,
-# 10/02,10/10,10/14,10/16,10/18,10/19,10/31,11/6,11/14,11/16 Gerd Kortemeyer)
-#
-# 3/1/1,6/1,17/1,29/1,30/1,2/8,9/21,9/24,9/25 Gerd Kortemeyer
-# YEAR=2002
-# 1/1 Gerd Kortemeyer
-# Oct-Nov Jeremy Bowers
-# YEAR=2003
-# Jeremy Bowers ... lots of days
+###
package Apache::lonnavmaps;
@@ -150,8 +137,9 @@ sub real_handler {
$r->print(''.
&Apache::loncommon::bodytag('Navigate Course Contents','',
$addentries,'','',$ENV{'form.register'}));
- $r->print('');
-
+ $r->print(''.
+ &Apache::loncommon::help_open_menu('','Navigation Screen','Navigation_Screen','',undef,'RAT'));
+
$r->rflush();
# Check that it's defined
@@ -303,8 +291,16 @@ sub getLinkForResource {
# Check to see if there are any pages in the stack
foreach $res (@$stack) {
- if (defined($res) && $res->is_page()) {
- return $res->src();
+ if (defined($res)) {
+ if ($res->is_page()) {
+ return $res->src();
+ }
+ # in case folder was skipped over as "only sequence"
+ my ($map,$id,$src)=&Apache::lonnet::decode_symb($res->symb());
+ if ($map=~/\.page$/) {
+ return &Apache::lonnet::clutter($map).'#'.
+ &Apache::lonnet::escape(&Apache::lonnet::declutter($src));
+ }
}
}
@@ -319,9 +315,9 @@ sub getLinkForResource {
return $res->src();
}
-# Convenience function: This seperates the logic of how to create
+# Convenience function: This separates 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
+# etc.) into a separate 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.
@@ -371,7 +367,7 @@ sub getDescription {
$triesString = "$triesString";
}
}
- if ($res->duedate()) {
+ if ($res->duedate($part)) {
return &mt("Due")." " . timeToHumanString($res->duedate($part)) .
" $triesString";
} else {
@@ -386,15 +382,15 @@ sub getDescription {
# Convenience function, so others can use it: Is the problem due in less then
# 24 hours, and still can be done?
-sub dueInLessThen24Hours {
+sub dueInLessThan24Hours {
my $res = shift;
my $part = shift;
my $status = $res->status($part);
return ($status == $res->OPEN() ||
$status == $res->TRIES_LEFT()) &&
- $res->duedate() && $res->duedate() < time()+(24*60*60) &&
- $res->duedate() > time();
+ $res->duedate($part) && $res->duedate($part) < time()+(24*60*60) &&
+ $res->duedate($part) > time();
}
# Convenience function, so others can use it: Is there only one try remaining for the
@@ -406,8 +402,8 @@ sub lastTry {
my $tries = $res->tries($part);
my $maxtries = $res->maxtries($part);
return $tries && $maxtries && $maxtries > 1 &&
- $maxtries - $tries == 1 && $res->duedate() &&
- $res->duedate() > time();
+ $maxtries - $tries == 1 && $res->duedate($part) &&
+ $res->duedate($part) > time();
}
# This puts a human-readable name on the ENV variable.
@@ -517,7 +513,7 @@ sub timeToHumanString {
}
# Not this year, so show the year
- my $timeStr = strftime("on %A, %b %e %G at %I:%M %P", localtime($time));
+ my $timeStr = strftime("on %A, %b %e %Y at %I:%M %P", localtime($time));
$timeStr =~ s/12:00 am/00:00/;
$timeStr =~ s/12:00 pm/noon/;
return $timeStr;
@@ -869,10 +865,7 @@ sub render_resource {
my $filter = $it->{FILTER};
my $title = $resource->compTitle();
- if ($src =~ /^\/uploaded\//) {
- $nonLinkedText=$title;
- $title = '';
- }
+
my $partLabel = "";
my $newBranchText = "";
@@ -895,12 +888,8 @@ sub render_resource {
$icon = $params->{'indentString'};
}
} else {
- my $curfext= (split (/\./,$resource->src))[-1];
- my $embstyle = &Apache::loncommon::fileembstyle($curfext);
- # The unless conditional that follows is a bit of overkill
- if (!(!defined($embstyle) || $embstyle eq 'unk' || $embstyle eq 'hdn')) {
- $icon = "";
- }
+ $icon = "";
}
# Display the correct map icon to open or shut map
@@ -970,7 +959,11 @@ sub render_resource {
if ($resource->is_problem() && $part ne '0' &&
!$params->{'condensed'}) {
- $partLabel = " (Part $part)";
+ my $displaypart=&Apache::lonnet::EXT('resource.'.$part.'.display',
+ $resource->symb());
+ unless ($displaypart) { $displaypart=$part; }
+ $partLabel = " (Part: $displaypart)";
+ $link.='#'.&Apache::lonnet::escape($part);
$title = "";
}
@@ -978,8 +971,7 @@ sub render_resource {
$nonLinkedText .= ' (' . $resource->countParts() . ' parts)';
}
- if (!$params->{'resource_nolink'} && $src !~ /^\/uploaded\// &&
- !$resource->is_sequence()) {
+ if (!$params->{'resource_nolink'} && !$resource->is_sequence() && !$resource->is_empty_sequence) {
$result .= " $curMarkerBegin$title$partLabel$curMarkerEnd $nonLinkedText";
} else {
$result .= " $curMarkerBegin$title$partLabel$curMarkerEnd $nonLinkedText";
@@ -1016,8 +1008,11 @@ sub render_communication_status {
if ($resource->getErrors()) {
my $errors = $resource->getErrors();
+ my $errorcount = 0;
foreach (split(/,/, $errors)) {
+ last if ($errorcount>=10); # Only output 10 bombs maximum
if ($_) {
+ $errorcount++;
$errorHTML .= ' '
. 'is_problem()) {
$color = $colormap{$resource->status};
- if (dueInLessThen24Hours($resource, $part) ||
+ if (dueInLessThan24Hours($resource, $part) ||
lastTry($resource, $part)) {
$color = $hurryUpColor;
}
@@ -1121,35 +1116,53 @@ my @statuses = ($resObj->CORRECT, $resOb
use Data::Dumper;
sub render_parts_summary_status {
my ($resource, $part, $params) = @_;
- if (!$resource->is_problem()) { return '
| '; }
+ if (!$resource->is_problem() && !$resource->contains_problem) { return ' | '; }
if ($params->{showParts}) {
return ' | ';
}
my $td = "\n";
my $endtd = " | \n";
+ my @probs;
- # If there is a single part, just show the simple status
- if ($resource->singlepart()) {
- my $status = $resource->simpleStatus('0');
- return $td . ""
- . $statusStrings{$status} . "" . $endtd;
- }
-
- # Now we can be sure the $part doesn't really matter.
- my $statusCount = $resource->simpleStatusCount();
- my @counts;
- foreach my $status(@statuses) {
- # decouple display order from the simpleStatusCount order
- my $slot = Apache::lonnavmaps::resource::statusToSlot($status);
- if ($statusCount->[$slot]) {
- push @counts, "" . $statusCount->[$slot] . ' '
+ if ($resource->contains_problem) {
+ @probs=$resource->retrieveResources($resource,sub { $_[0]->is_problem() },1,0);
+ } else {
+ @probs=($resource);
+ }
+ my $return;
+ my %overallstatus;
+ my $totalParts;
+ foreach my $resource (@probs) {
+ # If there is a single part, just show the simple status
+ if ($resource->singlepart()) {
+ my $status = $resource->simpleStatus(${$resource->parts}[0]);
+ $overallstatus{$status}++;
+ $totalParts++;
+ next;
+ }
+ # Now we can be sure the $part doesn't really matter.
+ my $statusCount = $resource->simpleStatusCount();
+ my @counts;
+ foreach my $status (@statuses) {
+ # decouple display order from the simpleStatusCount order
+ my $slot = Apache::lonnavmaps::resource::statusToSlot($status);
+ if ($statusCount->[$slot]) {
+ $overallstatus{$status}+=$statusCount->[$slot];
+ $totalParts+=$statusCount->[$slot];
+ }
+ }
+ }
+ $return.= $td . $totalParts . ' parts: ';
+ foreach my $status (@statuses) {
+ if ($overallstatus{$status}) {
+ $return.="" . $overallstatus{$status} . ' '
. $statusStrings{$status} . "";
}
}
-
- return $td . $resource->countParts() . ' parts: ' . join (', ', @counts) . $endtd;
+ $return.= $endtd;
+ return $return;
}
my @preparedColumns = (\&render_resource, \&render_communication_status,
@@ -1184,6 +1197,7 @@ sub render {
my $jump = $args->{'jump'};
my $here = $args->{'here'};
my $suppressNavmap = setDefault($args->{'suppressNavmap'}, 0);
+ my $closeAllPages = setDefault($args->{'closeAllPages'}, 0);
my $currentJumpDelta = 2; # change this to change how many resources are displayed
# before the current resource when using #current
@@ -1246,7 +1260,7 @@ sub render {
# We only need to do this if we need to open the maps to show the
# current position. This will change the counter so we can't count
# for the jump marker with this loop.
- while (($curRes = $mapIterator->next()) && !$found) {
+ while ($here && ($curRes = $mapIterator->next()) && !$found) {
if (ref($curRes) && $curRes->symb() eq $here) {
my $mapStack = $mapIterator->getStack();
@@ -1292,7 +1306,7 @@ sub render {
$args->{'iterator'} = $it = $navmap->getIterator(undef, undef, $filterHash, $condition);
}
}
-
+
# (re-)Locate the jump point, if any
# Note this does not take filtering or hidden into account... need
# to be fixed?
@@ -1355,9 +1369,22 @@ sub render {
"&here=" . Apache::lonnet::escape($here) .
"\">".&mt('Open All Folders')."";
}
- $result .= "
\n";
- }
+ $result .= "\n";
+ }
+ # Check for any unread discussions in all resources.
+ if (!$args->{'resource_no_folder_link'}) {
+ my $time=time;
+ my $mapr = &mt('Mark all posts read');
+ $result .= (<$mapr
+
+END
+ }
+ $result .= "
\n";
if ($r) {
$r->print($result);
$r->rflush();
@@ -1429,7 +1456,7 @@ sub render {
$args->{'here'} = $here;
$args->{'indentLevel'} = -1; # first BEGIN_MAP takes this to 0
- while ($curRes = $it->next()) {
+ while ($curRes = $it->next($closeAllPages)) {
# Maintain indentation level.
if ($curRes == $it->BEGIN_MAP() ||
$curRes == $it->BEGIN_BRANCH() ) {
@@ -1545,11 +1572,15 @@ sub render {
my $filter = $it->{FILTER};
my $stack = $it->getStack();
my $src = getLinkForResource($stack);
-
+ my $anchor='';
+ if ($src=~s/(\#.*$)//) {
+ $anchor=$1;
+ }
my $srcHasQuestion = $src =~ /\?/;
$args->{"resourceLink"} = $src.
($srcHasQuestion?'&':'?') .
- 'symb=' . &Apache::lonnet::escape($curRes->symb());
+ 'symb=' . &Apache::lonnet::escape($curRes->symb()).
+ $anchor;
# Now, display each column.
foreach my $col (@$cols) {
@@ -1600,7 +1631,12 @@ sub render {
# it's quite likely this might fix other browsers, too, and
# certainly won't hurt anything.
if ($displayedJumpMarker) {
- $result .= "\n";
+ $result .= "
+";
}
$result .= "";
@@ -1791,6 +1827,7 @@ sub generate_course_user_opt {
sub generate_email_discuss_status {
my $self = shift;
+ my $symb = shift;
if ($self->{EMAIL_DISCUSS_GENERATED}) { return; }
my $cid=$ENV{'request.course.id'};
@@ -1803,6 +1840,15 @@ sub generate_email_discuss_status {
$courseLeaveTime : $logoutTime);
my %discussiontime = &Apache::lonnet::dump('discussiontimes',
$cdom, $cnum);
+ my %lastread = &Apache::lonnet::dump('nohist_'.$cid.'_discuss',
+ $ENV{'user.domain'},$ENV{'user.name'},'lastread');
+ my %lastreadtime = ();
+ foreach (keys %lastread) {
+ my $key = $_;
+ $key =~ s/_lastread$//;
+ $lastreadtime{$key} = $lastread{$_};
+ }
+
my %feedback=();
my %error=();
my $keys = &Apache::lonnet::reply('keys:'.
@@ -1812,17 +1858,11 @@ sub generate_email_discuss_status {
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 ((!$emailstatus{$msgid}) || ($emailstatus{$msgid} eq 'new')) {
+ my $plain=
+ &Apache::lonnet::unescape(&Apache::lonnet::unescape($msgid));
+ if ($plain=~/(Error|Feedback) \[([^\]]+)\]/) {
+ my ($what,$url)=($1,$2);
if ($what eq 'Error') {
$error{$url}.=','.$msgid;
} else {
@@ -1832,10 +1872,13 @@ sub generate_email_discuss_status {
}
}
+ #url's of resources that have feedbacks
$self->{FEEDBACK} = \%feedback;
- $self->{ERROR_MSG} = \%error; # what is this? JB
+ #or errors
+ $self->{ERROR_MSG} = \%error;
$self->{DISCUSSION_TIME} = \%discussiontime;
$self->{EMAIL_STATUS} = \%emailstatus;
+ $self->{LAST_READ} = \%lastreadtime;
$self->{EMAIL_DISCUSS_GENERATED} = 1;
}
@@ -1904,8 +1947,21 @@ sub hasDiscussion {
if (!defined($self->{DISCUSSION_TIME})) { return 0; }
#return defined($self->{DISCUSSION_TIME}->{$symb});
- return $self->{DISCUSSION_TIME}->{$symb} >
- $self->{LAST_CHECK};
+
+# backward compatibility (bulletin boards used to be 'wrapped')
+ my $ressymb = $symb;
+ if ($ressymb =~ m|adm/(\w+)/(\w+)/(\d+)/bulletinboard$|) {
+ unless ($ressymb =~ m|adm/wrapper/adm|) {
+ $ressymb = 'bulletin___'.$3.'___adm/wrapper/adm/'.$1.'/'.$2.'/'.$3.'/bulletinboard';
+ }
+ }
+
+ if ( defined ( $self->{LAST_READ}->{$ressymb} ) ) {
+ return $self->{DISCUSSION_TIME}->{$ressymb} > $self->{LAST_READ}->{$ressymb};
+ } else {
+# return $self->{DISCUSSION_TIME}->{$ressymb} > $self->{LAST_CHECK}; # v.1.1 behavior
+ return $self->{DISCUSSION_TIME}->{$ressymb} > 0; # in 1.2 will display speech bubble icons for all items with posts until marked as read (even if read in v 1.1).
+ }
}
# Private method: Does the given resource (as a symb string) have
@@ -2102,7 +2158,11 @@ sub parmval_real {
# ----------------------------------------------------- fourth , check default
- my $default=&Apache::lonnet::metadata($fn,$rwhat.'.default');
+ my $meta_rwhat=$rwhat;
+ $meta_rwhat=~s/\./_/g;
+ my $default=&Apache::lonnet::metadata($fn,$meta_rwhat);
+ if (defined($default)) { return $default}
+ $default=&Apache::lonnet::metadata($fn,'parameter_'.$meta_rwhat);
if (defined($default)) { return $default}
# --------------------------------------------------- fifth , cascade up parts
@@ -2157,7 +2217,7 @@ want to know is if I resources matc
parameter will allow you to avoid potentially expensive enumeration of
all matching resources.
-=item * B(map, filterFunc, recursive):
+=item * B(map, filterFunc, recursive):
Convience method for
@@ -2345,6 +2405,8 @@ consisting entirely of empty resources e
ending resource, will cause a lot of BRANCH_STARTs and BRANCH_ENDs,
but only one resource will be returned.
+=back
+
=head2 Normal Usage
Normal usage of the iterator object is to do the following:
@@ -2365,8 +2427,6 @@ the depth of the iterator to see when it
code. It is difficult to get right and harder to understand then
this. They should be migrated to this new style.
-=back
-
=cut
# Here are the tokens for the iterator:
@@ -2503,7 +2563,7 @@ sub new {
}
# Check: Was this only one resource, a map?
- if ($resourceCount == 1 && $resource->is_map() && !$self->{FORCE_TOP}) {
+ if ($resourceCount == 1 && $resource->is_sequence() && !$self->{FORCE_TOP}) {
my $firstResource = $resource->map_start();
my $finishResource = $resource->map_finish();
return
@@ -2536,7 +2596,7 @@ sub new {
sub next {
my $self = shift;
-
+ my $closeAllPages=shift;
if ($self->{FINISHED}) {
return END_ITERATOR();
}
@@ -2550,7 +2610,7 @@ sub next {
if ($self->{RECURSIVE_ITERATOR_FLAG}) {
# grab the next from the recursive iterator
- my $next = $self->{RECURSIVE_ITERATOR}->next();
+ my $next = $self->{RECURSIVE_ITERATOR}->next($closeAllPages);
# is it a begin or end map? If so, update the depth
if ($next == BEGIN_MAP() ) { $self->{RECURSIVE_DEPTH}++; }
@@ -2664,7 +2724,7 @@ sub next {
# That ends the main iterator logic. Now, do we want to recurse
# down this map (if this resource is a map)?
- if ($self->{HERE}->is_map() &&
+ if ( ($self->{HERE}->is_sequence() || (!$closeAllPages && $self->{HERE}->is_page())) &&
(defined($self->{FILTER}->{$self->{HERE}->map_pc()}) xor $self->{CONDITION})) {
$self->{RECURSIVE_ITERATOR_FLAG} = 1;
my $firstResource = $self->{HERE}->map_start();
@@ -2682,7 +2742,7 @@ sub next {
my $browsePriv = $self->{HERE}->browsePriv();
if (!$self->{HERE}->src() ||
(!($browsePriv eq 'F') && !($browsePriv eq '2')) ) {
- return $self->next();
+ return $self->next($closeAllPages);
}
return $self->{HERE};
@@ -2734,7 +2794,7 @@ package Apache::lonnavmaps::DFSiterator;
# useful for pre-processing of some kind, and is in fact used by the main
# iterator that way, but that's about it.
# One could imagine merging this into the init routine of the main iterator,
-# but this might as well be left seperate, since it is possible some other
+# but this might as well be left separate, since it is possible some other
# use might be found for it. - Jeremy
# Unlike the main iterator, this DOES return all resources, even blank ones.
@@ -3151,6 +3211,15 @@ Returns true if the resource is a sequen
=cut
+sub hasResource {
+ my $self = shift;
+ return $self->{NAV_MAP}->hasResource(@_);
+}
+
+sub retrieveResources {
+ my $self = shift;
+ return $self->{NAV_MAP}->retrieveResources(@_);
+}
sub is_html {
my $self=shift;
@@ -3167,7 +3236,15 @@ sub is_page {
sub is_problem {
my $self=shift;
my $src = $self->src();
- return ($src =~ /problem$/);
+ return ($src =~ /\.(problem|exam|quiz|assess|survey|form|library)$/)
+}
+sub contains_problem {
+ my $self=shift;
+ if ($self->is_page()) {
+ my $hasProblem=$self->hasResource($self,sub { $_[0]->is_problem() },1);
+ return $hasProblem;
+ }
+ return 0;
}
sub is_sequence {
my $self=shift;
@@ -3175,6 +3252,23 @@ sub is_sequence {
return $self->navHash("is_map_", 1) &&
$self->navHash("map_type_" . $self->map_pc()) eq 'sequence';
}
+sub is_survey {
+ my $self = shift();
+ my $part = shift();
+ if ($self->parmval('type',$part) eq 'survey') {
+ return 1;
+ }
+ if ($self->src() =~ /\.(survey)$/) {
+ return 1;
+ }
+ return 0;
+}
+
+sub is_empty_sequence {
+ my $self=shift;
+ my $src = $self->src();
+ return !$self->is_page() && $self->navHash("is_map_", 1) && !$self->navHash("map_type_" . $self->map_pc());
+}
# Private method: Shells out to the parmval in the nav map, handler parts.
sub parmval {
@@ -3351,6 +3445,11 @@ sub awarded {
}
sub duedate {
(my $self, my $part) = @_;
+ my $interval=$self->parmval("interval", $part);
+ if ($interval) {
+ my $first_access=&Apache::lonnet::get_first_access('map',$self->symb);
+ if ($first_access) { return ($first_access+$interval); }
+ }
return $self->parmval("duedate", $part);
}
sub maxtries {
@@ -3578,10 +3677,7 @@ sub extractParts {
# Retrieve part count, if this is a problem
if ($self->is_problem()) {
- my $partorder;
- # Hypothetically, replace previous line with:
- # my $partorder = &Apache::lonnet::metadata($self->src(), 'partorder');
- # and it'll all work...
+ my $partorder = &Apache::lonnet::metadata($self->src(), 'partorder');
my $metadata = &Apache::lonnet::metadata($self->src(), 'packages');
if ($partorder) {
@@ -3589,6 +3685,7 @@ sub extractParts {
for my $part (split (/,/,$partorder)) {
if (!Apache::loncommon::check_if_partid_hidden($part, $self->symb())) {
push @parts, $part;
+ $parts{$part} = 1;
}
}
$self->{PARTS} = \@parts;
@@ -3604,8 +3701,8 @@ sub extractParts {
my $part = $1;
# This floods the logs if it blows up
if (defined($parts{$part})) {
- Apache::lonnet::logthis("$part multiply defined in metadata for " . $self->symb());
- }
+ &Apache::lonnet::logthis("$part multiply defined in metadata for " . $self->symb());
+ }
# check to see if part is turned off.
@@ -3641,7 +3738,6 @@ sub extractParts {
my $partIdSoFar = '';
my @partChunks = split /_/, $partStuff;
my $i = 0;
-
for ($i = 0; $i < scalar(@partChunks); $i++) {
if ($partIdSoFar) { $partIdSoFar .= '_'; }
$partIdSoFar .= $partChunks[$i];
@@ -3654,7 +3750,20 @@ sub extractParts {
}
}
}
-
+ my $resorder = &Apache::lonnet::metadata($self->src(),'responseorder');
+ if ($resorder) {
+ my @resorder=split(/,/,$resorder);
+ foreach my $part (keys(%responseIdHash)) {
+ my %resids = map { ($_,1) } @{ $responseIdHash{$part} };
+ my @neworder;
+ foreach my $possibleid (@resorder) {
+ if (exists($resids{$possibleid})) {
+ push(@neworder,$possibleid);
+ }
+ }
+ $responseIdHash{$part}=\@neworder;
+ }
+ }
$self->{RESPONSE_IDS} = \%responseIdHash;
$self->{RESPONSE_TYPES} = \%responseTypeHash;
}
@@ -3846,8 +3955,9 @@ sub getCompletionStatus {
my $status = $self->queryRestoreHash('solved', shift);
- # Left as seperate if statements in case we ever do more with this
+ # Left as separate if statements in case we ever do more with this
if ($status eq 'correct_by_student') {return $self->CORRECT;}
+ if ($status eq 'correct_by_scantron') {return $self->CORRECT;}
if ($status eq 'correct_by_override') {return $self->CORRECT_BY_OVERRIDE; }
if ($status eq 'incorrect_attempted') {return $self->INCORRECT; }
if ($status eq 'incorrect_by_override') {return $self->INCORRECT_BY_OVERRIDE; }
@@ -3998,7 +4108,7 @@ sub status {
if ($dateStatus == PAST_DUE_ANSWER_LATER ||
$dateStatus == PAST_DUE_NO_ANSWER ) {
- return $dateStatus;
+ return $suppressFeedback ? ANSWER_SUBMITTED : $dateStatus;
}
if ($dateStatus == ANSWER_OPEN) {