--- loncom/interface/lonnavmaps.pm 2007/05/23 20:46:29 1.399
+++ loncom/interface/lonnavmaps.pm 2008/01/03 22:49:56 1.407
@@ -1,7 +1,7 @@
# The LearningOnline Network with CAPA
# Navigate Maps Handler
#
-# $Id: lonnavmaps.pm,v 1.399 2007/05/23 20:46:29 albertel Exp $
+# $Id: lonnavmaps.pm,v 1.407 2008/01/03 22:49:56 raeburn Exp $
#
# Copyright Michigan State University Board of Trustees
#
@@ -36,9 +36,9 @@ use Apache::lonenc();
use Apache::lonlocal;
use Apache::lonnet;
use POSIX qw (floor strftime);
-use Data::Dumper; # for debugging, not always
use Time::HiRes qw( gettimeofday tv_interval );
use LONCAPA;
+use DateTime();
# symbolic constants
sub SYMB { return 1; }
@@ -170,7 +170,10 @@ sub getLinkForResource {
if (defined($item)) { $res = $item; }
}
- return ($res->link(),$res->shown_symb());
+ if ($res) {
+ return ($res->link(),$res->shown_symb());
+ }
+ return;
}
# Convenience function: This separates the logic of how to create
@@ -184,6 +187,10 @@ sub getDescription {
my $part = shift;
my $status = $res->status($part);
+ my $open = $res->opendate($part);
+ my $due = $res->duedate($part);
+ my $answer = $res->answerdate($part);
+
if ($status == $res->NETWORK_FAILURE) {
return &mt("Having technical difficulties; please check status later");
}
@@ -191,20 +198,28 @@ sub getDescription {
return &mt("Not currently assigned.");
}
if ($status == $res->OPEN_LATER) {
- return "Open " . timeToHumanString($res->opendate($part),'start');
+ return "Open " .timeToHumanString($open,'start');
}
if ($status == $res->OPEN) {
- if ($res->duedate($part)) {
- return &mt("Due")." " .timeToHumanString($res->duedate($part),'end');
+ if ($due) {
+ if ($res->is_practice()) {
+ return &mt("Closes ")." " .timeToHumanString($due,'start');
+ } else {
+ return &mt("Due")." " .timeToHumanString($due,'end');
+ }
} else {
return &mt("Open, no due date");
}
}
if ($status == $res->PAST_DUE_ANSWER_LATER) {
- return &mt("Answer open")." " . timeToHumanString($res->answerdate($part),'start');
+ return &mt("Answer open")." " .timeToHumanString($answer,'start');
}
if ($status == $res->PAST_DUE_NO_ANSWER) {
- return &mt("Was due")." " . timeToHumanString($res->duedate($part),'end');
+ if ($res->is_practice()) {
+ return &mt("Closed")." " . timeToHumanString($due,'start');
+ } else {
+ return &mt("Was due")." " . timeToHumanString($due,'end');
+ }
}
if (($status == $res->ANSWER_OPEN || $status == $res->PARTIALLY_CORRECT)
&& $res->handgrade($part) ne 'yes') {
@@ -226,8 +241,8 @@ sub getDescription {
$triesString = "$triesString";
}
}
- if ($res->duedate($part)) {
- return &mt("Due")." " . timeToHumanString($res->duedate($part),'end') .
+ if ($due) {
+ return &mt("Due")." " . timeToHumanString($due,'end') .
" $triesString";
} else {
return &mt("No due date")." $triesString";
@@ -294,9 +309,6 @@ sub timeToHumanString {
}
my $now = time();
- my @time = localtime($time);
- my @now = localtime($now);
-
# Positive = future
my $delta = $time - $now;
@@ -355,22 +367,25 @@ sub timeToHumanString {
return "$prefix$hourString$minuteString$tense";
}
+ my $dt = DateTime->from_epoch(epoch => $time)
+ ->set_time_zone(&Apache::lonlocal::gettimezone());
+
# If there's a caller supplied format, use it.
- if($format ne '') {
- my $timeStr = strftime($format, localtime($time));
- return $timeStr.&Apache::lonlocal::gettimezone($time);
+ if ($format ne '') {
+ my $timeStr = $dt->strftime($format);
+ return $timeStr.' ('.$dt->time_zone_short_name().')';
}
# Less than 5 days away, display day of the week and
# HH:MM
if ( $delta < $day * 5 ) {
- my $timeStr = strftime("%A, %b %e at %I:%M %P", localtime($time));
+ my $timeStr = $dt->strftime("%A, %b %e at %I:%M %P (%Z)");
$timeStr =~ s/12:00 am/00:00/;
$timeStr =~ s/12:00 pm/noon/;
return ($inPast ? "last " : "this ") .
- $timeStr.&Apache::lonlocal::gettimezone($time);
+ $timeStr;
}
my $conjunction='on';
@@ -380,19 +395,22 @@ sub timeToHumanString {
$conjunction='by';
}
# Is it this year?
- if ( $time[5] == $now[5]) {
+ my $dt_now = DateTime->from_epoch(epoch => $now)
+ ->set_time_zone(&Apache::lonlocal::gettimezone());
+ if ( $dt->year() == $dt_now->year()) {
# Return on Month Day, HH:MM meridian
- my $timeStr = strftime("$conjunction %A, %b %e at %I:%M %P", localtime($time));
+ my $timeStr = $dt->strftime("$conjunction %A, %b %e at %I:%M %P (%Z)");
$timeStr =~ s/12:00 am/00:00/;
$timeStr =~ s/12:00 pm/noon/;
- return $timeStr.&Apache::lonlocal::gettimezone($time);
+ return $timeStr;
}
# Not this year, so show the year
- my $timeStr = strftime("$conjunction %A, %b %e %Y at %I:%M %P", localtime($time));
+ my $timeStr =
+ $dt->strftime("$conjunction %A, %b %e %Y at %I:%M %P (%Z)");
$timeStr =~ s/12:00 am/00:00/;
$timeStr =~ s/12:00 pm/noon/;
- return $timeStr.&Apache::lonlocal::gettimezone($time);
+ return $timeStr;
}
}
@@ -604,6 +622,11 @@ instruct the renderer to render only a p
the source of the map you want to process, like
'/res/103/jerf/navmap.course.sequence'.
+=item * B: default: false
+
+If you need to include the top level map (meaning the course) in the
+rendered output set this to true
+
=item * B: default: constructs one from %env
A reference to a navmap, used only if an iterator is not passed in. If
@@ -974,7 +997,7 @@ sub render_long_status {
$params->{'multipart'} && $part eq "0";
my $color;
- if ($resource->is_problem()) {
+ if ($resource->is_problem() || $resource->is_practice()) {
$color = $colormap{$resource->status};
if (dueInLessThan24Hours($resource, $part) ||
@@ -984,14 +1007,17 @@ sub render_long_status {
}
if ($resource->kind() eq "res" &&
- $resource->is_problem() &&
+ ($resource->is_problem() || $resource->is_practice()) &&
!$firstDisplayed) {
if ($color) {$result .= ""; }
$result .= getDescription($resource, $part);
if ($color) {$result .= ""; }
}
- if ($resource->is_map() && advancedUser() && $resource->randompick()) {
- $result .= '(randomly select ' . $resource->randompick() .')';
+ if ($resource->is_map() && &advancedUser() && $resource->randompick()) {
+ $result .= &mt('(randomly select [_1])', $resource->randompick());
+ }
+ if ($resource->is_map() && &advancedUser() && $resource->randomorder()) {
+ $result .= &mt('(randomly ordered)');
}
# Debugging code
@@ -1026,7 +1052,6 @@ my %statusStrings =
);
my @statuses = ($resObj->CORRECT, $resObj->ATTEMPTED, $resObj->INCORRECT, $resObj->OPEN, $resObj->CLOSED, $resObj->ERROR);
-use Data::Dumper;
sub render_parts_summary_status {
my ($resource, $part, $params) = @_;
if (!$resource->is_problem() && !$resource->contains_problem) { return ' | '; }
@@ -1233,7 +1258,7 @@ sub render {
$args->{'iterator'} = $it = $navmap->getIterator($firstResource, $finishResource, $filterHash, $condition);
} else {
- $args->{'iterator'} = $it = $navmap->getIterator(undef, undef, $filterHash, $condition);
+ $args->{'iterator'} = $it = $navmap->getIterator(undef, undef, $filterHash, $condition,undef,$args->{'include_top_level_map'});
}
}
@@ -1270,7 +1295,6 @@ sub render {
# Print key?
if ($printKey) {
$result .= '';
- my $date=localtime;
$result.='Key: | ';
my $location=&Apache::loncommon::lonhttpdurl("/adm/lonMisc");
if ($navmap->{LAST_CHECK}) {
@@ -2275,12 +2299,19 @@ sub parmval {
my $hashkey = $what."|||".$symb;
if (defined($self->{PARM_CACHE}->{$hashkey})) {
- return $self->{PARM_CACHE}->{$hashkey};
+ if (wantarray) {
+ return @{$self->{PARM_CACHE}->{$hashkey}};
+ } else {
+ return $self->{PARM_CACHE}->{$hashkey}->[0];
+ }
}
my $result = $self->parmval_real($what, $symb, $recurse);
$self->{PARM_CACHE}->{$hashkey} = $result;
- return $result;
+ if (wantarray) {
+ return @{$result};
+ }
+ return $result->[0];
}
sub parmval_real {
@@ -2301,7 +2332,7 @@ sub parmval_real {
my $uname=$env{'user.name'};
my $udom=$env{'user.domain'};
- unless ($symb) { return ''; }
+ unless ($symb) { return ['']; }
my $result='';
my ($mapname,$id,$fn)=&Apache::lonnet::decode_symb($symb);
@@ -2333,48 +2364,49 @@ sub parmval_real {
# ---------------------------------------------------------- first, check user
if ($uname and defined($useropt)) {
- if (defined($$useropt{$courselevelr})) { return $$useropt{$courselevelr}; }
- if (defined($$useropt{$courselevelm})) { return $$useropt{$courselevelm}; }
- if (defined($$useropt{$courselevel})) { return $$useropt{$courselevel}; }
+ if (defined($$useropt{$courselevelr})) { return [$$useropt{$courselevelr},'resource']; }
+ if (defined($$useropt{$courselevelm})) { return [$$useropt{$courselevelm},'map']; }
+ if (defined($$useropt{$courselevel})) { return [$$useropt{$courselevel},'course']; }
}
# ------------------------------------------------------- second, check course
if ($cgroup ne '' and defined($courseopt)) {
- if (defined($$courseopt{$grplevelr})) { return $$courseopt{$grplevelr}; }
- if (defined($$courseopt{$grplevelm})) { return $$courseopt{$grplevelm}; }
- if (defined($$courseopt{$grplevel})) { return $$courseopt{$grplevel}; }
+ if (defined($$courseopt{$grplevelr})) { return [$$courseopt{$grplevelr},'resource']; }
+ if (defined($$courseopt{$grplevelm})) { return [$$courseopt{$grplevelm},'map']; }
+ if (defined($$courseopt{$grplevel})) { return [$$courseopt{$grplevel},'course']; }
}
if ($csec and defined($courseopt)) {
- if (defined($$courseopt{$seclevelr})) { return $$courseopt{$seclevelr}; }
- if (defined($$courseopt{$seclevelm})) { return $$courseopt{$seclevelm}; }
- if (defined($$courseopt{$seclevel})) { return $$courseopt{$seclevel}; }
+ if (defined($$courseopt{$seclevelr})) { return [$$courseopt{$seclevelr},'resource']; }
+ if (defined($$courseopt{$seclevelm})) { return [$$courseopt{$seclevelm},'map']; }
+ if (defined($$courseopt{$seclevel})) { return [$$courseopt{$seclevel},'course']; }
}
if (defined($courseopt)) {
- if (defined($$courseopt{$courselevelr})) { return $$courseopt{$courselevelr}; }
+ if (defined($$courseopt{$courselevelr})) { return [$$courseopt{$courselevelr},'resource']; }
}
# ----------------------------------------------------- third, check map parms
my $thisparm=$$parmhash{$symbparm};
- if (defined($thisparm)) { return $thisparm; }
+ if (defined($thisparm)) { return [$thisparm,'map']; }
# ----------------------------------------------------- fourth , check default
my $meta_rwhat=$rwhat;
$meta_rwhat=~s/\./_/g;
my $default=&Apache::lonnet::metadata($fn,$meta_rwhat);
- if (defined($default)) { return $default}
+ if (defined($default)) { return [$default,'resource']}
$default=&Apache::lonnet::metadata($fn,'parameter_'.$meta_rwhat);
- if (defined($default)) { return $default}
-
+ if (defined($default)) { return [$default,'resource']}
# --------------------------------------------------- fifth, check more course
if (defined($courseopt)) {
- if (defined($$courseopt{$courselevelm})) { return $$courseopt{$courselevelm}; }
- if (defined($$courseopt{$courselevel})) { return $$courseopt{$courselevel}; }
+ if (defined($$courseopt{$courselevelm})) { return [$$courseopt{$courselevelm},'map']; }
+ if (defined($$courseopt{$courselevel})) {
+ my $ret = [$$courseopt{$courselevel},'course'];
+ return $ret;
+ }
}
-
# --------------------------------------------------- sixth , cascade up parts
my ($space,@qualifier)=split(/\./,$rwhat);
@@ -2384,13 +2416,13 @@ sub parmval_real {
my $id=pop(@parts);
my $part=join('_',@parts);
if ($part eq '') { $part='0'; }
- my $partgeneral=$self->parmval($part.".$qualifier",$symb,1);
- if (defined($partgeneral)) { return $partgeneral; }
+ my @partgeneral=$self->parmval($part.".$qualifier",$symb,1);
+ if (defined($partgeneral[0])) { return \@partgeneral; }
}
- if ($recurse) { return undef; }
+ if ($recurse) { return []; }
my $pack_def=&Apache::lonnet::packages_tab_default($fn,'resource.'.$rwhat);
- if (defined($pack_def)) { return $pack_def; }
- return '';
+ if (defined($pack_def)) { return [$pack_def,'resource']; }
+ return [''];
}
=pod
@@ -2511,6 +2543,10 @@ sub retrieveResources {
my @resources = ();
+ if (&$filterFunc($map)) {
+ push(@resources, $map);
+ }
+
# Run down the iterator and collect the resources.
my $curRes;
@@ -2520,7 +2556,7 @@ sub retrieveResources {
next;
}
- push @resources, $curRes;
+ push(@resources, $curRes);
if ($bailout) {
return @resources;
@@ -2851,6 +2887,10 @@ sub next {
$self->{HAVE_RETURNED_0} = 1;
return $self->{NAV_MAP}->getById('0.0');
}
+ if ($self->{RETURN_0} && !$self->{HAVE_RETURNED_0_BEGIN_MAP}) {
+ $self->{HAVE_RETURNED_0_BEGIN_MAP} = 1;
+ return $self->BEGIN_MAP();
+ }
if ($self->{RECURSIVE_ITERATOR_FLAG}) {
# grab the next from the recursive iterator
@@ -3364,8 +3404,13 @@ false.
=item * B:
-Returns true for a map if the randompick feature is being used on the
-map. (?)
+Returns the number of randomly picked items for a map if the randompick
+feature is being used on the map.
+
+=item * B:
+
+Returns true for a map if the randomorder feature is being used on the
+map.
=item * B:
@@ -3397,6 +3442,10 @@ sub randompick {
my $self = shift;
return $self->parmval('randompick');
}
+sub randomorder {
+ my $self = shift;
+ return ($self->parmval('randomorder') =~ /^yes$/i);
+}
sub link {
my $self=shift;
if ($self->encrypted()) { return &Apache::lonenc::encrypted($self->src); }
@@ -3560,6 +3609,15 @@ sub contains_problem {
}
return 0;
}
+sub map_contains_problem {
+ my $self=shift;
+ if ($self->is_map()) {
+ my $has_problem=
+ $self->hasResource($self,sub { $_[0]->is_problem() },1);
+ return $has_problem;
+ }
+ return 0;
+}
sub is_sequence {
my $self=shift;
return $self->navHash("is_map_", 1) &&
@@ -3765,13 +3823,15 @@ sub awarded {
sub duedate {
(my $self, my $part) = @_;
my $date;
- my $interval=$self->parmval("interval", $part);
+ my @interval=$self->parmval("interval", $part);
my $due_date=$self->parmval("duedate", $part);
- if ($interval =~ /\d+/) {
- my $first_access=&Apache::lonnet::get_first_access('map',$self->symb);
+ if ($interval[0] =~ /\d+/) {
+ my $first_access=&Apache::lonnet::get_first_access($interval[1],
+ $self->symb);
if (defined($first_access)) {
- $interval = $first_access+$interval;
- $date = ($interval < $due_date)? $interval : $due_date;
+ my $interval = $first_access+$interval[0];
+ $date = (!$due_date || $interval < $due_date) ? $interval
+ : $due_date;
} else {
$date = $due_date;
}