--- loncom/interface/lonnavmaps.pm 2003/05/05 17:44:03 1.184 +++ loncom/interface/lonnavmaps.pm 2003/05/14 18:01:16 1.187 @@ -1,7 +1,7 @@ # The LearningOnline Network with CAPA # Navigate Maps Handler # -# $Id: lonnavmaps.pm,v 1.184 2003/05/05 17:44:03 bowersj2 Exp $ +# $Id: lonnavmaps.pm,v 1.187 2003/05/14 18:01:16 bowersj2 Exp $ # # Copyright Michigan State University Board of Trustees # @@ -71,7 +71,8 @@ my %statusIconMap = $resObj->TRIES_LEFT => 'navmap.open.gif', $resObj->INCORRECT => 'navmap.wrong.gif', $resObj->OPEN => 'navmap.open.gif', - $resObj->ATTEMPTED => 'navmap.open.gif' ); + $resObj->ATTEMPTED => 'navmap.open.gif', + $resObj->ANSWER_SUBMITTED => '' ); my %iconAltTags = ( 'navmap.correct.gif' => 'Correct', @@ -365,6 +366,9 @@ sub getDescription { return "No due date $triesString"; } } + if ($status == $res->ANSWER_SUBMITTED) { + return 'Answer submitted'; + } } # Convenience function, so others can use it: Is the problem due in less then @@ -2799,7 +2803,10 @@ sub is_sequence { sub parmval { my $self = shift; my $what = shift; - my $part = shift || "0"; + my $part = shift; + if (!defined($part)) { + $part = '0'; + } return $self->{NAV_MAP}->parmval($part.'.'.$what, $self->symb()); } @@ -2973,6 +2980,10 @@ sub opendate { } return $self->parmval("opendate"); } +sub problemstatus { + (my $self, my $part) = @_; + return $self->parmval("problemstatus", $part); +} sub sig { (my $self, my $part) = @_; return $self->parmval("sig", $part); @@ -3086,6 +3097,15 @@ number of parts in the problem, not incl B may return an array with fewer parts in it then countParts might lead you to believe. +=item * B($part): + +Returns the response type of the part, without the word "response" on the +end. Example return values: 'string', 'essay', 'numeric', etc. + +=item * B($part): + +Retreives the response ID for the given part, which may be an empty string. + =back =cut @@ -3115,16 +3135,24 @@ sub countParts { return scalar(@{$parts}) + $delta; } -sub partType { +sub responseType { + my $self = shift; + my $part = shift; + + $self->extractParts(); + return $self->{RESPONSE_TYPE}->{$part}; +} + +sub responseId { my $self = shift; my $part = shift; $self->extractParts(); - return $self->{PART_TYPE}->{$part}; + return $self->{RESPONSE_IDS}->{$part}; } # Private function: Extracts the parts information, both part names and -# part types, and saves it +# part types, and saves it. sub extractParts { my $self = shift; @@ -3138,6 +3166,7 @@ sub extractParts { # Retrieve part count, if this is a problem if ($self->is_problem()) { my $metadata = &Apache::lonnet::metadata($self->src(), 'packages'); + print $metadata; if (!$metadata) { $self->{RESOURCE_ERROR} = 1; $self->{PARTS} = []; @@ -3163,6 +3192,40 @@ sub extractParts { my @sortedParts = sort keys %parts; $self->{PARTS} = \@sortedParts; + + my %responseIdHash; + my %responseTypeHash; + + # Now, the unfortunate thing about this is that parts, part name, and + # response if are delimited by underscores, but both the part + # name and response id can themselves have underscores in them. + # So we have to use our knowlege of part names to figure out + # where the part names begin and end, and even then, it is possible + # to construct ambiguous situations. + foreach (split /,/, $metadata) { + if ($_ =~ /^([a-zA-Z]+)response_(.*)/) { + my $responseType = $1; + my $partStuff = $2; + my $partIdSoFar = ''; + my @partChunks = split /_/, $partStuff; + my $i = 0; + + for ($i = 0; $i < scalar(@partChunks); $i++) { + if ($partIdSoFar) { $partIdSoFar .= '_'; } + $partIdSoFar .= $partChunks[$i]; + if ($parts{$partIdSoFar}) { + my @otherChunks = @partChunks[$i+1..$#partChunks]; + my $responseId = join('_', @otherChunks); + $responseIdHash{$partIdSoFar} = $responseId; + $responseTypeHash{$partIdSoFar} = $responseType; + last; + } + } + } + } + + $self->{RESPONSE_IDS} = \%responseIdHash; + $self->{RESPONSE_TYPES} = \%responseTypeHash; } return; @@ -3366,7 +3429,7 @@ sub queryRestoreHash { my $self = shift; my $hashentry = shift; my $part = shift; - $part = "0" if (!defined($part)); + $part = "0" if (!defined($part) || $part eq ''); return $self->NETWORK_FAILURE if ($self->{NAV_MAP}->{NETWORK_FAILURE}); $self->getReturnHash(); @@ -3384,7 +3447,10 @@ combine the two status tidbits into one represent the status of the resource as a whole. The precise logic is documented in the comments of the status method. The following results may be returned, all available as methods on the resource object -($res->NETWORK_FAILURE): +($res->NETWORK_FAILURE): In addition to the return values that match +the date or completion status, this function can return "ANSWER_SUBMITTED" +if that problemstatus parameter value is set to No, suppressing the +incorrect/correct feedback. =over 4 @@ -3443,11 +3509,16 @@ The item is open and not yet tried. The problem has been attempted. +=item * B: + +An answer has been submitted, but the student should not see it. + =back =cut -sub TRIES_LEFT { return 10; } +sub TRIES_LEFT { return 20; } +sub ANSWER_SUBMITTED { return 21; } sub status { my $self = shift; @@ -3462,10 +3533,12 @@ sub status { if ($completionStatus == NETWORK_FAILURE) { return NETWORK_FAILURE; } + my $suppressFeedback = lc($self->parmval("problemstatus", $part)) eq 'no'; + # There are a few whole rows we can dispose of: if ($completionStatus == CORRECT || $completionStatus == CORRECT_BY_OVERRIDE ) { - return CORRECT; + return $suppressFeedback? ANSWER_SUBMITTED : CORRECT; } if ($completionStatus == ATTEMPTED) { @@ -3506,7 +3579,7 @@ sub status { if ($self->tries($part) < $self->maxtries($part) || !$self->maxtries($part)) { return TRIES_LEFT; } - return INCORRECT; # otherwise, return orange; student can't fix this + return $suppressFeedback ? ANSWER_SUBMITTED : INCORRECT; # otherwise, return orange; student can't fix this } # Otherwise, it's untried and open