version 1.460, 2011/05/22 14:55:30
|
version 1.474, 2011/12/21 16:53:03
|
Line 225 automatically.
|
Line 225 automatically.
|
|
|
=over 4 |
=over 4 |
|
|
=item * B<iterator>: default: constructs one from %env |
=item * B<iterator: default: constructs one from %env |
|
|
A reference to a fresh ::iterator to use from the navmaps. The |
A reference to a fresh ::iterator to use from the navmaps. The |
rendering will reflect the options passed to the iterator, so you can |
rendering will reflect the options passed to the iterator, so you can |
Line 478 use Apache::loncommon();
|
Line 478 use Apache::loncommon();
|
use Apache::lonenc(); |
use Apache::lonenc(); |
use Apache::lonlocal; |
use Apache::lonlocal; |
use Apache::lonnet; |
use Apache::lonnet; |
|
use Apache::lonmap; |
|
|
use POSIX qw (floor strftime); |
use POSIX qw (floor strftime); |
use Time::HiRes qw( gettimeofday tv_interval ); |
use Time::HiRes qw( gettimeofday tv_interval ); |
use LONCAPA; |
use LONCAPA; |
use DateTime(); |
use DateTime(); |
use Data::Dumper; |
|
|
# For debugging |
|
|
|
# use Data::Dumper; |
|
|
|
|
# symbolic constants |
# symbolic constants |
sub SYMB { return 1; } |
sub SYMB { return 1; } |
sub URL { return 2; } |
sub URL { return 2; } |
Line 509 my %statusIconMap =
|
Line 515 my %statusIconMap =
|
my %iconAltTags = #texthash does not work here |
my %iconAltTags = #texthash does not work here |
( 'navmap.correct.gif' => 'Correct', |
( 'navmap.correct.gif' => 'Correct', |
'navmap.wrong.gif' => 'Incorrect', |
'navmap.wrong.gif' => 'Incorrect', |
'navmap.open.gif' => 'Open', |
'navmap.open.gif' => 'Is Open', |
'navmap.partial.gif' => 'Partially Correct', |
'navmap.partial.gif' => 'Partially Correct', |
'navmap.ellipsis.gif' => 'Attempted', |
'navmap.ellipsis.gif' => 'Attempted', |
); |
); |
Line 536 my %colormap =
|
Line 542 my %colormap =
|
# is not yet done and due in less than 24 hours |
# is not yet done and due in less than 24 hours |
my $hurryUpColor = "#FF0000"; |
my $hurryUpColor = "#FF0000"; |
|
|
my $future_slots_checked = 0; |
|
my $future_slots = 0; |
|
|
|
sub addToFilter { |
sub addToFilter { |
my $hashIn = shift; |
my $hashIn = shift; |
my $addition = shift; |
my $addition = shift; |
Line 612 sub getDescription {
|
Line 615 sub getDescription {
|
return &Apache::lonhtmlcommon::direct_parm_link(&mt("Not currently assigned.",$res->symb(),'opendate'),$part); |
return &Apache::lonhtmlcommon::direct_parm_link(&mt("Not currently assigned.",$res->symb(),'opendate'),$part); |
} |
} |
if ($status == $res->OPEN_LATER) { |
if ($status == $res->OPEN_LATER) { |
return &mt("Open ") .&Apache::lonhtmlcommon::direct_parm_link(&timeToHumanString($open,'start'),$res->symb(),'opendate',$part); |
return &mt("Open [_1]",&Apache::lonhtmlcommon::direct_parm_link(&timeToHumanString($open,'start'),$res->symb(),'opendate',$part)); |
} |
} |
if ($res->simpleStatus($part) == $res->OPEN) { |
if ($res->simpleStatus($part) == $res->OPEN) { |
unless (&Apache::lonnet::allowed('mgr',$env{'request.course.id'})) { |
unless (&Apache::lonnet::allowed('mgr',$env{'request.course.id'})) { |
Line 629 sub getDescription {
|
Line 632 sub getDescription {
|
return &mt('Reserved - next open [_1]', |
return &mt('Reserved - next open [_1]', |
timeToHumanString($slot_time,'start')); |
timeToHumanString($slot_time,'start')); |
} elsif ($slot_status == $res->RESERVABLE) { |
} elsif ($slot_status == $res->RESERVABLE) { |
return &mt('Reservable ending [_1]', |
return &mt('Reservable, reservations close [_1]', |
timeToHumanString($slot_time,'end')); |
timeToHumanString($slot_time,'end')); |
} elsif ($slot_status == $res->RESERVABLE_LATER) { |
} elsif ($slot_status == $res->RESERVABLE_LATER) { |
return &mt('Reservable starting [_1]', |
return &mt('Reservable, reservations open [_1]', |
timeToHumanString($slot_time,'start')); |
timeToHumanString($slot_time,'start')); |
} elsif ($slot_status == $res->NOT_IN_A_SLOT) { |
} elsif ($slot_status == $res->NOT_IN_A_SLOT) { |
return &mt('Reserve a time/place to work'); |
return &mt('Reserve a time/place to work'); |
Line 646 sub getDescription {
|
Line 649 sub getDescription {
|
if ($status == $res->OPEN) { |
if ($status == $res->OPEN) { |
if ($due) { |
if ($due) { |
if ($res->is_practice()) { |
if ($res->is_practice()) { |
return &mt("Closes ")." " .&Apache::lonhtmlcommon::direct_parm_link(&timeToHumanString($due,'start'),$res->symb(),'duedate',$part); |
return &mt("Closes [_1]",&Apache::lonhtmlcommon::direct_parm_link(&timeToHumanString($due,'start'),$res->symb(),'duedate',$part)); |
} else { |
} else { |
return &mt("Due")." " .&Apache::lonhtmlcommon::direct_parm_link(&timeToHumanString($due,'end'),$res->symb(),'duedate',$part); |
return &mt("Due [_1]",&Apache::lonhtmlcommon::direct_parm_link(&timeToHumanString($due,'end'),$res->symb(),'duedate',$part)); |
} |
} |
} else { |
} else { |
return &Apache::lonhtmlcommon::direct_parm_link(&mt("Open, no due date"),$res->symb(),'duedate',$part); |
return &Apache::lonhtmlcommon::direct_parm_link(&mt("Open, no due date"),$res->symb(),'duedate',$part); |
} |
} |
} |
} |
if ($status == $res->PAST_DUE_ANSWER_LATER) { |
if ($status == $res->PAST_DUE_ANSWER_LATER) { |
return &mt("Answer open")." " .&Apache::lonhtmlcommon::direct_parm_link(&timeToHumanString($answer,'start'),$res->symb(),'answerdate',$part); |
return &mt("Answer open [_1]",&Apache::lonhtmlcommon::direct_parm_link(&timeToHumanString($answer,'start'),$res->symb(),'answerdate',$part)); |
} |
} |
if ($status == $res->PAST_DUE_NO_ANSWER) { |
if ($status == $res->PAST_DUE_NO_ANSWER) { |
if ($res->is_practice()) { |
if ($res->is_practice()) { |
return &mt("Closed")." " . &Apache::lonhtmlcommon::direct_parm_link(&timeToHumanString($due,'start'),$res->symb(),'answerdate,duedate',$part); |
return &mt("Closed [_1]",&Apache::lonhtmlcommon::direct_parm_link(&timeToHumanString($due,'start'),$res->symb(),'answerdate,duedate',$part)); |
} else { |
} else { |
return &mt("Was due")." " .&Apache::lonhtmlcommon::direct_parm_link(&timeToHumanString($due,'end'),$res->symb(),'answerdate,duedate',$part); |
return &mt("Was due [_1]",&Apache::lonhtmlcommon::direct_parm_link(&timeToHumanString($due,'end'),$res->symb(),'answerdate,duedate',$part)); |
} |
} |
} |
} |
if (($status == $res->ANSWER_OPEN || $status == $res->PARTIALLY_CORRECT) |
if (($status == $res->ANSWER_OPEN || $status == $res->PARTIALLY_CORRECT) |
Line 694 sub getDescription {
|
Line 697 sub getDescription {
|
} |
} |
} |
} |
if ($due) { |
if ($due) { |
return &mt("Due")." " . &Apache::lonhtmlcommon::direct_parm_link(&timeToHumanString($due,'end'),$res->symb(),'duedate',$part) . |
return &mt("Due [_1]",&Apache::lonhtmlcommon::direct_parm_link(&timeToHumanString($due,'end'),$res->symb(),'duedate',$part)) . |
" $triesString"; |
" $triesString"; |
} else { |
} else { |
return &Apache::lonhtmlcommon::direct_parm_link(&mt("No due date"),$res->symb(),'duedate',$part)." $triesString"; |
return &Apache::lonhtmlcommon::direct_parm_link(&mt("No due date"),$res->symb(),'duedate',$part)." $triesString"; |
Line 779 sub timeToHumanString {
|
Line 782 sub timeToHumanString {
|
|
|
# Less than an hour |
# Less than an hour |
if ( $delta < $hour ) { |
if ( $delta < $hour ) { |
# If so, use minutes |
# If so, use minutes; or minutes, seconds (if format requires) |
my $minutes = floor($delta / 60); |
my $minutes = floor($delta / 60); |
|
if (($format ne '') && ($format =~ /\%(T|S)/)) { |
|
my $display; |
|
if ($minutes == 1) { |
|
$display = "${prefix}1 minute"; |
|
} else { |
|
$display = "$prefix$minutes minutes"; |
|
} |
|
my $seconds = $delta % $minute; |
|
if ($seconds == 0) { |
|
$display .= $tense; |
|
} elsif ($seconds == 1) { |
|
$display .= ", 1 second$tense"; |
|
} else { |
|
$display .= ", $seconds seconds$tense"; |
|
} |
|
return $display; |
|
} |
if ($minutes == 1) { return "${prefix}1 minute$tense"; } |
if ($minutes == 1) { return "${prefix}1 minute$tense"; } |
return "$prefix$minutes minutes$tense"; |
return "$prefix$minutes minutes$tense"; |
} |
} |
|
|
# Is it less than 24 hours away? If so, |
# Is it less than 24 hours away? If so, |
# display hours + minutes |
# display hours + minutes, (and + seconds, if format specified it) |
if ( $delta < $hour * 24) { |
if ( $delta < $hour * 24) { |
my $hours = floor($delta / $hour); |
my $hours = floor($delta / $hour); |
my $minutes = floor(($delta % $hour) / $minute); |
my $minutes = floor(($delta % $hour) / $minute); |
Line 801 sub timeToHumanString {
|
Line 821 sub timeToHumanString {
|
if ($minutes == 0) { |
if ($minutes == 0) { |
$minuteString = ""; |
$minuteString = ""; |
} |
} |
|
if (($format ne '') && ($format =~ /\%(T|S)/)) { |
|
my $display = "$prefix$hourString$minuteString"; |
|
my $seconds = $delta-(($hours * $hour)+($minutes * $minute)); |
|
if ($seconds == 0) { |
|
$display .= $tense; |
|
} elsif ($seconds == 1) { |
|
$display .= ", 1 second$tense"; |
|
} else { |
|
$display .= ", $seconds seconds$tense"; |
|
} |
|
return $display; |
|
} |
return "$prefix$hourString$minuteString$tense"; |
return "$prefix$hourString$minuteString$tense"; |
} |
} |
|
|
|
# Date/time is more than 24 hours away |
|
|
my $dt = DateTime->from_epoch(epoch => $time) |
my $dt = DateTime->from_epoch(epoch => $time) |
->set_time_zone(&Apache::lonlocal::gettimezone()); |
->set_time_zone(&Apache::lonlocal::gettimezone()); |
|
|
# If there's a caller supplied format, use it. |
# If there's a caller supplied format, use it, unless it only displays |
|
# H:M:S or H:M. |
|
|
if ($format ne '') { |
if (($format ne '') && ($format ne '%T') && ($format ne '%R')) { |
my $timeStr = $dt->strftime($format); |
my $timeStr = $dt->strftime($format); |
return $timeStr.' ('.$dt->time_zone_short_name().')'; |
return $timeStr.' ('.$dt->time_zone_short_name().')'; |
} |
} |
Line 975 sub render_resource {
|
Line 1010 sub render_resource {
|
# Is this the current resource? |
# Is this the current resource? |
if (!$params->{'displayedHereMarker'} && |
if (!$params->{'displayedHereMarker'} && |
$resource->symb() eq $params->{'here'} ) { |
$resource->symb() eq $params->{'here'} ) { |
$curMarkerBegin = '<em>'; |
$curMarkerBegin = '<span class="LC_current_nav_location">'; |
$curMarkerEnd = '</em>'; |
$curMarkerEnd = '</span>'; |
$params->{'displayedHereMarker'} = 1; |
$params->{'displayedHereMarker'} = 1; |
} |
} |
|
|
Line 1090 sub render_long_status {
|
Line 1125 sub render_long_status {
|
} |
} |
} |
} |
|
|
if (($resource->kind() eq "res" && |
if ($resource->kind() eq "res" && |
($resource->is_problem() || $resource->is_practice()) && |
$resource->is_raw_problem() && |
!$firstDisplayed) && |
!$firstDisplayed) { |
$resource->is_raw_problem()) { |
|
if ($color) {$result .= "<font color=\"$color\"><b>"; } |
if ($color) {$result .= "<font color=\"$color\"><b>"; } |
$result .= getDescription($resource, $part); |
$result .= getDescription($resource, $part); |
if ($color) {$result .= "</b></font>"; } |
if ($color) {$result .= "</b></font>"; } |
} |
} |
|
if ($resource->is_map()) { |
|
if (&Apache::lonnet::allowed('mdc')) { |
|
if ($resource->symb=~/\_\_\_[^\_]+\_\_\_uploaded/) { |
|
$result.=" <a href='/adm/coursedocs?command=direct&symb=".&escape($resource->symb())."'>". |
|
"<span class='LC_setting'>".&mt("Edit Content").'</span></a> '; |
|
} |
|
} |
|
} |
if ($resource->is_map() && &advancedUser() && $resource->randompick()) { |
if ($resource->is_map() && &advancedUser() && $resource->randompick()) { |
$result .= &mt('(randomly select [_1])', $resource->randompick()); |
$result .= &mt('(randomly select [_1])', $resource->randompick()); |
} |
} |
Line 1352 sub render {
|
Line 1394 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 |
# Note this does not take filtering or hidden into account... need |
# to be fixed? |
# to be fixed? |
Line 1604 END
|
Line 1647 END
|
$curRes = shift(@resources); |
$curRes = shift(@resources); |
} else { |
} else { |
$curRes = $it->next($closeAllPages); |
$curRes = $it->next($closeAllPages); |
|
|
} |
} |
if (!$curRes) { last; } |
if (!$curRes) { last; } |
|
|
Line 1930 sub new {
|
Line 1974 sub new {
|
my $proto = shift; |
my $proto = shift; |
my $class = ref($proto) || $proto; |
my $class = ref($proto) || $proto; |
my $self = {}; |
my $self = {}; |
|
bless($self); # So we can call change_user if neceesary |
|
|
$self->{USERNAME} = shift || $env{'user.name'}; |
$self->{USERNAME} = shift || $env{'user.name'}; |
$self->{DOMAIN} = shift || $env{'user.domain'}; |
$self->{DOMAIN} = shift || $env{'user.domain'}; |
|
|
|
|
|
|
# Resource cache stores navmap resources as we reference them. We generate |
# Resource cache stores navmap resources as we reference them. We generate |
# them on-demand so we don't pay for creating resources unless we use them. |
# them on-demand so we don't pay for creating resources unless we use them. |
$self->{RESOURCE_CACHE} = {}; |
$self->{RESOURCE_CACHE} = {}; |
Line 1942 sub new {
|
Line 1989 sub new {
|
# failed |
# failed |
$self->{NETWORK_FAILURE} = 0; |
$self->{NETWORK_FAILURE} = 0; |
|
|
# tie the nav hash |
# We can only tie the nav hash as done below if the username/domain |
|
# match the env one. Otherwise change_user does everything we need...since we can't |
|
# assume there are course hashes for the specific requested user@domamin: |
|
# |
|
|
my %navmaphash; |
if ( ($self->{USERNAME} eq $env{'user.name'}) && ($self->{DOMAIN} eq $env{'user.domain'})) { |
my %parmhash; |
|
my $courseFn = $env{"request.course.fn"}; |
# tie the nav hash |
if (!(tie(%navmaphash, 'GDBM_File', "${courseFn}.db", |
|
&GDBM_READER(), 0640))) { |
my %navmaphash; |
return undef; |
my %parmhash; |
} |
my $courseFn = $env{"request.course.fn"}; |
|
if (!(tie(%navmaphash, 'GDBM_File', "${courseFn}.db", |
if (!(tie(%parmhash, 'GDBM_File', "${courseFn}_parms.db", |
&GDBM_READER(), 0640))) { |
&GDBM_READER(), 0640))) |
return undef; |
{ |
} |
untie %{$self->{PARM_HASH}}; |
|
return undef; |
if (!(tie(%parmhash, 'GDBM_File', "${courseFn}_parms.db", |
|
&GDBM_READER(), 0640))) |
|
{ |
|
untie %{$self->{PARM_HASH}}; |
|
return undef; |
|
} |
|
|
|
$self->{NAV_HASH} = \%navmaphash; |
|
$self->{PARM_HASH} = \%parmhash; |
|
$self->{PARM_CACHE} = {}; |
|
} else { |
|
$self->change_user($self->{USERNAME}, $self->{DOMAIN}); |
} |
} |
|
|
$self->{NAV_HASH} = \%navmaphash; |
my $d = Data::Dumper->new([$self]); |
$self->{PARM_HASH} = \%parmhash; |
|
$self->{PARM_CACHE} = {}; |
|
|
|
bless($self); |
|
|
|
return $self; |
return $self; |
} |
} |
|
|
|
# |
|
# In some instances it is useful to be able to dynamically change the |
|
# username/domain associated with a navmap (e.g. to navigate for someone |
|
# else besides the current user...if sufficiently privileged. |
|
# Parameters: |
|
# user - New user. |
|
# domain- Domain the user belongs to. |
|
# Implicit inputs: |
|
# |
|
sub change_user { |
|
my $self = shift; |
|
$self->{USERNAME} = shift; |
|
$self->{DOMAIN} = shift; |
|
|
|
# If the hashes are already tied make sure to break that bond: |
|
|
|
untie %{$self->{NAV_HASH}}; |
|
untie %{$self->{PARM_HASH}}; |
|
|
|
# The assumption is that we have to |
|
# use lonmap here to re-read the hash and from it reconstruct |
|
# new big and parameter hashes. An implicit assumption at this time |
|
# is that the course file is probably not created locally yet |
|
# an that we will therefore just read without tying. |
|
|
|
my ($cdom, $cnum) = split(/\_/, $env{'request.course.id'}); |
|
|
|
my %big_hash; |
|
&Apache::lonmap::loadmap($cnum, $cdom, $self->{USERNAME}, $self->{DOMAIN}, \%big_hash); |
|
$self->{NAV_HASH} = \%big_hash; |
|
|
|
|
|
|
|
# Now clear the parm cache and reconstruct the parm hash fromt he big_hash |
|
# param.xxxx keys. |
|
|
|
$self->{PARM_CACHE} = {}; |
|
|
|
my %parm_hash = {}; |
|
foreach my $key (keys %big_hash) { |
|
if ($key =~ /^param\./) { |
|
my $param_key = $key; |
|
$param_key =~ s/^param\.//; |
|
$parm_hash{$param_key} = $big_hash{$key}; |
|
} |
|
} |
|
|
|
$self->{PARM_HASH} = \%parm_hash; |
|
|
|
|
|
|
|
|
|
} |
|
|
sub generate_course_user_opt { |
sub generate_course_user_opt { |
my $self = shift; |
my $self = shift; |
if ($self->{COURSE_USER_OPT_GENERATED}) { return; } |
if ($self->{COURSE_USER_OPT_GENERATED}) { return; } |
Line 2955 sub new {
|
Line 3066 sub new {
|
if ($resourceCount == 1 && $resource->is_sequence() && !$self->{FORCE_TOP}) { |
if ($resourceCount == 1 && $resource->is_sequence() && !$self->{FORCE_TOP}) { |
my $firstResource = $resource->map_start(); |
my $firstResource = $resource->map_start(); |
my $finishResource = $resource->map_finish(); |
my $finishResource = $resource->map_finish(); |
return |
my $result; |
Apache::lonnavmaps::iterator->new($self->{NAV_MAP}, $firstResource, |
my $rdump = Data::Dumper->new([$result]); |
$finishResource, $self->{FILTER}, |
$result = Apache::lonnavmaps::iterator->new($self->{NAV_MAP}, $firstResource, |
$self->{ALREADY_SEEN}, |
$finishResource, $self->{FILTER}, |
$self->{CONDITION}, |
$self->{ALREADY_SEEN}, |
$self->{FORCE_TOP}); |
$self->{CONDITION}, |
|
$self->{FORCE_TOP}); |
|
return $result; |
|
|
|
|
} |
} |
|
|
Line 2980 sub new {
|
Line 3094 sub new {
|
$self->{ALREADY_SEEN}->{$self->{FIRST_RESOURCE}->{ID}} = 1; |
$self->{ALREADY_SEEN}->{$self->{FIRST_RESOURCE}->{ID}} = 1; |
|
|
bless ($self); |
bless ($self); |
|
my $selfDump = Data::Dumper->new([$self]); |
|
|
return $self; |
return $self; |
} |
} |
Line 2995 sub next {
|
Line 3110 sub next {
|
# do so. |
# do so. |
if ($self->{RETURN_0} && !$self->{HAVE_RETURNED_0}) { |
if ($self->{RETURN_0} && !$self->{HAVE_RETURNED_0}) { |
$self->{HAVE_RETURNED_0} = 1; |
$self->{HAVE_RETURNED_0} = 1; |
|
my $nextTopLevel = $self->{NAV_MAP}->getById('0.0'); |
|
|
return $self->{NAV_MAP}->getById('0.0'); |
return $self->{NAV_MAP}->getById('0.0'); |
} |
} |
if ($self->{RETURN_0} && !$self->{HAVE_RETURNED_0_BEGIN_MAP}) { |
if ($self->{RETURN_0} && !$self->{HAVE_RETURNED_0_BEGIN_MAP}) { |
Line 3014 sub next {
|
Line 3131 sub next {
|
if ($self->{RECURSIVE_DEPTH} == 0) { |
if ($self->{RECURSIVE_DEPTH} == 0) { |
$self->{RECURSIVE_ITERATOR_FLAG} = 0; |
$self->{RECURSIVE_ITERATOR_FLAG} = 0; |
} |
} |
|
|
return $next; |
return $next; |
} |
} |
|
|
if (defined($self->{FORCE_NEXT})) { |
if (defined($self->{FORCE_NEXT})) { |
my $tmp = $self->{FORCE_NEXT}; |
my $tmp = $self->{FORCE_NEXT}; |
$self->{FORCE_NEXT} = undef; |
$self->{FORCE_NEXT} = undef; |
|
|
return $tmp; |
return $tmp; |
} |
} |
|
|
Line 3090 sub next {
|
Line 3207 sub next {
|
# So we need to look at all the resources we can get to from here, |
# So we need to look at all the resources we can get to from here, |
# categorize them if we haven't seen them, remember if we have a new |
# categorize them if we haven't seen them, remember if we have a new |
my $nextUnfiltered = $here->getNext(); |
my $nextUnfiltered = $here->getNext(); |
|
|
|
|
my $maxDepthAdded = -1; |
my $maxDepthAdded = -1; |
|
|
for (@$nextUnfiltered) { |
for (@$nextUnfiltered) { |
Line 3123 sub next {
|
Line 3242 sub next {
|
$self->{RECURSIVE_ITERATOR_FLAG} = 1; |
$self->{RECURSIVE_ITERATOR_FLAG} = 1; |
my $firstResource = $self->{HERE}->map_start(); |
my $firstResource = $self->{HERE}->map_start(); |
my $finishResource = $self->{HERE}->map_finish(); |
my $finishResource = $self->{HERE}->map_finish(); |
|
|
$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}, |
$finishResource, $self->{FILTER}, |
Line 3141 sub next {
|
Line 3259 sub next {
|
return $self->next($closeAllPages); |
return $self->next($closeAllPages); |
} |
} |
|
|
|
my $hereResource = $self->{HERE}; |
|
|
return $self->{HERE}; |
return $self->{HERE}; |
|
|
} |
} |
Line 3307 sub next {
|
Line 3427 sub next {
|
my $nextUnfiltered; |
my $nextUnfiltered; |
if ($self->{DIRECTION} == FORWARD()) { |
if ($self->{DIRECTION} == FORWARD()) { |
$nextUnfiltered = $self->{HERE}->getNext(); |
$nextUnfiltered = $self->{HERE}->getNext(); |
|
|
} else { |
} else { |
$nextUnfiltered = $self->{HERE}->getPrevious(); |
$nextUnfiltered = $self->{HERE}->getPrevious(); |
} |
} |
Line 3720 sub is_practice {
|
Line 3841 sub is_practice {
|
sub is_problem { |
sub is_problem { |
my $self=shift; |
my $self=shift; |
my $src = $self->src(); |
my $src = $self->src(); |
if ($src =~ /\.(problem|exam|quiz|assess|survey|form|library|task)$/) { |
if ($src =~ /$LONCAPA::assess_re/) { |
return !($self->is_practice()); |
return !($self->is_practice()); |
} |
} |
return 0; |
return 0; |
Line 3755 sub is_incomplete {
|
Line 3876 sub is_incomplete {
|
sub is_raw_problem { |
sub is_raw_problem { |
my $self=shift; |
my $self=shift; |
my $src = $self->src(); |
my $src = $self->src(); |
if ($src =~ /\.(problem|exam|quiz|assess|survey|form|library|task)$/) { |
if ($src =~ /$LONCAPA::assess_re/) { |
return 1; |
return 1; |
} |
} |
return 0; |
return 0; |
Line 3993 Get the weight for the problem.
|
Line 4114 Get the weight for the problem.
|
|
|
sub printable { |
sub printable { |
|
|
&Apache::lonnet::logthis("Printable"); |
|
my ($self, $part) = @_; |
my ($self, $part) = @_; |
|
|
# Get the print open/close dates for the resource. |
# Get the print open/close dates for the resource. |
Line 4008 sub printable {
|
Line 4128 sub printable {
|
# - both defined: printable if start <= now <= end |
# - both defined: printable if start <= now <= end |
# |
# |
my $now = time(); |
my $now = time(); |
&Apache::lonnet::logthis("now: $now, Opens at $start Closes at $end"); |
|
|
|
my $startok = 1; |
my $startok = 1; |
my $endok = 1; |
my $endok = 1; |
|
|
if ((defined $start) && ($start ne '')) { |
if ((defined $start) && ($start ne '')) { |
&Apache::lonnet::logthis("checking start time."); |
|
$startok = $start <= $now; |
$startok = $start <= $now; |
if (!$startok) { |
|
&Apache::lonnet::logthis("Start date is after now"); |
|
} |
|
} |
} |
if ((defined $end) && ($end != '')) { |
if ((defined $end) && ($end != '')) { |
&Apache::lonnet::logthis("checkin end time"); |
|
$endok = $end >= $now; |
$endok = $end >= $now; |
if (!$endok) { |
|
&Apache::lonnet::logthis("End date is prior to now"); |
|
} |
|
} |
} |
if (!($startok && $endok)) { |
|
&Apache::lonnet::logthis("Resource not printable due to open/close date"); |
|
} |
|
return $startok && $endok; |
return $startok && $endok; |
} |
} |
|
|
Line 4042 sub resprintable {
|
Line 4150 sub resprintable {
|
my @parts = @$partsref; |
my @parts = @$partsref; |
|
|
if ((!defined(@parts)) || (scalar(@parts) == 0)) { |
if ((!defined(@parts)) || (scalar(@parts) == 0)) { |
&Apache::lonnet::logthis("resprintable - no parts trying part 0"); |
|
return $self->printable(0); |
return $self->printable(0); |
} else { |
} else { |
&Apache::lonnet::logthis("resprintable - have " . scalar(@parts) . " parts require all to be good"); |
|
foreach my $part (@parts) { |
foreach my $part (@parts) { |
if (!$self->printable($part)) { |
if (!$self->printable($part)) { |
&Apache::lonnet::logthis("resprintable - one of the parts failed date check"); |
|
return 0; |
return 0; |
} |
} |
} |
} |
&Apache::lonnet::logthis("resprintable - All parts passed date check"); |
|
return 1; |
return 1; |
} |
} |
&Apache::lonnet::logthis("resprintable - should not have gotten here?"); |
|
} |
} |
|
|
sub acc { |
sub acc { |
Line 4984 sub status {
|
Line 5087 sub status {
|
} |
} |
|
|
# Otherwise, it's untried and open |
# Otherwise, it's untried and open |
return OPEN; |
return OPEN; |
} |
} |
|
|
sub check_for_slot { |
sub check_for_slot { |
my $self = shift; |
my $self = shift; |
my $part = shift; |
my $part = shift; |
|
my $symb = $self->symb(); |
my ($use_slots,$available,$availablestudent) = $self->slot_control($part); |
my ($use_slots,$available,$availablestudent) = $self->slot_control($part); |
if (($use_slots ne '') && ($use_slots !~ /^\s*no\s*$/i)) { |
if (($use_slots ne '') && ($use_slots !~ /^\s*no\s*$/i)) { |
my @slots = (split(/:/,$availablestudent),split(/:/,$available)); |
my @slots = (split(/:/,$availablestudent),split(/:/,$available)); |
Line 4997 sub check_for_slot {
|
Line 5101 sub check_for_slot {
|
my $cdom=$env{'course.'.$cid.'.domain'}; |
my $cdom=$env{'course.'.$cid.'.domain'}; |
my $cnum=$env{'course.'.$cid.'.num'}; |
my $cnum=$env{'course.'.$cid.'.num'}; |
my $now = time; |
my $now = time; |
|
my $num_usable_slots = 0; |
if (@slots > 0) { |
if (@slots > 0) { |
my %slots=&Apache::lonnet::get('slots',[@slots],$cdom,$cnum); |
my %slots=&Apache::lonnet::get('slots',[@slots],$cdom,$cnum); |
if (&Apache::lonnet::error(%slots)) { |
if (&Apache::lonnet::error(%slots)) { |
return (UNKNOWN); |
return (UNKNOWN); |
} |
} |
my @sorted_slots = &Apache::loncommon::sorted_slots(\@slots,\%slots); |
my @sorted_slots = &Apache::loncommon::sorted_slots(\@slots,\%slots,'starttime'); |
my ($checkedin,$checkedinslot); |
my ($checkedin,$checkedinslot); |
foreach my $slot_name (@sorted_slots) { |
foreach my $slot_name (@sorted_slots) { |
next if (!defined($slots{$slot_name}) || |
next if (!defined($slots{$slot_name}) || !ref($slots{$slot_name})); |
!ref($slots{$slot_name})); |
|
my $end = $slots{$slot_name}->{'endtime'}; |
my $end = $slots{$slot_name}->{'endtime'}; |
my $start = $slots{$slot_name}->{'starttime'}; |
my $start = $slots{$slot_name}->{'starttime'}; |
my $ip = $slots{$slot_name}->{'ip'}; |
my $ip = $slots{$slot_name}->{'ip'}; |
if ($self->simpleStatus() == OPEN) { |
if ($self->simpleStatus() == OPEN) { |
my $startreserve = $slots{$slot_name}->{'startreserve'}; |
|
my @proctors; |
|
if ($slots{$slot_name}->{'proctor'} ne '') { |
|
@proctors = split(',',$slots{$slot_name}->{'proctor'}); |
|
} |
|
if ($end > $now) { |
if ($end > $now) { |
($checkedin,$checkedinslot) = $self->checkedin(); |
if ($start > $now) { |
if ($startreserve < $now) { |
return (RESERVED_LATER,$start,$slot_name); |
if ($start > $now) { |
} else { |
return (RESERVED_LATER,$start,$slot_name); |
if ($ip ne '') { |
} else { |
if (!&Apache::loncommon::check_ip_acc($ip)) { |
if ($ip ne '') { |
return (RESERVED_LOCATION,$ip,$slot_name); |
if (!&Apache::loncommon::check_ip_acc($ip)) { |
|
return (RESERVED_LOCATION,$ip,$slot_name); |
|
} |
|
} |
|
if (@proctors > 0) { |
|
unless ((grep(/^\Q$checkedin\E/,@proctors)) && |
|
($checkedinslot eq $slot_name)) { |
|
return (NEEDS_CHECKIN,undef,$slot_name); |
|
} |
|
} |
} |
return (RESERVED,$end,$slot_name); |
|
} |
} |
} else { |
my @proctors; |
if ($start > $now) { |
if ($slots{$slot_name}->{'proctor'} ne '') { |
return (RESERVABLE,$startreserve,$slot_name); |
@proctors = split(',',$slots{$slot_name}->{'proctor'}); |
|
} |
|
if (@proctors > 0) { |
|
($checkedin,$checkedinslot) = $self->checkedin(); |
|
unless ((grep(/^\Q$checkedin\E/,@proctors)) && |
|
($checkedinslot eq $slot_name)) { |
|
return (NEEDS_CHECKIN,undef,$slot_name); |
|
} |
} |
} |
|
return (RESERVED,$end,$slot_name); |
} |
} |
} |
} |
|
} elsif ($end > $now) { |
|
$num_usable_slots ++; |
} |
} |
} |
} |
my ($is_correct,$got_grade); |
my ($is_correct,$got_grade); |
Line 5061 sub check_for_slot {
|
Line 5160 sub check_for_slot {
|
return (CORRECT); |
return (CORRECT); |
} |
} |
} |
} |
return(NOT_IN_A_SLOT); |
if ($num_usable_slots) { |
} else { |
|
if (!$future_slots_checked) { |
|
$future_slots = &get_future_slots($cdom,$cnum,$now); |
|
$future_slots_checked = 1; |
|
} |
|
if ($future_slots) { |
|
return(NOT_IN_A_SLOT); |
return(NOT_IN_A_SLOT); |
} |
} |
return(NOTRESERVABLE); |
|
} |
} |
} |
my $reservable = &Apache::lonnet::get_reservable_slots($cnum,$cdom,$env{'user.name'}, |
return; |
$env{'user.domain'}); |
} |
if (ref($reservable) eq 'HASH') { |
|
if ((ref($reservable->{'now_order'}) eq 'ARRAY') && (ref($reservable->{'now'}) eq 'HASH')) { |
sub get_future_slots { |
foreach my $slot (reverse (@{$reservable->{'now_order'}})) { |
my ($cdom,$cnum,$now) = @_; |
if (($reservable->{'now'}{$slot}{'symb'} eq '') || |
my %slots=&Apache::lonnet::dump('slots',$cdom,$cnum); |
($reservable->{'now'}{$slot}{'symb'} eq $symb)) { |
my $future_slots = 0; |
return(RESERVABLE,$reservable->{'now'}{$slot}{'endreserve'}); |
foreach my $slot (keys(%slots)) { |
} |
if (($slots{$slot}->{'starttime'} > $now) && |
} |
($slots{$slot}->{'endtime'} > $now)) { |
} |
$future_slots ++; |
if ((ref($reservable->{'future_order'}) eq 'ARRAY') && (ref($reservable->{'future'}) eq 'HASH')) { |
|
foreach my $slot (@{$reservable->{'future_order'}}) { |
|
if (($reservable->{'future'}{$slot}{'symb'} eq '') || |
|
($reservable->{'future'}{$slot}{'symb'} eq $symb)) { |
|
return(RESERVABLE_LATER,$reservable->{'future'}{$slot}{'startreserve'}); |
|
} |
|
} |
|
} |
} |
} |
|
return(NOTRESERVABLE); |
} |
} |
return $future_slots; |
return; |
} |
} |
|
|
sub CLOSED { return 23; } |
sub CLOSED { return 23; } |