--- loncom/interface/lonnavmaps.pm 2011/09/22 12:48:40 1.464
+++ loncom/interface/lonnavmaps.pm 2012/05/28 10:31:17 1.485
@@ -1,7 +1,7 @@
# The LearningOnline Network with CAPA
# Navigate Maps Handler
#
-# $Id: lonnavmaps.pm,v 1.464 2011/09/22 12:48:40 raeburn Exp $
+# $Id: lonnavmaps.pm,v 1.485 2012/05/28 10:31:17 foxr Exp $
#
# Copyright Michigan State University Board of Trustees
@@ -464,7 +464,7 @@ returns 4
=item add_linkitem()
-=item show_linkitems()
+=item show_linkitems_toolbar()
=back
@@ -478,12 +478,18 @@ use Apache::loncommon();
use Apache::lonenc();
use Apache::lonlocal;
use Apache::lonnet;
+use Apache::lonmap;
use POSIX qw (floor strftime);
use Time::HiRes qw( gettimeofday tv_interval );
use LONCAPA;
use DateTime();
+
+# For debugging
+
use Data::Dumper;
+
+
# symbolic constants
sub SYMB { return 1; }
sub URL { return 2; }
@@ -536,9 +542,6 @@ my %colormap =
# is not yet done and due in less than 24 hours
my $hurryUpColor = "#FF0000";
-my $future_slots_checked = 0;
-my $future_slots = 0;
-
sub addToFilter {
my $hashIn = shift;
my $addition = shift;
@@ -612,7 +615,7 @@ sub getDescription {
return &Apache::lonhtmlcommon::direct_parm_link(&mt("Not currently assigned.",$res->symb(),'opendate'),$part);
}
if ($status == $res->OPEN_LATER) {
- return &mt("Open [_1]",&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) {
unless (&Apache::lonnet::allowed('mgr',$env{'request.course.id'})) {
@@ -629,10 +632,10 @@ sub getDescription {
return &mt('Reserved - next open [_1]',
timeToHumanString($slot_time,'start'));
} elsif ($slot_status == $res->RESERVABLE) {
- return &mt('Reservable ending [_1]',
+ return &mt('Reservable, reservations close [_1]',
timeToHumanString($slot_time,'end'));
} elsif ($slot_status == $res->RESERVABLE_LATER) {
- return &mt('Reservable starting [_1]',
+ return &mt('Reservable, reservations open [_1]',
timeToHumanString($slot_time,'start'));
} elsif ($slot_status == $res->NOT_IN_A_SLOT) {
return &mt('Reserve a time/place to work');
@@ -646,22 +649,22 @@ sub getDescription {
if ($status == $res->OPEN) {
if ($due) {
if ($res->is_practice()) {
- return &mt("Closes [_1]",&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 {
- return &mt("Due [_1]",&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 {
return &Apache::lonhtmlcommon::direct_parm_link(&mt("Open, no due date"),$res->symb(),'duedate',$part);
}
}
if ($status == $res->PAST_DUE_ANSWER_LATER) {
- return &mt("Answer open [_1]",&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 ($res->is_practice()) {
- return &mt("Closed [_1]",&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 {
- return &mt("Was due [_1]",&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)
@@ -694,7 +697,7 @@ sub getDescription {
}
}
if ($due) {
- return &mt("Due [_1]",&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";
} else {
return &Apache::lonhtmlcommon::direct_parm_link(&mt("No due date"),$res->symb(),'duedate',$part)." $triesString";
@@ -893,6 +896,7 @@ sub part_status_summary { return 4; }
sub render_resource {
my ($resource, $part, $params) = @_;
+ my $editmapLink;
my $nonLinkedText = ''; # stuff after resource title not in link
my $link = $params->{"resourceLink"};
@@ -974,6 +978,14 @@ sub render_resource {
$linkopen = "";
$linkclose = "";
}
+ if ((&Apache::lonnet::allowed('mdc',$env{'request.course.id'})) &&
+ ($resource->symb=~/\_\_\_[^\_]+\_\_\_uploaded/)) {
+ my $icon = &Apache::loncommon::lonhttpdurl('/res/adm/pages').'/editmap.png';
+ $editmapLink=' '.
+ ''.
+ '
'.
+ '';
+ }
}
if ($resource->randomout()) {
@@ -1007,8 +1019,10 @@ sub render_resource {
# Is this the current resource?
if (!$params->{'displayedHereMarker'} &&
$resource->symb() eq $params->{'here'} ) {
- $curMarkerBegin = '';
- $curMarkerEnd = '';
+ unless ($resource->is_map()) {
+ $curMarkerBegin = '';
+ $curMarkerEnd = '';
+ }
$params->{'displayedHereMarker'} = 1;
}
@@ -1027,7 +1041,7 @@ sub render_resource {
if (!$params->{'resource_nolink'} && !$resource->is_sequence() && !$resource->is_empty_sequence) {
$result .= "$curMarkerBegin$title$partLabel$curMarkerEnd$nonLinkedText";
} else {
- $result .= "$curMarkerBegin$linkopen$title$partLabel$curMarkerEnd$nonLinkedText";
+ $result .= "$curMarkerBegin$linkopen$title$partLabel$curMarkerEnd$editmapLink$nonLinkedText";
}
return $result;
@@ -1041,6 +1055,7 @@ sub render_communication_status {
my $linkopen = "";
my $linkclose = "";
my $location=&Apache::loncommon::lonhttpdurl("/adm/lonMisc");
+
if ($resource->hasDiscussion()) {
$discussionHTML = $linkopen .
'
' .
@@ -1450,8 +1465,10 @@ sub render {
$link .= '®ister='.$env{'form.register'};
}
if ($args->{'caller'} eq 'navmapsdisplay') {
- &add_linkitem($args->{'linkitems'},'changefolder',
- "location.href='$link'",$text);
+ unless ($args->{'notools'}) {
+ &add_linkitem($args->{'linkitems'},'changefolder',
+ "location.href='$link'",$text);
+ }
} else {
$result.= ''.&mt($text).'';
}
@@ -1459,7 +1476,7 @@ sub render {
}
# Check for any unread discussions in all resources.
- if ($args->{'caller'} eq 'navmapsdisplay') {
+ if (($args->{'caller'} eq 'navmapsdisplay') && (!$args->{'notools'})) {
&add_linkitem($args->{'linkitems'},'clearbubbles',
'document.clearbubbles.submit()',
'Mark all posts read');
@@ -1492,18 +1509,20 @@ END
}
$result.='';
}
+ if (($args->{'caller'} eq 'navmapsdisplay') &&
+ (&Apache::lonnet::allowed('mdc',$env{'request.course.id'}))) {
+ my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'};
+ my $cnum = $env{'course.'.$env{'request.course.id'}.'.num'};
+ if ($env{'course.'.$env{'request.course.id'}.'.url'} eq
+ "uploaded/$cdom/$cnum/default.sequence") {
+ &add_linkitem($args->{'linkitems'},'edittoplevel',
+ "javascript:gocmd('/adm/coursedocs','editdocs');",
+ 'Content Editor');
+ }
+ }
if ($args->{'caller'} eq 'navmapsdisplay') {
- $result .= '
'.
- &Apache::loncommon::help_open_menu('Navigation Screen','Navigation_Screen',undef,'RAT').' | ';
- $result .= ' | ';
- $result.=''.&mt('Tools:').' | ';
- $result.=&show_linkitems_toolbar($args->{'linkitems'});
- if ($args->{'sort_html'}) {
- $result.=' | | | '.
- ''.$args->{'sort_html'}.' |
';
- }
- $result .= '
';
+ $result .= &show_linkitems_toolbar($args,$condition);
} elsif ($args->{'sort_html'}) {
$result.=$args->{'sort_html'};
}
@@ -1840,41 +1859,65 @@ sub add_linkitem {
}
sub show_linkitems_toolbar {
- my ($linkitems,$condition)=@_;
- my @linkorder = ('firsthomework','everything','uncompleted',
- 'changefolder','clearbubbles');
- my $result .=''."\n".
- ''."\n".
- ''.
- ' | '."\n";
+ if ($result) {
+ $result = "";
+ }
return $result;
}
-
1;
@@ -1961,10 +2004,13 @@ sub new {
my $proto = shift;
my $class = ref($proto) || $proto;
my $self = {};
+ bless($self); # So we can call change_user if neceesary
$self->{USERNAME} = shift || $env{'user.name'};
$self->{DOMAIN} = shift || $env{'user.domain'};
+
+
# 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.
$self->{RESOURCE_CACHE} = {};
@@ -1973,31 +2019,92 @@ sub new {
# failed
$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;
- my %parmhash;
- my $courseFn = $env{"request.course.fn"};
- if (!(tie(%navmaphash, 'GDBM_File', "${courseFn}.db",
- &GDBM_READER(), 0640))) {
- return undef;
+ if (($self->{USERNAME} eq $env{'user.name'}) && ($self->{DOMAIN} eq $env{'user.domain'})) {
+
+ # tie the nav hash
+
+ my %navmaphash;
+ my %parmhash;
+ my $courseFn = $env{"request.course.fn"};
+ if (!(tie(%navmaphash, 'GDBM_File', "${courseFn}.db",
+ &GDBM_READER(), 0640))) {
+ 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});
}
+
+ 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} = {};
- if (!(tie(%parmhash, 'GDBM_File', "${courseFn}_parms.db",
- &GDBM_READER(), 0640)))
- {
- untie %{$self->{PARM_HASH}};
- return undef;
+ 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->{NAV_HASH} = \%navmaphash;
- $self->{PARM_HASH} = \%parmhash;
- $self->{PARM_CACHE} = {};
+ $self->{PARM_HASH} = \%parm_hash;
- bless($self);
-
- return $self;
-}
+
+
+}
sub generate_course_user_opt {
my $self = shift;
@@ -2039,6 +2146,8 @@ sub generate_course_user_opt {
return;
}
+
+
sub generate_email_discuss_status {
my $self = shift;
my $symb = shift;
@@ -2452,10 +2561,12 @@ sub parmval {
return $result->[0];
}
+
sub parmval_real {
my $self = shift;
my ($what,$symb,$recurse) = @_;
+
# Make sure the {USER_OPT} and {COURSE_OPT} hashes are populated
$self->generate_course_user_opt();
@@ -2484,18 +2595,23 @@ sub parmval_real {
my $mapparm=$mapname.'___(all).'.$what;
my $usercourseprefix=$cid;
+
+
my $grplevel=$usercourseprefix.'.['.$cgroup.'].'.$what;
my $grplevelr=$usercourseprefix.'.['.$cgroup.'].'.$symbparm;
my $grplevelm=$usercourseprefix.'.['.$cgroup.'].'.$mapparm;
+
my $seclevel= $usercourseprefix.'.['.$csec.'].'.$what;
my $seclevelr=$usercourseprefix.'.['.$csec.'].'.$symbparm;
my $seclevelm=$usercourseprefix.'.['.$csec.'].'.$mapparm;
+
my $courselevel= $usercourseprefix.'.'.$what;
my $courselevelr=$usercourseprefix.'.'.$symbparm;
my $courselevelm=$usercourseprefix.'.'.$mapparm;
+
my $useropt = $self->{USER_OPT};
my $courseopt = $self->{COURSE_OPT};
my $parmhash = $self->{PARM_HASH};
@@ -2562,6 +2678,217 @@ sub parmval_real {
if (defined($pack_def)) { return [$pack_def,'resource']; }
return [''];
}
+#
+# Determines the open/close dates for printing a map that
+# encloses a resource.
+#
+sub map_printdates {
+ my ($self, $res, $part) = @_;
+
+
+
+
+
+ my $opendate = $self->get_mapparam($res->symb(), "$part.printstartdate");
+ my $closedate= $self->get_mapparam($res->symb(), "$part.printenddate");
+
+
+ return ($opendate, $closedate);
+}
+
+sub get_mapparam {
+ my ($self, $symb, $what) = @_;
+
+ # Ensure the course option hash is populated:
+
+ $self->generate_course_user_opt();
+
+ # Get the course id and section if there is one.
+
+ my $cid=$env{'request.course.id'};
+ my $csec=$env{'request.course.sec'};
+ my $cgroup='';
+ my @cgrps=split(/:/,$env{'request.course.groups'});
+ if (@cgrps > 0) {
+ @cgrps = sort(@cgrps);
+ $cgroup = $cgrps[0];
+ }
+ my $uname=$self->{USERNAME};
+ my $udom=$self->{DOMAIN};
+
+ unless ($symb) { return ['']; }
+ my $result='';
+
+
+ # Figure out which map we are in.
+
+ my ($mapname,$id,$fn)=&Apache::lonnet::decode_symb($symb);
+ $mapname = &Apache::lonnet::deversion($mapname);
+
+
+ my $rwhat=$what;
+ $what=~s/^parameter\_//;
+ $what=~s/\_/\./;
+
+ # Build the hash keys for the lookup:
+
+ my $symbparm=$symb.'.'.$what;
+ my $mapparm=$mapname.'___(all).'.$what;
+ my $usercourseprefix=$cid;
+
+
+ my $grplevel = "$usercourseprefix.[$cgroup].$mapparm";
+ my $seclevel = "$usercourseprefix.[$csec].$mapparm";
+ my $courselevel = "$usercourseprefix.$mapparm";
+
+
+ # Get handy references to the hashes we need in $self:
+
+ my $useropt = $self->{USER_OPT};
+ my $courseopt = $self->{COURSE_OPT};
+ my $parmhash = $self->{PARM_HASH};
+
+ # Check per user
+
+
+
+ if ($uname and defined($useropt)) {
+ if (defined($$useropt{$courselevel})) {
+ return $$useropt{$courselevel};
+ }
+ }
+
+ # Check course -- group
+
+
+
+ if ($cgroup ne '' and defined ($courseopt)) {
+ if (defined($$courseopt{$grplevel})) {
+ return $$courseopt{$grplevel};
+ }
+ }
+
+ # Check course -- section
+
+
+
+
+
+ if ($csec and defined($courseopt)) {
+ if (defined($$courseopt{$seclevel})) {
+ return $$courseopt{$seclevel};
+ }
+ }
+ # Check the map parameters themselves:
+
+ my $thisparm = $$parmhash{$symbparm};
+ if (defined($thisparm)) {
+ return $thisparm;
+ }
+
+
+ # Additional course parameters:
+
+ if (defined($courseopt)) {
+ if (defined($$courseopt{$courselevel})) {
+ return $$courseopt{$courselevel};
+ }
+ }
+ return undef; # Unefined if we got here.
+}
+
+sub course_printdates {
+ my ($self, $symb, $part) = @_;
+
+
+ my $opendate = $self->getcourseparam($symb, $part . '.printstartdate');
+ my $closedate = $self->getcourseparam($symb, $part . '.printenddate');
+ return ($opendate, $closedate);
+
+}
+
+sub getcourseparam {
+ my ($self, $symb, $what) = @_;
+
+ $self->generate_course_user_opt(); # If necessary populate the hashes.
+
+ my $uname = $self->{USERNAME};
+ my $udom = $self->{DOMAIN};
+
+ # Course, section, group ids come from the env:
+
+ my $cid = $env{'request.course.id'};
+ my $csec = $env{'request.course.sec'};
+ my $cgroup = ''; # Assume no group
+
+ my @cgroups = split(/:/, $env{'request.course.groups'});
+ if(@cgroups > 0) {
+ @cgroups = sort(@cgroups);
+ $cgroup = $cgroups[0]; # There is a course group.
+ }
+ my ($mapname,$id,$fn)=&Apache::lonnet::decode_symb($symb);
+ $mapname = &Apache::lonnet::deversion($mapname);
+
+ #
+ # Make the various lookup keys:
+ #
+
+ $what=~s/^parameter\_//;
+ $what=~s/\_/\./;
+
+
+ my $symbparm = $symb . '.' . $what;
+ my $mapparm=$mapname.'___(all).'.$what;
+
+ # Local refs to the hashes we're going to look at:
+
+ my $useropt = $self->{USER_OPT};
+ my $courseopt = $self->{COURSE_OPT};
+
+ #
+ # We want the course level stuff from the way
+ # parmval_real operates
+ # TODO: Fator some of this stuff out of
+ # both parmval_real and here
+ #
+ my $courselevel = $cid . '.' . $what;
+ my $grplevel = $cid . '.[' . $cgroup . ']' . $what;
+ my $seclevel = $cid . '.[' . $csec . ']' . $what;
+
+
+ # Try for the user's course level option:
+
+ if ($uname and defined($useropt)) {
+ if (defined($$useropt{$courselevel})) {
+ return $$useropt{$courselevel};
+ }
+ }
+ # Try for the group's course level option:
+
+ if ($uname ne '' and defined($courseopt)) {
+ if (defined($$courseopt{$grplevel})) {
+ return $$courseopt{$grplevel};
+ }
+ }
+
+ # Try for section level parameters:
+
+ if ($csec and defined($courseopt)) {
+ if (defined($$courseopt{$seclevel})) {
+ return $$courseopt{$seclevel};
+ }
+ }
+ # Try for 'additional' course parameterse:
+
+ if (defined($courseopt)) {
+ if (defined($$courseopt{$courselevel})) {
+ return $$courseopt{$courselevel};
+ }
+ }
+ return undef;
+
+}
+
=pod
@@ -2986,12 +3313,14 @@ sub new {
if ($resourceCount == 1 && $resource->is_sequence() && !$self->{FORCE_TOP}) {
my $firstResource = $resource->map_start();
my $finishResource = $resource->map_finish();
- return
- Apache::lonnavmaps::iterator->new($self->{NAV_MAP}, $firstResource,
- $finishResource, $self->{FILTER},
- $self->{ALREADY_SEEN},
- $self->{CONDITION},
- $self->{FORCE_TOP});
+ my $result;
+ $result = Apache::lonnavmaps::iterator->new($self->{NAV_MAP}, $firstResource,
+ $finishResource, $self->{FILTER},
+ $self->{ALREADY_SEEN},
+ $self->{CONDITION},
+ $self->{FORCE_TOP});
+ return $result;
+
}
@@ -3011,7 +3340,6 @@ sub new {
$self->{ALREADY_SEEN}->{$self->{FIRST_RESOURCE}->{ID}} = 1;
bless ($self);
-
return $self;
}
@@ -3026,6 +3354,7 @@ sub next {
# do so.
if ($self->{RETURN_0} && !$self->{HAVE_RETURNED_0}) {
$self->{HAVE_RETURNED_0} = 1;
+ my $nextTopLevel = $self->{NAV_MAP}->getById('0.0');
return $self->{NAV_MAP}->getById('0.0');
}
if ($self->{RETURN_0} && !$self->{HAVE_RETURNED_0_BEGIN_MAP}) {
@@ -3045,7 +3374,6 @@ sub next {
if ($self->{RECURSIVE_DEPTH} == 0) {
$self->{RECURSIVE_ITERATOR_FLAG} = 0;
}
-
return $next;
}
@@ -3121,6 +3449,8 @@ sub next {
# 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
my $nextUnfiltered = $here->getNext();
+
+
my $maxDepthAdded = -1;
for (@$nextUnfiltered) {
@@ -3154,7 +3484,6 @@ sub next {
$self->{RECURSIVE_ITERATOR_FLAG} = 1;
my $firstResource = $self->{HERE}->map_start();
my $finishResource = $self->{HERE}->map_finish();
-
$self->{RECURSIVE_ITERATOR} =
Apache::lonnavmaps::iterator->new($self->{NAV_MAP}, $firstResource,
$finishResource, $self->{FILTER},
@@ -3492,6 +3821,8 @@ sub new {
$self->{NAV_MAP}->{RESOURCE_CACHE}->{$self->{ID}} = $self;
$self->{RESOURCE_ERROR} = 0;
+ $self->{DUEDATE_CACHE} = undef;
+
# A hash that can be used by two-pass algorithms to store data
# about this resource in. Not used by the resource object
# directly.
@@ -3751,7 +4082,7 @@ sub is_practice {
sub is_problem {
my $self=shift;
my $src = $self->src();
- if ($src =~ /\.(problem|exam|quiz|assess|survey|form|library|task)$/) {
+ if ($src =~ /$LONCAPA::assess_re/) {
return !($self->is_practice());
}
return 0;
@@ -3786,7 +4117,7 @@ sub is_incomplete {
sub is_raw_problem {
my $self=shift;
my $src = $self->src();
- if ($src =~ /\.(problem|exam|quiz|assess|survey|form|library|task)$/) {
+ if ($src =~ /$LONCAPA::assess_re/) {
return 1;
}
return 0;
@@ -3959,11 +4290,13 @@ their code.)
=over 4
+
=item * B
returns true if the current date is such that the
specified resource part is printable.
+
=item * B
Returns true if all parts in the resource are printable making the
@@ -4022,13 +4355,16 @@ Get the weight for the problem.
=cut
+
+
+
sub printable {
my ($self, $part) = @_;
# Get the print open/close dates for the resource.
- my $start = $self->parmval("prinstartdate", $part);
+ my $start = $self->parmval("printstartdate", $part);
my $end = $self->parmval("printenddate", $part);
# The following cases apply:
@@ -4130,6 +4466,9 @@ sub checkedin {
sub duedate {
(my $self, my $part) = @_;
+ if (defined ($self->{DUEDATE_CACHE}->{$part})) {
+ return $self->{DUEDATE_CACHE}->{$part};
+ }
my $date;
my @interval=$self->parmval("interval", $part);
my $due_date=$self->parmval("duedate", $part);
@@ -4146,6 +4485,7 @@ sub duedate {
} else {
$date = $due_date;
}
+ $self->{DUEDATE_CACHE}->{$part} = $date;
return $date;
}
sub handgrade {
@@ -4997,12 +5337,13 @@ sub status {
}
# Otherwise, it's untried and open
- return OPEN;
+ return OPEN;
}
sub check_for_slot {
my $self = shift;
my $part = shift;
+ my $symb = $self->symb();
my ($use_slots,$available,$availablestudent) = $self->slot_control($part);
if (($use_slots ne '') && ($use_slots !~ /^\s*no\s*$/i)) {
my @slots = (split(/:/,$availablestudent),split(/:/,$available));
@@ -5010,50 +5351,45 @@ sub check_for_slot {
my $cdom=$env{'course.'.$cid.'.domain'};
my $cnum=$env{'course.'.$cid.'.num'};
my $now = time;
+ my $num_usable_slots = 0;
if (@slots > 0) {
my %slots=&Apache::lonnet::get('slots',[@slots],$cdom,$cnum);
if (&Apache::lonnet::error(%slots)) {
return (UNKNOWN);
}
- my @sorted_slots = &Apache::loncommon::sorted_slots(\@slots,\%slots);
+ my @sorted_slots = &Apache::loncommon::sorted_slots(\@slots,\%slots,'starttime');
my ($checkedin,$checkedinslot);
foreach my $slot_name (@sorted_slots) {
- next if (!defined($slots{$slot_name}) ||
- !ref($slots{$slot_name}));
+ next if (!defined($slots{$slot_name}) || !ref($slots{$slot_name}));
my $end = $slots{$slot_name}->{'endtime'};
my $start = $slots{$slot_name}->{'starttime'};
my $ip = $slots{$slot_name}->{'ip'};
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) {
- ($checkedin,$checkedinslot) = $self->checkedin();
- if ($startreserve < $now) {
- if ($start > $now) {
- return (RESERVED_LATER,$start,$slot_name);
- } else {
- if ($ip ne '') {
- 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);
- }
+ if ($start > $now) {
+ return (RESERVED_LATER,$start,$slot_name);
+ } else {
+ if ($ip ne '') {
+ if (!&Apache::loncommon::check_ip_acc($ip)) {
+ return (RESERVED_LOCATION,$ip,$slot_name);
}
- return (RESERVED,$end,$slot_name);
}
- } else {
- if ($start > $now) {
- return (RESERVABLE,$startreserve,$slot_name);
+ my @proctors;
+ if ($slots{$slot_name}->{'proctor'} ne '') {
+ @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);
@@ -5074,32 +5410,33 @@ sub check_for_slot {
return (CORRECT);
}
}
- return(NOT_IN_A_SLOT);
- } else {
- if (!$future_slots_checked) {
- $future_slots = &get_future_slots($cdom,$cnum,$now);
- $future_slots_checked = 1;
- }
- if ($future_slots) {
+ if ($num_usable_slots) {
return(NOT_IN_A_SLOT);
}
- return(NOTRESERVABLE);
}
- }
- return;
-}
-
-sub get_future_slots {
- my ($cdom,$cnum,$now) = @_;
- my %slots=&Apache::lonnet::dump('slots',$cdom,$cnum);
- my $future_slots = 0;
- foreach my $slot (keys(%slots)) {
- if (($slots{$slot}->{'starttime'} > $now) &&
- ($slots{$slot}->{'endtime'} > $now)) {
- $future_slots ++;
+ my $reservable = &Apache::lonnet::get_reservable_slots($cnum,$cdom,$env{'user.name'},
+ $env{'user.domain'});
+ if (ref($reservable) eq 'HASH') {
+ if ((ref($reservable->{'now_order'}) eq 'ARRAY') && (ref($reservable->{'now'}) eq 'HASH')) {
+ foreach my $slot (reverse (@{$reservable->{'now_order'}})) {
+ if (($reservable->{'now'}{$slot}{'symb'} eq '') ||
+ ($reservable->{'now'}{$slot}{'symb'} eq $symb)) {
+ return(RESERVABLE,$reservable->{'now'}{$slot}{'endreserve'});
+ }
+ }
+ }
+ 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; }