version 1.51, 2002/09/24 01:18:50
|
version 1.53, 2002/09/24 03:48:18
|
Line 841 sub new_handle {
|
Line 841 sub new_handle {
|
$res->OPEN_LATER => '', |
$res->OPEN_LATER => '', |
$res->TRIES_LEFT => '#FFFF00', |
$res->TRIES_LEFT => '#FFFF00', |
$res->INCORRECT => '#FFAA00', |
$res->INCORRECT => '#FFAA00', |
$res->OPEN => '#FFFF88' ); |
$res->OPEN => '#FFFF88', |
|
$res->NOTHING_SET => '' ); |
|
|
if (!defined($navmap)) { |
if (!defined($navmap)) { |
my $requrl = $r->uri; |
my $requrl = $r->uri; |
Line 863 sub new_handle {
|
Line 864 sub new_handle {
|
|
|
my $mapIterator = $navmap->getIterator(undef, undef, \%filterHash); |
my $mapIterator = $navmap->getIterator(undef, undef, \%filterHash); |
my $curRes = $mapIterator->next(); |
my $curRes = $mapIterator->next(); |
|
undef $res; # so we don't accidentally use it later |
my $indentLevel = -1; |
my $indentLevel = -1; |
my $indentString = " "; |
my $indentString = " "; |
|
|
Line 870 sub new_handle {
|
Line 872 sub new_handle {
|
|
|
while ($curRes != $mapIterator->END_NAV_MAP) { |
while ($curRes != $mapIterator->END_NAV_MAP) { |
if ($curRes == $mapIterator->BEGIN_MAP() || |
if ($curRes == $mapIterator->BEGIN_MAP() || |
$curRes == $mapIterator->BEGIN_BRANCH()) { |
$curRes == $mapIterator->BEGIN_BRANCH()) { |
$indentLevel++; |
$indentLevel++; |
} |
} |
if ($curRes == $mapIterator->END_MAP() || |
if ($curRes == $mapIterator->END_MAP() || |
$curRes == $mapIterator->END_BRANCH()) { |
$curRes == $mapIterator->END_BRANCH()) { |
$indentLevel--; |
$indentLevel--; |
} |
} |
|
if ($curRes == $mapIterator->BEGIN_BRANCH()) { |
if ($curRes == $mapIterator->BEGIN_BRANCH()) { |
$isNewBranch = 1; |
$r->print("Begin branch<br/>"); |
|
} |
|
if ($curRes == $mapIterator->END_BRANCH()) { |
|
$r->print("End branch<br/>"); |
|
} |
} |
|
|
if (ref($curRes) && $curRes->src()) { |
if (ref($curRes) && $curRes->src()) { |
Line 911 sub new_handle {
|
Line 909 sub new_handle {
|
'"'; |
'"'; |
my $title = $curRes->title(); |
my $title = $curRes->title(); |
my $partLabel = ""; |
my $partLabel = ""; |
|
my $newBranchText = ""; |
|
|
|
# If this is a new branch, label it so |
|
# (temporary, this should be an icon w/ alt text) |
|
if ($isNewBranch) { |
|
$newBranchText = "NB -> "; |
|
$isNewBranch = 0; |
|
} |
|
|
# links to open and close the folders |
# links to open and close the folders |
my $linkopen = "<a href=\"$link\">"; |
my $linkopen = "<a href=\"$link\">"; |
Line 927 sub new_handle {
|
Line 933 sub new_handle {
|
my $nowOpen = !defined($filterHash{$mapId}); |
my $nowOpen = !defined($filterHash{$mapId}); |
$icon = $nowOpen ? |
$icon = $nowOpen ? |
"folder_opened.gif" : "folder_closed.gif"; |
"folder_opened.gif" : "folder_closed.gif"; |
$linkopen = "<a href=\"/adm/navmaps?jtest=1&filter="; |
$linkopen = "<a href=\"/adm/navmaps?filter="; |
$linkopen .= $nowOpen ? |
$linkopen .= $nowOpen ? |
addToFilter(\%filterHash, $mapId) : |
addToFilter(\%filterHash, $mapId) : |
removeFromFilter(\%filterHash, $mapId); |
removeFromFilter(\%filterHash, $mapId); |
Line 952 sub new_handle {
|
Line 958 sub new_handle {
|
$r->print($indentString); |
$r->print($indentString); |
} |
} |
|
|
$r->print(" ${linkopen}<img border=\"0\" src=\"" . |
$r->print(" ${newBranchText}${linkopen}<img border=\"0\" src=\"" . |
"/adm/lonIcons/$icon\" alt=\"\">${linkclose}\n"); |
"/adm/lonIcons/$icon\" alt=\"\">${linkclose}\n"); |
|
|
if ($curRes->is_problem() && $part != "0") { $partLabel = " (Part $part)"; } |
if ($curRes->is_problem() && $part != "0") { $partLabel = " (Part $part)"; } |
Line 962 sub new_handle {
|
Line 968 sub new_handle {
|
|
|
if ($curRes->kind() eq "res" and |
if ($curRes->kind() eq "res" and |
$curRes->is_problem() ) { |
$curRes->is_problem() ) { |
$r->print (" Due: " . localtime($curRes->duedate())); |
$r->print (getDescription($curRes, $part)); |
} |
} |
} |
} |
} |
} |
Line 1020 sub getLinkForResource {
|
Line 1026 sub getLinkForResource {
|
return $res->src(); |
return $res->src(); |
} |
} |
|
|
|
# Convenience function: This seperates 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 |
|
# 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. |
|
|
|
sub getDescription { |
|
my $res = shift; |
|
my $part = shift; |
|
my $status = $res->getDateStatus(); |
|
|
|
if ($status == $res->NETWORK_FAILURE) { return ""; } |
|
if ($status == $res->NOTHING_SET) { |
|
return "Not currently assigned."; |
|
} |
|
if ($status == $res->OPEN_LATER) { |
|
return "Opens: " . timeToHumanString($res->opendate($part)); |
|
} |
|
if ($status == $res->OPEN) { |
|
return "Due: " . timeToHumanString($res->duedate($part)); |
|
} |
|
if ($status == $res->PAST_DUE) { |
|
return "Answer: " . timeToHumanString($res->duedate($part)); |
|
} |
|
if ($status == $res->ANSWER_OPEN) { |
|
return "Answer available"; |
|
} |
|
|
|
} |
|
|
|
# I want to change this into something more human-friendly. For |
|
# now, this is a simple call to localtime. The final function |
|
# probably belongs in loncommon. |
|
sub timeToHumanString { |
|
return localtime(shift); |
|
} |
|
|
1; |
1; |
|
|
package Apache::lonnavmaps::navmap; |
package Apache::lonnavmaps::navmap; |
Line 1460 sub next {
|
Line 1503 sub next {
|
if (scalar(@{$self->{BRANCH_STACK}}) == 0) { |
if (scalar(@{$self->{BRANCH_STACK}}) == 0) { |
if ($self->{BRANCH_DEPTH} > 0) { |
if ($self->{BRANCH_DEPTH} > 0) { |
$self->{FORCE_NEXT} = $self->END_MAP(); |
$self->{FORCE_NEXT} = $self->END_MAP(); |
$self->{BRANCH_DEPTH}--; |
$self->{BRANCH_DEPTH}--; |
return $self->END_BRANCH(); |
return $self->END_BRANCH(); |
} else { |
} else { |
return $self->END_MAP(); |
return $self->END_MAP(); |
Line 1479 sub next {
|
Line 1522 sub next {
|
# to start a new one. (We know because we already checked to see |
# to start a new one. (We know because we already checked to see |
# if the stack was empty.) |
# if the stack was empty.) |
if ( scalar (@{$self->{BRANCH_STACK}}) < $self->{BRANCH_STACK_SIZE}) { |
if ( scalar (@{$self->{BRANCH_STACK}}) < $self->{BRANCH_STACK_SIZE}) { |
$self->{BRANCH_STACK_SIZE} = scalar(@{$self->{BRANCH_STACK}}); |
$self->{BRANCH_STACK_SIZE} = scalar(@{$self->{BRANCH_STACK}}); |
$self->{BRANCH_DEPTH}++; |
$self->{BRANCH_DEPTH}++; |
return $self->BEGIN_BRANCH(); |
return $self->BEGIN_BRANCH(); |
} |
} |
|
|
|
# Remember the size for comparision next time. |
|
$self->{BRANCH_STACK_SIZE} = scalar(@{$self->{BRANCH_STACK}}); |
|
|
|
# If the next resource we mean to return is going to need |
|
# a lower branch level, terminate branches until we get |
|
# there. |
|
|
# Get the next resource in the branch |
# Get the next resource in the branch |
$self->{HERE} = pop @{$self->{BRANCH_STACK}}; |
$self->{HERE} = pop @{$self->{BRANCH_STACK}}; |
|
|
|
# Are we at the right depth? If not, close a branch and return |
|
# the current resource onto the branch stack |
|
if (defined($self->{HERE}->{DATA}->{ITERATOR_DEPTH}) |
|
&& $self->{HERE}->{DATA}->{ITERATOR_DEPTH} < |
|
$self->{BRANCH_DEPTH} ) { |
|
$self->{BRANCH_DEPTH}--; |
|
# return it so we can pick it up eventually |
|
push @{$self->{BRANCH_STACK}}, $self->{HERE}; |
|
return $self->END_BRANCH(); |
|
} |
|
|
# We always return it after this point and never before |
# We always return it after this point and never before |
# (proof: look at just the return statements), so we |
# (proof: look at just the return statements), so we |
# remember that we've seen this. |
# remember that we've seen this. |
Line 1493 sub next {
|
Line 1555 sub next {
|
|
|
# Are we at the utter end? If so, return the END_NAV_MAP marker. |
# Are we at the utter end? If so, return the END_NAV_MAP marker. |
if ($self->{HERE} == $self->{NAV_MAP}->finishResource() ) { |
if ($self->{HERE} == $self->{NAV_MAP}->finishResource() ) { |
$self->{FORCE_NEXT} = $self->END_NAV_MAP; |
$self->{FORCE_NEXT} = $self->END_NAV_MAP; |
return $self->{HERE}; |
return $self->{HERE}; |
} |
} |
|
|
# Remember the size for comparision next time. |
|
$self->{BRANCH_STACK_SIZE} = scalar(@{$self->{BRANCH_STACK}}); |
|
|
|
# Get the next possible resources |
# Get the next possible resources |
my $nextUnfiltered = $self->{HERE}->getNext(); |
my $nextUnfiltered = $self->{HERE}->getNext(); |
my $next = []; |
my $next = []; |
|
|
# filter the next possibilities to remove things we've |
# filter the next possibilities to remove things we've |
# already seen |
# already seen. Also, remember what branch depth they should |
|
# be displayed at, since there's no other reliable way to tell. |
foreach (@$nextUnfiltered) { |
foreach (@$nextUnfiltered) { |
if (!defined($self->{ALREADY_SEEN}->{$_->{ID}})) { |
if (!defined($self->{ALREADY_SEEN}->{$_->{ID}})) { |
push @$next, $_; |
push @$next, $_; |
} |
$_->{DATA}->{ITERATOR_DEPTH} = |
|
$self->{BRANCH_DEPTH} + 1; |
|
} |
} |
} |
|
|
# Handle branch cases: |
# Handle branch cases: |
Line 1518 sub next {
|
Line 1580 sub next {
|
# 2+ things next: have some branches |
# 2+ things next: have some branches |
my $nextCount = scalar(@$next); |
my $nextCount = scalar(@$next); |
if ($nextCount == 0) { |
if ($nextCount == 0) { |
# Return this and on the next run, close the branch up if we're |
# Return this and on the next run, close the branch up if we're |
# in a branch |
# in a branch |
if ($self->{BRANCH_DEPTH} > 0 ) { |
if ($self->{BRANCH_DEPTH} > 0 ) { |
$self->{FORCE_NEXT} = $self->END_BRANCH(); |
$self->{FORCE_NEXT} = $self->END_BRANCH(); |
$self->{BRANCH_DEPTH}--; |
$self->{BRANCH_DEPTH}--; |
} |
} |
return $self->{HERE}; |
return $self->{HERE}; |
} |
} |
|
|
while (@$next) { |
while (@$next) { |
# copy the next possibilities over to the branch stack |
# copy the next possibilities over to the branch stack |
# in the right order |
# in the right order |
push @{$self->{BRANCH_STACK}}, shift @$next; |
push @{$self->{BRANCH_STACK}}, shift @$next; |
} |
} |
|
|
if ($nextCount >= 2) { |
if ($nextCount >= 2) { |
$self->{FORCE_NEXT} = $self->BEGIN_BRANCH(); |
$self->{FORCE_NEXT} = $self->BEGIN_BRANCH(); |
$self->{BRANCH_DEPTH}++; |
$self->{BRANCH_DEPTH}++; |
return $self->{HERE}; |
return $self->{HERE}; |
} |
} |
|
|
Line 1552 sub next {
|
Line 1614 sub next {
|
$self->{RECURSIVE_ITERATOR} = |
$self->{RECURSIVE_ITERATOR} = |
Apache::lonnavmaps::iterator->new ($self->{NAV_MAP}, $firstResource, |
Apache::lonnavmaps::iterator->new ($self->{NAV_MAP}, $firstResource, |
$finishResource, $self->{FILTER}, $self->{ALREADY_SEEN}); |
$finishResource, $self->{FILTER}, $self->{ALREADY_SEEN}); |
# prime the new iterator with the first resource |
# prime the new iterator with the first resource |
#push @{$self->{RECURSIVE_ITERATOR}->{BRANCH_STACK}}, $firstResource; |
#push @{$self->{RECURSIVE_ITERATOR}->{BRANCH_STACK}}, $firstResource; |
} |
} |
|
|
return $self->{HERE}; |
return $self->{HERE}; |
Line 1977 sub OPEN_LATER { return 0; }
|
Line 2039 sub OPEN_LATER { return 0; }
|
sub OPEN { return 1; } |
sub OPEN { return 1; } |
sub PAST_DUE { return 2; } |
sub PAST_DUE { return 2; } |
sub ANSWER_OPEN { return 3; } |
sub ANSWER_OPEN { return 3; } |
|
sub NOTHING_SET { return 4; } |
sub NETWORK_FAILURE { return 100; } |
sub NETWORK_FAILURE { return 100; } |
|
|
sub getDateStatus { |
sub getDateStatus { |
Line 1987 sub getDateStatus {
|
Line 2050 sub getDateStatus {
|
|
|
my $now = time(); |
my $now = time(); |
|
|
my $o = $now - $self->opendate($part); |
my $open = $self->opendate($part); |
my $d = $now - $self->duedate($part); |
my $due = $self->duedate($part); |
my $a = $now - $self->answerdate($part); |
my $answer = $self->answerdate($part); |
|
|
if ($o < 0) {return $self->OPEN_LATER}; |
if ($open && $now < $open) {return $self->OPEN_LATER}; |
if ($d < 0) {return $self->OPEN}; |
if ($due && $now < $due) {return $self->OPEN}; |
if ($a < 0) {return $self->PAST_DUE}; |
if ($answer && $now < $answer) {return $self->PAST_DUE}; |
|
if (!$open && !$due && !$answer) { |
|
# no data on the problem at all |
|
# should this be the same as "open later"? think multipart. |
|
return $self->NOTHING_SET; |
|
} |
return $self->ANSWER_OPEN; |
return $self->ANSWER_OPEN; |
} |
} |
|
|
Line 2029 B<Completion Codes>
|
Line 2097 B<Completion Codes>
|
|
|
=cut |
=cut |
|
|
sub NOT_ATTEMPTED { return 0; } |
sub NOT_ATTEMPTED { return 10; } |
sub INCORRECT { return 1; } |
sub INCORRECT { return 11; } |
sub INCORRECT_BY_OVERRIDE { return 2; } |
sub INCORRECT_BY_OVERRIDE { return 12; } |
sub CORRECT { return 3; } |
sub CORRECT { return 13; } |
sub CORRECT_BY_OVERRIDE { return 4; } |
sub CORRECT_BY_OVERRIDE { return 14; } |
sub EXCUSED { return 5; } |
sub EXCUSED { return 15; } |
|
|
sub getCompletionStatus { |
sub getCompletionStatus { |
my $self = shift; |
my $self = shift; |
Line 2066 Along with directly returning the date o
|
Line 2134 Along with directly returning the date o
|
|
|
=item * NETWORK_FAILURE: The network has failed and the information is not available. |
=item * NETWORK_FAILURE: The network has failed and the information is not available. |
|
|
|
=item * NOTHING_SET: No dates have been set for this problem (part) at all. (Because only certain parts of a multi-part problem may be assigned, this can not be collapsed into "open later", as we don't know a given part will EVER be opened.) |
|
|
=item * CORRECT: For any reason at all, the part is considered correct. |
=item * CORRECT: For any reason at all, the part is considered correct. |
|
|
=item * EXCUSED: For any reason at all, the problem is excused. |
=item * EXCUSED: For any reason at all, the problem is excused. |
Line 2097 sub status {
|
Line 2167 sub status {
|
|
|
# What we have is a two-dimensional matrix with 4 entries on one |
# What we have is a two-dimensional matrix with 4 entries on one |
# 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. |
# plus network failure and "no date data". |
|
|
# Don't colorize on network failure. |
if ($completionStatus == NETWORK_FAILURE) { return NETWORK_FAILURE; } |
if ($completionStatus == NETWORK_FAILURE()) { return $self->NETWORK_FAILURE(); } |
|
|
|
# There are a few whole rows we can dispose of: |
# There are a few whole rows we can dispose of: |
# If the problem is CORRECT, color it green no matter what |
if ($completionStatus == CORRECT || |
if ($completionStatus == CORRECT() || |
$completionStatus == CORRECT_BY_OVERRIDE ) { |
$completionStatus == CORRECT_BY_OVERRIDE() ) { |
return CORRECT(); |
return $self->CORRECT(); # Return a nice green. |
} |
|
|
|
# If it's EXCUSED, then return that no matter what |
|
if ($completionStatus == EXCUSED) { |
|
return EXCUSED; |
} |
} |
|
|
# If it's EXCUSED, then return something no matter what |
if ($dateStatus == NOTHING_SET) { |
if ($completionStatus == EXCUSED()) { |
return NOTHING_SET; |
return $self->EXCUSED(); # return a nice blue |
|
} |
} |
|
|
# Now we're down to a 3 (incorrect, incorrect_override, not_attempted) |
# Now we're down to a 3 (incorrect, incorrect_override, not_attempted) |
# by 4 matrix (date status). |
# by 4 matrix (date status). |
|
|
# If it's Past Due and we didn't bail earlier because it's correct, |
if ($dateStatus == PAST_DUE) { |
# color it orange. (Red is sort inappropriate; too drastic a color |
return PAST_DUE; |
# for something the student can't fix. |
|
if ($dateStatus == PAST_DUE()) { |
|
return $self->PAST_DUE(); # return orange |
|
} |
} |
|
|
if ($dateStatus == ANSWER_OPEN()) { |
if ($dateStatus == ANSWER_OPEN) { |
return $self->ANSWER_OPEN(); |
return ANSWER_OPEN; |
} |
} |
|
|
# Now: (incorrect, incorrect_override, not_attempted) x |
# Now: (incorrect, incorrect_override, not_attempted) x |
# (open_later), (open) |
# (open_later), (open) |
|
|
# If it's open later, then don't colorize |
if ($dateStatus == OPEN_LATER) { |
if ($dateStatus == OPEN_LATER()) { |
return OPEN_LATER; |
return $self->OPEN_LATER(); |
|
} |
} |
|
|
# If it's WRONG... |
# If it's WRONG... |
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() < $self->maxtries()) { |
if ($self->tries() < $self->maxtries()) { |
return $self->TRIES_LEFT(); # return red: The student can fix this |
return TRIES_LEFT; |
} |
} |
return $self->INCORRECT(); # otherwise, return orange; student can't fix this |
return INCORRECT; # otherwise, return orange; student can't fix this |
} |
} |
|
|
# Otherwise, it's untried and open |
# Otherwise, it's untried and open |
return $self->OPEN(); # Light yellow |
return OPEN; |
} |
} |
|
|
=pod |
=pod |