: default: constructs one from %env
A reference to a navmap, used only if an iterator is not passed in. If
@@ -832,7 +854,10 @@ sub render_resource {
if (!$resource->condval()) {
$nonLinkedText .= ' ('.&mt('conditionally hidden').') ';
}
-
+ if (($resource->is_practice()) && ($resource->is_raw_problem())) {
+ $nonLinkedText .=' '.&mt('not graded').'';
+ }
+
# We're done preparing and finally ready to start the rendering
my $result = "";
@@ -975,7 +1000,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) ||
@@ -985,14 +1010,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
@@ -1027,7 +1055,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 ' | | '; }
@@ -1234,7 +1261,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'});
}
}
@@ -1271,7 +1298,6 @@ sub render {
# Print key?
if ($printKey) {
$result .= '';
- my $date=localtime;
$result.='Key: | ';
my $location=&Apache::loncommon::lonhttpdurl("/adm/lonMisc");
if ($navmap->{LAST_CHECK}) {
@@ -1715,7 +1741,7 @@ ENDBLOCK
$result.='}
'."\n";
+ '."\n";
return $result;
}
@@ -1802,6 +1828,7 @@ See iterator documentation below.
use strict;
use GDBM_File;
use Apache::lonnet;
+use LONCAPA;
sub new {
# magic invocation to create a class instance
@@ -2057,7 +2084,7 @@ sub discussion_info {
my $ressymb = $self->wrap_symb($symb);
# keys used to store bulletinboard postings use 'unwrapped' symb.
- my $discsymb = $self->unwrap_symb($ressymb);
+ my $discsymb = &escape($self->unwrap_symb($ressymb));
my $version = $self->{DISCUSSION_DATA}{'version:'.$discsymb};
if (!$version) { return; }
@@ -2197,7 +2224,7 @@ the given map. This is one of the proper
# The strategy here is to cache the resource objects, and only construct them
# as we use them. The real point is to prevent reading any more from the tied
-# hash then we have to, which should hopefully alleviate speed problems.
+# hash than we have to, which should hopefully alleviate speed problems.
sub getById {
my $self = shift;
@@ -2271,16 +2298,28 @@ sub finishResource {
# the actual lookup; parmval caches the results.
sub parmval {
my $self = shift;
- my ($what,$symb)=@_;
+ my ($what,$symb,$recurse)=@_;
my $hashkey = $what."|||".$symb;
if (defined($self->{PARM_CACHE}->{$hashkey})) {
- return $self->{PARM_CACHE}->{$hashkey};
+ if (ref($self->{PARM_CACHE}->{$hashkey}) eq 'ARRAY') {
+ if (defined($self->{PARM_CACHE}->{$hashkey}->[0])) {
+ if (wantarray) {
+ return @{$self->{PARM_CACHE}->{$hashkey}};
+ } else {
+ return $self->{PARM_CACHE}->{$hashkey}->[0];
+ }
+ }
+ } else {
+ return $self->{PARM_CACHE}->{$hashkey};
+ }
}
-
- my $result = $self->parmval_real($what, $symb);
+ 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 +2340,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 +2372,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 +2424,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; }
- my $pack_def=&Apache::lonnet::packages_tab_default($fn,'resource.'.$what);
- if (defined($pack_def)) { return $pack_def; }
- return '';
+ if ($recurse) { return []; }
+ my $pack_def=&Apache::lonnet::packages_tab_default($fn,'resource.'.$rwhat);
+ if (defined($pack_def)) { return [$pack_def,'resource']; }
+ return [''];
}
=pod
@@ -2398,7 +2438,7 @@ sub parmval_real {
=item * B(url,multiple):
Retrieves a resource object by URL of the resource, unless the optional
-multiple parameter is included in wahich caes an array of resource
+multiple parameter is included in which case an array of resource
objects is returned. If passed a resource object, it will simply return
it, so it is safe to use this method in code like
"$res = $navmap->getResourceByUrl($res)"
@@ -2433,7 +2473,7 @@ all matching resources.
=item * B(map, filterFunc, recursive, showall):
-Convience method for
+Convenience method for
scalar(retrieveResources($map, $filterFunc, $recursive, 1, $showall)) > 0
@@ -2511,6 +2551,10 @@ sub retrieveResources {
my @resources = ();
+ if (&$filterFunc($map)) {
+ push(@resources, $map);
+ }
+
# Run down the iterator and collect the resources.
my $curRes;
@@ -2520,7 +2564,7 @@ sub retrieveResources {
next;
}
- push @resources, $curRes;
+ push(@resources, $curRes);
if ($bailout) {
return @resources;
@@ -2667,7 +2711,7 @@ 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
+code. It is difficult to get right and harder to understand than
this. They should be migrated to this new style.
=cut
@@ -2851,6 +2895,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
@@ -2952,7 +3000,7 @@ sub next {
}
# Is this the end of a branch? If so, all of the resources examined above
- # led to lower levels then the one we are currently at, so we push a END_BRANCH
+ # led to lower levels than the one we are currently at, so we push a END_BRANCH
# marker onto the stack so we don't forget.
# Example: For the usual A(BC)(DE)F case, when the iterator goes down the
# BC branch and gets to C, it will see F as the only next resource, but it's
@@ -3288,7 +3336,7 @@ X X
All resources also have Bs, which uniquely identify a resource
in a course. Many internal LON-CAPA functions expect a symb. A symb
carries along with it the URL of the resource, and the map it appears
-in. Symbs are much larger then resource IDs.
+in. Symbs are much larger than resource IDs.
=cut
@@ -3364,8 +3412,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:
@@ -3395,7 +3448,13 @@ sub kind { my $self=shift; return $self-
sub randomout { my $self=shift; return $self->navHash("randomout_", 1); }
sub randompick {
my $self = shift;
- return $self->parmval('randompick');
+ my $randompick = $self->parmval('randompick');
+ return $randompick;
+}
+sub randomorder {
+ my $self = shift;
+ my $randomorder = $self->parmval('randomorder');
+ return ($randomorder =~ /^yes$/i);
}
sub link {
my $self=shift;
@@ -3473,6 +3532,7 @@ sub compTitle {
}
return $title;
}
+
=pod
B
@@ -3515,7 +3575,8 @@ sub retrieveResources {
sub is_exam {
my ($self,$part) = @_;
- if ($self->parmval('type',$part) eq 'exam') {
+ my $type = $self->parmval('type',$part);
+ if ($type eq 'exam') {
return 1;
}
if ($self->src() =~ /\.(exam)$/) {
@@ -3538,7 +3599,8 @@ sub is_page {
sub is_practice {
my $self=shift;
my ($part) = @_;
- if ($self->parmval('type',$part) eq 'practice') {
+ my $type = $self->parmval('type',$part);
+ if ($type eq 'practice') {
return 1;
}
return 0;
@@ -3551,6 +3613,15 @@ sub is_problem {
}
return 0;
}
+sub is_raw_problem {
+ my $self=shift;
+ my $src = $self->src();
+ if ($src =~ /\.(problem|exam|quiz|assess|survey|form|library|task)$/) {
+ return 1;
+ }
+ return 0;
+}
+
sub contains_problem {
my $self=shift;
if ($self->is_page()) {
@@ -3559,6 +3630,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) &&
@@ -3567,7 +3647,8 @@ sub is_sequence {
sub is_survey {
my $self = shift();
my $part = shift();
- if ($self->parmval('type',$part) eq 'survey') {
+ my $type = $self->parmval('type',$part);
+ if ($type eq 'survey') {
return 1;
}
if ($self->src() =~ /\.(survey)$/) {
@@ -3665,9 +3746,9 @@ sub map_type {
# These functions will be responsible for returning the CORRECT
# VALUE for the parameter, no matter what. So while they may look
-# like direct calls to parmval, they can be more then that.
+# like direct calls to parmval, they can be more than that.
# So, for instance, the duedate function should use the "duedatetype"
-# information, rather then the resource object user.
+# information, rather than the resource object user.
=pod
@@ -3743,16 +3824,19 @@ Get the weight for the problem.
sub acc {
(my $self, my $part) = @_;
- return $self->parmval("acc", $part);
+ my $acc = $self->parmval("acc", $part);
+ return $acc;
}
sub answerdate {
(my $self, my $part) = @_;
# Handle intervals
- if ($self->parmval("answerdate.type", $part) eq 'date_interval') {
- return $self->duedate($part) +
- $self->parmval("answerdate", $part);
+ my $answerdatetype = $self->parmval("answerdate.type", $part);
+ my $answerdate = $self->parmval("answerdate", $part);
+ my $duedate = $self->parmval("duedate", $part);
+ if ($answerdatetype eq 'date_interval') {
+ $answerdate = $duedate + $answerdate;
}
- return $self->parmval("answerdate", $part);
+ return $answerdate;
}
sub awarded {
my $self = shift; my $part = shift;
@@ -3764,13 +3848,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;
}
@@ -3781,33 +3867,49 @@ sub duedate {
}
sub handgrade {
(my $self, my $part) = @_;
- return $self->parmval("handgrade", $part);
+ my @response_ids = $self->responseIds($part);
+ if (@response_ids) {
+ foreach my $response_id (@response_ids) {
+ my $handgrade = $self->parmval("handgrade",$part.'_'.$response_id);
+ if (lc($handgrade) eq 'yes') {
+ return 'yes';
+ }
+ }
+ }
+ my $handgrade = $self->parmval("handgrade", $part);
+ return $handgrade;
}
sub maxtries {
(my $self, my $part) = @_;
- return $self->parmval("maxtries", $part);
+ my $maxtries = $self->parmval("maxtries", $part);
+ return $maxtries;
}
sub opendate {
(my $self, my $part) = @_;
- if ($self->parmval("opendate.type", $part) eq 'date_interval') {
- return $self->duedate($part) -
- $self->parmval("opendate", $part);
+ my $opendatetype = $self->parmval("opendate.type", $part);
+ my $opendate = $self->parmval("opendate", $part);
+ if ($opendatetype eq 'date_interval') {
+ my $duedate = $self->duedate($part);
+ $opendate = $duedate - $opendate;
}
- return $self->parmval("opendate");
+ return $opendate;
}
sub problemstatus {
(my $self, my $part) = @_;
- return lc $self->parmval("problemstatus", $part);
+ my $problemstatus = $self->parmval("problemstatus", $part);
+ return lc($problemstatus);
}
sub sig {
(my $self, my $part) = @_;
- return $self->parmval("sig", $part);
+ my $sig = $self->parmval("sig", $part);
+ return $sig;
}
sub tol {
(my $self, my $part) = @_;
- return $self->parmval("tol", $part);
+ my $tol = $self->parmval("tol", $part);
+ return $tol;
}
-sub tries {
+sub tries {
my $self = shift;
my $tries = $self->queryRestoreHash('tries', shift);
if (!defined($tries)) { return '0';}
@@ -3815,15 +3917,17 @@ sub tries {
}
sub type {
(my $self, my $part) = @_;
- return $self->parmval("type", $part);
+ my $type = $self->parmval("type", $part);
+ return $type;
}
sub weight {
my $self = shift; my $part = shift;
if (!defined($part)) { $part = '0'; }
- return &Apache::lonnet::EXT('resource.'.$part.'.weight',
- $self->symb(), $env{'user.domain'},
- $env{'user.name'},
- $env{'request.course.sec'});
+ my $weight = &Apache::lonnet::EXT('resource.'.$part.'.weight',
+ $self->symb(), $env{'user.domain'},
+ $env{'user.name'},
+ $env{'request.course.sec'});
+ return $weight;
}
sub part_display {
my $self= shift(); my $partID = shift();
@@ -4497,7 +4601,11 @@ sub status {
#if ($self->{RESOURCE_ERROR}) { return NETWORK_FAILURE; }
if ($completionStatus == NETWORK_FAILURE) { return NETWORK_FAILURE; }
- my $suppressFeedback = $self->problemstatus($part) eq 'no';
+ my $suppressFeedback = 0;
+ if (($self->problemstatus($part) eq 'no') ||
+ ($self->problemstatus($part) eq 'no_feedback_ever')) {
+ $suppressFeedback = 1;
+ }
# If there's an answer date and we're past it, don't
# suppress the feedback; student should know
if ($self->duedate($part) && $self->duedate($part) < time() &&