--- loncom/interface/lonnavmaps.pm 2003/05/14 20:16:56 1.190 +++ loncom/interface/lonnavmaps.pm 2003/05/16 14:17:08 1.191 @@ -1,7 +1,7 @@ # The LearningOnline Network with CAPA # Navigate Maps Handler # -# $Id: lonnavmaps.pm,v 1.190 2003/05/14 20:16:56 bowersj2 Exp $ +# $Id: lonnavmaps.pm,v 1.191 2003/05/16 14:17:08 bowersj2 Exp $ # # Copyright Michigan State University Board of Trustees # @@ -200,8 +200,10 @@ sub real_handler { } } + my $jumpToFirstHomework = 0; # Check to see if the student is jumping to next open, do-able problem if ($ENV{QUERY_STRING} eq 'jumpToFirstHomework') { + $jumpToFirstHomework = 1; # Find the next homework problem that they can do. my $iterator = $navmap->getIterator(undef, undef, undef, 1); my $depth = 1; @@ -216,9 +218,7 @@ sub real_handler { if (ref($curRes) && $curRes->is_problem()) { my $status = $curRes->status(); - if (($status == $curRes->OPEN || - $status == $curRes->TRIES_LEFT()) && - $curRes->getCompletionStatus() != $curRes->ATTEMPTED()) { + if ($curRes->completable()) { $problemRes = $curRes; $foundDoableProblem = 1; @@ -246,15 +246,45 @@ sub real_handler { "Go To My First Homework Problem
"); } - # renderer call - my $render = render({ 'cols' => [0,1,2,3], - 'url' => '/adm/navmaps', - 'navmap' => $navmap, - 'suppressNavmap' => 1, - 'r' => $r}); + my $suppressEmptySequences = 0; + my $filterFunc = undef; + # Display only due homework. + my $showOnlyHomework = 0; + if ($ENV{QUERY_STRING} eq 'showOnlyHomework') { + $showOnlyHomework = 1; + $suppressEmptySequences = 1; + $filterFunc = sub { my $res = shift; + return $res->completable() || $res->is_sequence(); + }; + $r->print("

Uncompleted Homework

"); + $ENV{'form.filter'} = ''; + $ENV{'form.condition'} = 1; + } else { + $r->print("" . + "Show Only Uncompleted Homework
"); + } + # renderer call + my $renderArgs = { 'cols' => [0,1,2,3], + 'url' => '/adm/navmaps', + 'navmap' => $navmap, + 'suppressNavmap' => 1, + 'suppressEmptySequences' => $suppressEmptySequences, + 'filterFunc' => $filterFunc, + 'r' => $r}; + my $render = render($renderArgs); $navmap->untieHashes(); + # If no resources were printed, print a reassuring message so the + # user knows there was no error. + if ($renderArgs->{'counter'} == 0) { + if ($showOnlyHomework) { + $r->print("

All homework is currently completed.

"); + } else { # both jumpToFirstHomework and normal use the same: course must be empty + $r->print("

This course is empty.

"); + } + } + $r->print(""); $r->rflush(); @@ -1041,6 +1071,19 @@ sub render { } } + # Filter: Remember filter function and add our own filter: Refuse + # to show hidden resources unless the user can see them. + my $userCanSeeHidden = advancedUser(); + my $filterFunc = setDefault($args->{'filterFunc'}, + sub {return 1;}); + if (!$userCanSeeHidden) { + # Without renaming the filterfunc, the server seems to go into + # an infinite loop + my $oldFilterFunc = $filterFunc; + $filterFunc = sub { my $res = shift; return !$res->randomout() && + &$oldFilterFunc($res);}; + } + my $condition = 0; if ($ENV{'form.condition'}) { $condition = 1; @@ -1137,6 +1180,8 @@ sub render { } # (re-)Locate the jump point, if any + # Note this does not take filtering or hidden into account... need + # to be fixed? my $mapIterator = $navmap->getIterator(undef, undef, $filterHash, 0); my $depth = 1; $mapIterator->next(); @@ -1169,8 +1214,6 @@ sub render { my $printKey = $args->{'printKey'}; my $printCloseAll = $args->{'printCloseAll'}; if (!defined($printCloseAll)) { $printCloseAll = 1; } - my $filterFunc = setDefault($args->{'filterFunc'}, - sub {return 1;}); # Print key? if ($printKey) { @@ -1303,8 +1346,6 @@ sub render { next; } - $args->{'counter'}++; - # If this has been filtered out, continue on if (!(&$filterFunc($curRes))) { $args->{'isNewBranch'} = 0; # Don't falsely remember this @@ -1322,6 +1363,8 @@ sub render { next; } + $args->{'counter'}++; + # Does it have multiple parts? $args->{'multipart'} = 0; $args->{'condensed'} = 0; @@ -3177,7 +3220,7 @@ each part. Filtering part 0 if you want Returns the number of parts of the problem a student can answer. Thus, for single part problems, returns 1. For multipart, it returns the number of parts in the problem, not including psuedo-part 0. Thus, -B may return an array with fewer parts in it then countParts +B may return an array with more parts in it then countParts might lead you to believe. =item * B($part): @@ -3206,16 +3249,18 @@ sub countParts { my $self = shift; my $parts = $self->parts(); - my $delta = 0; - for my $part (@$parts) { - if ($part eq '0') { $delta--; } - } + + # If I left this here, then it's not necessary. + #my $delta = 0; + #for my $part (@$parts) { + # if ($part eq '0') { $delta--; } + #} if ($self->{RESOURCE_ERROR}) { return 0; } - return scalar(@{$parts}) + $delta; + return scalar(@{$parts}); # + $delta; } sub responseType { @@ -3532,7 +3577,9 @@ B Along with directly returning the date or completion status, the resource object includes a convenience function B() that will combine the two status tidbits into one composite status that can -represent the status of the resource as a whole. The precise logic is +represent the status of the resource as a whole. This method represents +the concept of the thing we want to display to the user on the nav maps +screen, which is a combination of completion and open status. 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): In addition to the return values that match @@ -3675,6 +3722,48 @@ sub status { } =pod + +B + +The completable method represents the concept of I. If the student can do the problem, which means +that it is open, there are tries left, and if the problem is manually graded +or the grade is suppressed via problemstatus, the student has not tried it +yet, then the method returns 1. Otherwise, it returns 0, to indicate that +either the student has tried it and there is no feedback, or that for +some reason it is no longer completable (not open yet, successfully completed, +out of tries, etc.). As an example, this is used as the filter for the +"Uncompleted Homework" option for the nav maps. + +If this does not quite meet your needs, do not fiddle with it (unless you are +fixing it to better match the student's conception of "completable" because +it's broken somehow)... make a new method. + +=cut + +sub completable { + my $self = shift; + if (!$self->is_problem()) { return 0; } + my $partCount = $self->countParts(); + + foreach my $part (@{$self->parts()}) { + if ($part eq '0' && $partCount != 1) { next; } + my $status = $self->status($part); + # "If any of the parts are open, or have tries left (implies open), + # and it is not "attempted" (manually graded problem), it is + # not "complete" + if (!(($status == OPEN() || $status == TRIES_LEFT()) + && $self->getCompletionStatus($part) != ATTEMPTED() + && $status != ANSWER_SUBMITTED())) { + return 0; + } + } + + # If all the parts were complete, so was this problem. + return 1; +} + +=pod =head2 Resource/Nav Map Navigation