version 1.190, 2003/05/14 20:16:56
|
version 1.191, 2003/05/16 14:17:08
|
Line 200 sub real_handler {
|
Line 200 sub real_handler {
|
} |
} |
} |
} |
|
|
|
my $jumpToFirstHomework = 0; |
# Check to see if the student is jumping to next open, do-able problem |
# Check to see if the student is jumping to next open, do-able problem |
if ($ENV{QUERY_STRING} eq 'jumpToFirstHomework') { |
if ($ENV{QUERY_STRING} eq 'jumpToFirstHomework') { |
|
$jumpToFirstHomework = 1; |
# Find the next homework problem that they can do. |
# Find the next homework problem that they can do. |
my $iterator = $navmap->getIterator(undef, undef, undef, 1); |
my $iterator = $navmap->getIterator(undef, undef, undef, 1); |
my $depth = 1; |
my $depth = 1; |
Line 216 sub real_handler {
|
Line 218 sub real_handler {
|
|
|
if (ref($curRes) && $curRes->is_problem()) { |
if (ref($curRes) && $curRes->is_problem()) { |
my $status = $curRes->status(); |
my $status = $curRes->status(); |
if (($status == $curRes->OPEN || |
if ($curRes->completable()) { |
$status == $curRes->TRIES_LEFT()) && |
|
$curRes->getCompletionStatus() != $curRes->ATTEMPTED()) { |
|
$problemRes = $curRes; |
$problemRes = $curRes; |
$foundDoableProblem = 1; |
$foundDoableProblem = 1; |
|
|
Line 246 sub real_handler {
|
Line 246 sub real_handler {
|
"Go To My First Homework Problem</a><br />"); |
"Go To My First Homework Problem</a><br />"); |
} |
} |
|
|
# renderer call |
my $suppressEmptySequences = 0; |
my $render = render({ 'cols' => [0,1,2,3], |
my $filterFunc = undef; |
'url' => '/adm/navmaps', |
# Display only due homework. |
'navmap' => $navmap, |
my $showOnlyHomework = 0; |
'suppressNavmap' => 1, |
if ($ENV{QUERY_STRING} eq 'showOnlyHomework') { |
'r' => $r}); |
$showOnlyHomework = 1; |
|
$suppressEmptySequences = 1; |
|
$filterFunc = sub { my $res = shift; |
|
return $res->completable() || $res->is_sequence(); |
|
}; |
|
$r->print("<p><font size='+2'>Uncompleted Homework</font></p>"); |
|
$ENV{'form.filter'} = ''; |
|
$ENV{'form.condition'} = 1; |
|
} else { |
|
$r->print("<a href='navmaps?showOnlyHomework'>" . |
|
"Show Only Uncompleted Homework</a><br />"); |
|
} |
|
|
|
# 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(); |
$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("<p><font size='+1'>All homework is currently completed.</font></p>"); |
|
} else { # both jumpToFirstHomework and normal use the same: course must be empty |
|
$r->print("<p><font size='+1'>This course is empty.</font></p>"); |
|
} |
|
} |
|
|
$r->print("</body></html>"); |
$r->print("</body></html>"); |
$r->rflush(); |
$r->rflush(); |
|
|
Line 1041 sub render {
|
Line 1071 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; |
my $condition = 0; |
if ($ENV{'form.condition'}) { |
if ($ENV{'form.condition'}) { |
$condition = 1; |
$condition = 1; |
Line 1137 sub render {
|
Line 1180 sub render {
|
} |
} |
|
|
# (re-)Locate the jump point, if any |
# (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 $mapIterator = $navmap->getIterator(undef, undef, $filterHash, 0); |
my $depth = 1; |
my $depth = 1; |
$mapIterator->next(); |
$mapIterator->next(); |
Line 1169 sub render {
|
Line 1214 sub render {
|
my $printKey = $args->{'printKey'}; |
my $printKey = $args->{'printKey'}; |
my $printCloseAll = $args->{'printCloseAll'}; |
my $printCloseAll = $args->{'printCloseAll'}; |
if (!defined($printCloseAll)) { $printCloseAll = 1; } |
if (!defined($printCloseAll)) { $printCloseAll = 1; } |
my $filterFunc = setDefault($args->{'filterFunc'}, |
|
sub {return 1;}); |
|
|
|
# Print key? |
# Print key? |
if ($printKey) { |
if ($printKey) { |
Line 1303 sub render {
|
Line 1346 sub render {
|
next; |
next; |
} |
} |
|
|
$args->{'counter'}++; |
|
|
|
# If this has been filtered out, continue on |
# If this has been filtered out, continue on |
if (!(&$filterFunc($curRes))) { |
if (!(&$filterFunc($curRes))) { |
$args->{'isNewBranch'} = 0; # Don't falsely remember this |
$args->{'isNewBranch'} = 0; # Don't falsely remember this |
Line 1322 sub render {
|
Line 1363 sub render {
|
next; |
next; |
} |
} |
|
|
|
$args->{'counter'}++; |
|
|
# Does it have multiple parts? |
# Does it have multiple parts? |
$args->{'multipart'} = 0; |
$args->{'multipart'} = 0; |
$args->{'condensed'} = 0; |
$args->{'condensed'} = 0; |
Line 3177 each part. Filtering part 0 if you want
|
Line 3220 each part. Filtering part 0 if you want
|
Returns the number of parts of the problem a student can answer. Thus, |
Returns the number of parts of the problem a student can answer. Thus, |
for single part problems, returns 1. For multipart, it returns the |
for single part problems, returns 1. For multipart, it returns the |
number of parts in the problem, not including psuedo-part 0. Thus, |
number of parts in the problem, not including psuedo-part 0. Thus, |
B<parts> may return an array with fewer parts in it then countParts |
B<parts> may return an array with more parts in it then countParts |
might lead you to believe. |
might lead you to believe. |
|
|
=item * B<responseType>($part): |
=item * B<responseType>($part): |
Line 3206 sub countParts {
|
Line 3249 sub countParts {
|
my $self = shift; |
my $self = shift; |
|
|
my $parts = $self->parts(); |
my $parts = $self->parts(); |
my $delta = 0; |
|
for my $part (@$parts) { |
# If I left this here, then it's not necessary. |
if ($part eq '0') { $delta--; } |
#my $delta = 0; |
} |
#for my $part (@$parts) { |
|
# if ($part eq '0') { $delta--; } |
|
#} |
|
|
if ($self->{RESOURCE_ERROR}) { |
if ($self->{RESOURCE_ERROR}) { |
return 0; |
return 0; |
} |
} |
|
|
return scalar(@{$parts}) + $delta; |
return scalar(@{$parts}); # + $delta; |
} |
} |
|
|
sub responseType { |
sub responseType { |
Line 3532 B<Composite Status>
|
Line 3577 B<Composite Status>
|
Along with directly returning the date or completion status, the |
Along with directly returning the date or completion status, the |
resource object includes a convenience function B<status>() that will |
resource object includes a convenience function B<status>() that will |
combine the two status tidbits into one composite status that can |
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 |
documented in the comments of the status method. The following results |
may be returned, all available as methods on the resource object |
may be returned, all available as methods on the resource object |
($res->NETWORK_FAILURE): In addition to the return values that match |
($res->NETWORK_FAILURE): In addition to the return values that match |
Line 3675 sub status {
|
Line 3722 sub status {
|
} |
} |
|
|
=pod |
=pod |
|
|
|
B<Completable> |
|
|
|
The completable method represents the concept of I<whether the student can |
|
currently do the problem>. 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 |
=head2 Resource/Nav Map Navigation |
|
|