version 1.221, 2003/08/07 17:26:44
|
version 1.222, 2003/08/19 15:29:33
|
Line 168 sub real_handler {
|
Line 168 sub real_handler {
|
|
|
# See if there's only one map in the top-level, if we don't |
# See if there's only one map in the top-level, if we don't |
# already have a filter... if so, automatically display it |
# already have a filter... if so, automatically display it |
|
# (older code; should use retrieveResources) |
if ($ENV{QUERY_STRING} !~ /filter/) { |
if ($ENV{QUERY_STRING} !~ /filter/) { |
my $iterator = $navmap->getIterator(undef, undef, undef, 0); |
my $iterator = $navmap->getIterator(undef, undef, undef, 0); |
my $depth = 1; |
my $curRes; |
$iterator->next(); |
|
my $curRes = $iterator->next(); |
|
my $sequenceCount = 0; |
my $sequenceCount = 0; |
my $sequenceId; |
my $sequenceId; |
while ($depth > 0) { |
while ($curRes = $iterator->next()) { |
if ($curRes == $iterator->BEGIN_MAP()) { $depth++; } |
|
if ($curRes == $iterator->END_MAP()) { $depth--; } |
|
|
|
if (ref($curRes) && $curRes->is_sequence()) { |
if (ref($curRes) && $curRes->is_sequence()) { |
$sequenceCount++; |
$sequenceCount++; |
$sequenceId = $curRes->map_pc(); |
$sequenceId = $curRes->map_pc(); |
} |
} |
|
|
$curRes = $iterator->next(); |
|
} |
} |
|
|
if ($sequenceCount == 1) { |
if ($sequenceCount == 1) { |
Line 202 sub real_handler {
|
Line 196 sub real_handler {
|
$jumpToFirstHomework = 1; |
$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 $curRes; |
$iterator->next(); |
|
my $curRes = $iterator->next(); |
|
my $foundDoableProblem = 0; |
my $foundDoableProblem = 0; |
my $problemRes; |
my $problemRes; |
|
|
while ($depth > 0 && !$foundDoableProblem) { |
while (($curRes = $iterator->next()) && !$foundDoableProblem) { |
if ($curRes == $iterator->BEGIN_MAP()) { $depth++; } |
|
if ($curRes == $iterator->END_MAP()) { $depth--; } |
|
|
|
if (ref($curRes) && $curRes->is_problem()) { |
if (ref($curRes) && $curRes->is_problem()) { |
my $status = $curRes->status(); |
my $status = $curRes->status(); |
if ($curRes->completable()) { |
if ($curRes->completable()) { |
Line 229 sub real_handler {
|
Line 218 sub real_handler {
|
$ENV{'form.postsymb'} = $curRes->symb(); |
$ENV{'form.postsymb'} = $curRes->symb(); |
} |
} |
} |
} |
} continue { |
|
$curRes = $iterator->next(); |
|
} |
} |
|
|
# If we found no problems, print a note to that effect. |
# If we found no problems, print a note to that effect. |
Line 1185 sub render {
|
Line 1172 sub render {
|
|
|
# Step three: Ensure the folders are open |
# Step three: Ensure the folders are open |
my $mapIterator = $navmap->getIterator(undef, undef, undef, 1); |
my $mapIterator = $navmap->getIterator(undef, undef, undef, 1); |
my $depth = 1; |
my $curRes; |
$mapIterator->next(); # discard the first BEGIN_MAP |
|
my $curRes = $mapIterator->next(); |
|
my $found = 0; |
my $found = 0; |
|
|
# We only need to do this if we need to open the maps to show the |
# 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 |
# current position. This will change the counter so we can't count |
# for the jump marker with this loop. |
# for the jump marker with this loop. |
while ($depth > 0 && !$found) { |
while (($curRes = $mapIterator->next()) && !$found) { |
if ($curRes == $mapIterator->BEGIN_MAP()) { $depth++; } |
|
if ($curRes == $mapIterator->END_MAP()) { $depth--; } |
|
|
|
if (ref($curRes) && $curRes->symb() eq $here) { |
if (ref($curRes) && $curRes->symb() eq $here) { |
my $mapStack = $mapIterator->getStack(); |
my $mapStack = $mapIterator->getStack(); |
|
|
Line 1210 sub render {
|
Line 1192 sub render {
|
} |
} |
$found = 1; |
$found = 1; |
} |
} |
|
|
$curRes = $mapIterator->next(); |
|
} |
} |
} |
} |
|
|
Line 1249 sub render {
|
Line 1229 sub render {
|
# Note this does not take filtering or hidden into account... need |
# Note this does not take filtering or hidden into account... need |
# to be fixed? |
# to be fixed? |
my $mapIterator = $navmap->getIterator(undef, undef, $filterHash, 0); |
my $mapIterator = $navmap->getIterator(undef, undef, $filterHash, 0); |
my $depth = 1; |
my $curRes; |
$mapIterator->next(); |
|
my $curRes = $mapIterator->next(); |
|
my $foundJump = 0; |
my $foundJump = 0; |
my $counter = 0; |
my $counter = 0; |
|
|
while ($depth > 0 && !$foundJump) { |
while (($curRes = $mapIterator->next()) && !$foundJump) { |
if ($curRes == $mapIterator->BEGIN_MAP()) { $depth++; } |
|
if ($curRes == $mapIterator->END_MAP()) { $depth--; } |
|
if (ref($curRes)) { $counter++; } |
if (ref($curRes)) { $counter++; } |
|
|
if (ref($curRes) && $jump eq $curRes->symb()) { |
if (ref($curRes) && $jump eq $curRes->symb()) { |
Line 1268 sub render {
|
Line 1244 sub render {
|
$args->{'currentJumpIndex'} = $counter; |
$args->{'currentJumpIndex'} = $counter; |
$foundJump = 1; |
$foundJump = 1; |
} |
} |
|
|
$curRes = $mapIterator->next(); |
|
} |
} |
|
|
my $showParts = setDefault($args->{'showParts'}, 1); |
my $showParts = setDefault($args->{'showParts'}, 1); |
Line 1347 sub render {
|
Line 1321 sub render {
|
$it->{FIRST_RESOURCE}, |
$it->{FIRST_RESOURCE}, |
$it->{FINISH_RESOURCE}, |
$it->{FINISH_RESOURCE}, |
{}, undef, 1); |
{}, undef, 1); |
$depth = 0; |
my $depth = 0; |
$dfsit->next(); |
$dfsit->next(); |
my $curRes = $dfsit->next(); |
my $curRes = $dfsit->next(); |
while ($depth > -1) { |
while ($depth > -1) { |
Line 1379 sub render {
|
Line 1353 sub render {
|
|
|
my $displayedJumpMarker = 0; |
my $displayedJumpMarker = 0; |
# Set up iteration. |
# Set up iteration. |
$depth = 1; |
|
$it->next(); # discard initial BEGIN_MAP |
|
$curRes = $it->next(); |
|
my $now = time(); |
my $now = time(); |
my $in24Hours = $now + 24 * 60 * 60; |
my $in24Hours = $now + 24 * 60 * 60; |
my $rownum = 0; |
my $rownum = 0; |
Line 1389 sub render {
|
Line 1360 sub render {
|
# export "here" marker information |
# export "here" marker information |
$args->{'here'} = $here; |
$args->{'here'} = $here; |
|
|
while ($depth > 0) { |
$args->{'indentLevel'} = -1; # first BEGIN_MAP takes this to 0 |
if ($curRes == $it->BEGIN_MAP()) { $depth++; } |
while ($curRes = $it->next()) { |
if ($curRes == $it->END_MAP()) { $depth--; } |
|
|
|
# Maintain indentation level. |
# Maintain indentation level. |
if ($curRes == $it->BEGIN_MAP() || |
if ($curRes == $it->BEGIN_MAP() || |
$curRes == $it->BEGIN_BRANCH() ) { |
$curRes == $it->BEGIN_BRANCH() ) { |
Line 1545 sub render {
|
Line 1514 sub render {
|
$r->rflush(); |
$r->rflush(); |
} |
} |
} continue { |
} continue { |
$curRes = $it->next(); |
|
|
|
if ($r) { |
if ($r) { |
# If we have the connection, make sure the user is still connected |
# If we have the connection, make sure the user is still connected |
my $c = $r->connection; |
my $c = $r->connection; |
Line 2184 sub retrieveResources {
|
Line 2151 sub retrieveResources {
|
my @resources = (); |
my @resources = (); |
|
|
# Run down the iterator and collect the resources. |
# Run down the iterator and collect the resources. |
my $depth = 1; |
my $curRes; |
$it->next(); |
|
my $curRes = $it->next(); |
while ($curRes = $it->next()) { |
|
|
while ($depth > 0) { |
|
if ($curRes == $it->BEGIN_MAP()) { |
|
$depth++; |
|
} |
|
if ($curRes == $it->END_MAP()) { |
|
$depth--; |
|
} |
|
|
|
if (ref($curRes)) { |
if (ref($curRes)) { |
if (!&$filterFunc($curRes)) { |
if (!&$filterFunc($curRes)) { |
next; |
next; |
Line 2208 sub retrieveResources {
|
Line 2166 sub retrieveResources {
|
} |
} |
} |
} |
|
|
} continue { |
|
$curRes = $it->next(); |
|
} |
} |
|
|
return @resources; |
return @resources; |
Line 2285 new branch. The possible tokens are:
|
Line 2241 new branch. The possible tokens are:
|
|
|
=over 4 |
=over 4 |
|
|
|
=item * B<END_ITERATOR>: |
|
|
|
The iterator has returned all that it's going to. Further calls to the |
|
iterator will just produce more of these. This is a "false" value, and |
|
is the only false value the iterator which will be returned, so it can |
|
be used as a loop sentinel. |
|
|
=item * B<BEGIN_MAP>: |
=item * B<BEGIN_MAP>: |
|
|
A new map is being recursed into. This is returned I<after> the map |
A new map is being recursed into. This is returned I<after> the map |
Line 2315 consisting entirely of empty resources e
|
Line 2278 consisting entirely of empty resources e
|
ending resource, will cause a lot of BRANCH_STARTs and BRANCH_ENDs, |
ending resource, will cause a lot of BRANCH_STARTs and BRANCH_ENDs, |
but only one resource will be returned. |
but only one resource will be returned. |
|
|
|
=head2 Normal Usage |
|
|
|
Normal usage of the iterator object is to do the following: |
|
|
|
my $it = $navmap->getIterator([your params here]); |
|
my $curRes; |
|
while ($curRes = $it->next()) { |
|
[your logic here] |
|
} |
|
|
|
Note that inside of the loop, it's frequently useful to check if |
|
"$curRes" is a reference or not with the reference function; only |
|
resource objects will be references, and any non-references will |
|
be the tokens described above. |
|
|
|
Also note there is some old code floating around that trys to track |
|
the depth of the iterator to see when it's done; do not copy that |
|
code. It is difficult to get right and harder to understand then |
|
this. They should be migrated to this new style. |
|
|
=back |
=back |
|
|
=cut |
=cut |
|
|
# Here are the tokens for the iterator: |
# Here are the tokens for the iterator: |
|
|
|
sub END_ITERATOR { return 0; } |
sub BEGIN_MAP { return 1; } # begining of a new map |
sub BEGIN_MAP { return 1; } # begining of a new map |
sub END_MAP { return 2; } # end of the map |
sub END_MAP { return 2; } # end of the map |
sub BEGIN_BRANCH { return 3; } # beginning of a branch |
sub BEGIN_BRANCH { return 3; } # beginning of a branch |
Line 2406 sub new {
|
Line 2390 sub new {
|
|
|
# prime the recursion |
# prime the recursion |
$self->{$firstResourceName}->{DATA}->{$valName} = 0; |
$self->{$firstResourceName}->{DATA}->{$valName} = 0; |
my $depth = 0; |
$iterator->next(); |
$iterator->next(); |
|
my $curRes = $iterator->next(); |
my $curRes = $iterator->next(); |
while ($depth > -1) { |
my $depth = 1; |
if ($curRes == $iterator->BEGIN_MAP()) { $depth++; } |
while ($depth > 0) { |
if ($curRes == $iterator->END_MAP()) { $depth--; } |
if ($curRes == $iterator->BEGIN_MAP()) { $depth++; } |
|
if ($curRes == $iterator->END_MAP()) { $depth--; } |
|
|
if (ref($curRes)) { |
if (ref($curRes)) { |
# If there's only one resource, this will save it |
# If there's only one resource, this will save it |
# we have to filter empty resources from consideration here, |
# we have to filter empty resources from consideration here, |
Line 2446 sub new {
|
Line 2430 sub new {
|
$curRes->{DATA}->{DISPLAY_DEPTH} = $finalDepth; |
$curRes->{DATA}->{DISPLAY_DEPTH} = $finalDepth; |
if ($finalDepth > $maxDepth) {$maxDepth = $finalDepth;} |
if ($finalDepth > $maxDepth) {$maxDepth = $finalDepth;} |
} |
} |
} continue { |
|
$curRes = $iterator->next(); |
$curRes = $iterator->next(); |
} |
} |
} |
} |
|
|
Line 2468 sub new {
|
Line 2452 sub new {
|
$self->{MAX_DEPTH} = $maxDepth; |
$self->{MAX_DEPTH} = $maxDepth; |
$self->{STACK} = []; |
$self->{STACK} = []; |
$self->{RECURSIVE_ITERATOR_FLAG} = 0; |
$self->{RECURSIVE_ITERATOR_FLAG} = 0; |
|
$self->{FINISHED} = 0; # When true, the iterator has finished |
|
|
for (my $i = 0; $i <= $self->{MAX_DEPTH}; $i++) { |
for (my $i = 0; $i <= $self->{MAX_DEPTH}; $i++) { |
push @{$self->{STACK}}, []; |
push @{$self->{STACK}}, []; |
Line 2485 sub new {
|
Line 2470 sub new {
|
sub next { |
sub next { |
my $self = shift; |
my $self = shift; |
|
|
|
if ($self->{FINISHED}) { |
|
return END_ITERATOR(); |
|
} |
|
|
# If we want to return the top-level map object, and haven't yet, |
# If we want to return the top-level map object, and haven't yet, |
# do so. |
# do so. |
if ($self->{RETURN_0} && !$self->{HAVE_RETURNED_0}) { |
if ($self->{RETURN_0} && !$self->{HAVE_RETURNED_0}) { |
Line 2544 sub next {
|
Line 2533 sub next {
|
$self->{CURRENT_DEPTH}--; |
$self->{CURRENT_DEPTH}--; |
return END_BRANCH(); |
return END_BRANCH(); |
} else { |
} else { |
|
$self->{FINISHED} = 1; |
return END_MAP(); |
return END_MAP(); |
} |
} |
} |
} |
Line 3881 sub status {
|
Line 3871 sub status {
|
# dimension and 5 entries on the other, which we want to colorize, |
# dimension and 5 entries on the other, which we want to colorize, |
# plus network failure and "no date data at all". |
# plus network failure and "no date data at all". |
|
|
|
#if ($self->{RESOURCE_ERROR}) { return NETWORK_FAILURE; } |
if ($completionStatus == NETWORK_FAILURE) { return NETWORK_FAILURE; } |
if ($completionStatus == NETWORK_FAILURE) { return NETWORK_FAILURE; } |
|
|
my $suppressFeedback = lc($self->parmval("problemstatus", $part)) eq 'no'; |
my $suppressFeedback = lc($self->parmval("problemstatus", $part)) eq 'no'; |
Line 3927 sub status {
|
Line 3918 sub status {
|
if ($completionStatus == INCORRECT || $completionStatus == INCORRECT_BY_OVERRIDE) { |
if ($completionStatus == INCORRECT || $completionStatus == INCORRECT_BY_OVERRIDE) { |
# and there are TRIES LEFT: |
# and there are TRIES LEFT: |
if ($self->tries($part) < $self->maxtries($part) || !$self->maxtries($part)) { |
if ($self->tries($part) < $self->maxtries($part) || !$self->maxtries($part)) { |
return TRIES_LEFT; |
return $suppressFeedback ? ANSWER_SUBMITTED : TRIES_LEFT; |
} |
} |
return $suppressFeedback ? ANSWER_SUBMITTED : INCORRECT; # otherwise, return orange; student can't fix this |
return $suppressFeedback ? ANSWER_SUBMITTED : INCORRECT; # otherwise, return orange; student can't fix this |
} |
} |