--- loncom/interface/lonnavmaps.pm 2006/03/04 06:12:40 1.367 +++ loncom/interface/lonnavmaps.pm 2006/05/15 19:29:03 1.382 @@ -1,7 +1,7 @@ # The LearningOnline Network with CAPA # Navigate Maps Handler # -# $Id: lonnavmaps.pm,v 1.367 2006/03/04 06:12:40 albertel Exp $ +# $Id: lonnavmaps.pm,v 1.382 2006/05/15 19:29:03 albertel Exp $ # # Copyright Michigan State University Board of Trustees # @@ -194,10 +194,7 @@ MENU MENU } $r->send_http_header; - my $html=&Apache::lonxml::xmlbegin(); - $r->print(<<"ENDSUBM"); - $html - + my $js =<<"ENDSUBM"; - - - ENDSUBM + $r->print(&Apache::loncommon::start_page(undef,$js, + {'only_body' => 1, + 'bgcolor' => '#FFFFFF', + 'add_entries' => + {'onload' => + "submitthis()"}}). + &Apache::loncommon::end_page()); + return OK; } if ($ENV{QUERY_STRING} =~ /^launchExternal/) { @@ -239,49 +241,37 @@ MENU return HTTP_NOT_ACCEPTABLE; } $r->send_http_header; - my $html=&Apache::lonxml::xmlbegin(); - $r->print("$html\n"); - $r->print("".&mt('Navigate Course Contents').""); + # ------------------------------------------------------------ Get query string &Apache::loncommon::get_unprocessed_cgi($ENV{'QUERY_STRING'},['register','sort','showOnlyHomework','postsymb']); # ----------------------------------------------------- Force menu registration - my $addentries=''; - my $more_unload; my $body_only=''; + my $js; if ($env{'environment.remotenavmap'} eq 'on') { - $r->print(''); -# FIXME need to be smarter to only catch window close events -# $more_unload="collapse()" + $js=''; $body_only=1; } - if ($env{'form.register'}) { - $addentries=' onLoad="'.&Apache::lonmenu::loadevents(). - '" onUnload="'.&Apache::lonmenu::unloadevents().';'. - $more_unload.'"'; - $r->print(&Apache::lonmenu::registerurl(1)); - } else { - $addentries=' onUnload="'.$more_unload.'"'; - } # Header - $r->print(''. - &Apache::loncommon::bodytag('Navigate Course Contents','', - $addentries,$body_only,'', - $env{'form.register'})); - $r->print(''); + $r->print(&Apache::loncommon::start_page('Navigate Course Contents',$js, + {'only_body' => $body_only, + 'force_register' => + $env{'form.register'},})); + $r->print(''); $r->rflush(); # Check that it's defined if (!($navmap->courseMapDefined())) { $r->print(&Apache::loncommon::help_open_menu('','Navigation Screen','Navigation_Screen','',undef,'RAT')); - $r->print('Coursemap undefined.' . - ''); + $r->print(''.&mt('Coursemap undefined.'). + '' . + &Apache::loncommon::end_page()); return OK; } @@ -328,32 +318,38 @@ MENU "Close navigation window"); } - my $jumpToFirstHomework = 0; + # Check to see if the student is jumping to next open, do-able problem if ($ENV{QUERY_STRING} =~ /^jumpToFirstHomework/) { - $jumpToFirstHomework = 1; # Find the next homework problem that they can do. my $iterator = $navmap->getIterator(undef, undef, undef, 1); my $curRes; my $foundDoableProblem = 0; - my $problemRes; + my $minimumduedate; - while (($curRes = $iterator->next()) && !$foundDoableProblem) { + while ($curRes = $iterator->next()) { if (ref($curRes) && $curRes->is_problem()) { my $status = $curRes->status(); if ($curRes->completable()) { - $problemRes = $curRes; + my $thisduedate=$curRes->duedate(); + unless ($foundDoableProblem) { + $minimumduedate=$thisduedate; + } + $foundDoableProblem = 1; - # Pop open all previous maps - my $stack = $iterator->getStack(); - pop @$stack; # last resource in the stack is the problem - # itself, which we don't need in the map stack - my @mapPcs = map {$_->map_pc()} @$stack; - $env{'form.filter'} = join(',', @mapPcs); - - # Mark as both "here" and "jump" - $env{'form.postsymb'} = $curRes->symb(); + if ($thisduedate<=$minimumduedate) { + # Pop open all previous maps + my $stack = $iterator->getStack(); + pop @$stack; # last resource in the stack is the problem + # itself, which we don't need in the map stack + my @mapPcs = map {$_->map_pc()} @$stack; + $env{'form.filter'} = join(',', @mapPcs); + + # Mark as both "here" and "jump" + $env{'form.postsymb'} = $curRes->symb(); + $minimumduedate=$thisduedate; + } } } } @@ -365,7 +361,7 @@ MENU } else { &add_linkitem(\%toplinkitems,'firsthomework', 'location.href="navmaps?jumpToFirstHomework"', - "Show Me My First Homework Problem"); + "Show my first due problem"); } my $suppressEmptySequences = 0; @@ -382,8 +378,8 @@ MENU }; &add_linkitem(\%toplinkitems,'everything', 'location.href="navmaps?sort='.$env{'form.sort'}.'"', - "Show Everything"); - $r->print("

".&mt("Uncompleted Homework")."

"); + "Show everything"); + $r->print("

".&mt("Uncompleted Problems")."

"); $env{'form.filter'} = ''; $env{'form.condition'} = 1; $resource_no_folder_link = 1; @@ -391,7 +387,7 @@ MENU &add_linkitem(\%toplinkitems,'uncompleted', 'location.href="navmaps?sort='.$env{'form.sort'}. '&showOnlyHomework=1"', - "Show Only Uncompleted Homework"); + "Show only uncompleted problems"); } my %selected=($env{'form.sort'} => 'selected=on'); @@ -434,7 +430,7 @@ MENU #my $td=&tv_interval($t0); #$r->print("
$td"); - $r->print(""); + $r->print(&Apache::loncommon::end_page()); $r->rflush(); return OK; @@ -683,7 +679,7 @@ sub timeToHumanString { if($format ne '') { my $timeStr = strftime($format, localtime($time)); - return $timeStr.&Apache::lonlocal::gettimezone(); + return $timeStr.&Apache::lonlocal::gettimezone($time); } # Less then 5 days away, display day of the week and @@ -694,7 +690,7 @@ sub timeToHumanString { $timeStr =~ s/12:00 am/00:00/; $timeStr =~ s/12:00 pm/noon/; return ($inPast ? "last " : "this ") . - $timeStr.&Apache::lonlocal::gettimezone(); + $timeStr.&Apache::lonlocal::gettimezone($time); } my $conjunction='on'; @@ -709,14 +705,14 @@ sub timeToHumanString { my $timeStr = strftime("$conjunction %A, %b %e at %I:%M %P", localtime($time)); $timeStr =~ s/12:00 am/00:00/; $timeStr =~ s/12:00 pm/noon/; - return $timeStr.&Apache::lonlocal::gettimezone(); + return $timeStr.&Apache::lonlocal::gettimezone($time); } # Not this year, so show the year my $timeStr = strftime("$conjunction %A, %b %e %Y at %I:%M %P", localtime($time)); $timeStr =~ s/12:00 am/00:00/; $timeStr =~ s/12:00 pm/noon/; - return $timeStr.&Apache::lonlocal::gettimezone(); + return $timeStr.&Apache::lonlocal::gettimezone($time); } } @@ -1613,11 +1609,11 @@ sub render { if ($condition) { $link='"navmaps?condition=0&filter=&'.$queryString. '&here='.&Apache::lonnet::escape($here).'"'; - $text='Close All Folders'; + $text='Close all folders'; } else { $link='"navmaps?condition=1&filter=&'.$queryString. '&here='.&Apache::lonnet::escape($here).'"'; - $text='Open All Folders'; + $text='Open all folders'; } if ($args->{'caller'} eq 'navmapsdisplay') { &add_linkitem($args->{'linkitems'},'changefolder', @@ -2356,10 +2352,11 @@ sub unread_discussion { my $symb = shift; $self->get_discussion_data(); - - my $ressymb = $self->wrap_symb($symb); - my $version = $self->{DISCUSSION_DATA}{'version:'.$ressymb}; + my $ressymb = $self->wrap_symb($symb); + # keys used to store bulletinboard postings use 'unwrapped' symb. + my $discsymb = $self->unwrap_symb($ressymb); + my $version = $self->{DISCUSSION_DATA}{'version:'.$discsymb}; if (!$version) { return; } my $prevread = $self->{LAST_READ}{$ressymb}; @@ -2372,24 +2369,24 @@ sub unread_discussion { my %subjects; for (my $id=$version; $id>0; $id--) { - my $vkeys=$self->{DISCUSSION_DATA}{$id.':keys:'.$ressymb}; + my $vkeys=$self->{DISCUSSION_DATA}{$id.':keys:'.$discsymb}; my @keys=split(/:/,$vkeys); if (grep(/^hidden$/ ,@keys)) { if (!$hiddenflag) { - $hidden = $self->{DISCUSSION_DATA}{$id.':'.$ressymb.':hidden'}; + $hidden = $self->{DISCUSSION_DATA}{$id.':'.$discsymb.':hidden'}; $hiddenflag = 1; } } elsif (grep(/^deleted$/,@keys)) { if (!$deletedflag) { - $deleted = $self->{DISCUSSION_DATA}{$id.':'.$ressymb.':deleted'}; + $deleted = $self->{DISCUSSION_DATA}{$id.':'.$discsymb.':deleted'}; $deletedflag = 1; } } else { if (($hidden !~/\.$id\./) && ($deleted !~/\.$id\./) - && $prevread < $self->{DISCUSSION_DATA}{$id.':'.$ressymb.':timestamp'}) { + && $prevread < $self->{DISCUSSION_DATA}{$id.':'.$discsymb.':timestamp'}) { $unreadcount++; $subjects{$unreadcount}= - $id.': '.$self->{DISCUSSION_DATA}{$id.':'.$ressymb.':subject'}; + $id.': '.$self->{DISCUSSION_DATA}{$id.':'.$discsymb.':subject'}; } } } @@ -2402,7 +2399,7 @@ sub unread_discussion { sub wrap_symb { my $self = shift; my $symb = shift; - if ($symb =~ m-___(adm/\w+/\w+/)(\d+)(/bulletinboard)$-) { + if ($symb =~ m-___(adm/[^/]+/[^/]+/)(\d+)(/bulletinboard)$-) { unless ($symb =~ m|adm/wrapper/adm|) { $symb = 'bulletin___'.$2.'___adm/wrapper/'.$1.$2.$3; } @@ -2410,6 +2407,16 @@ sub wrap_symb { return $symb; } +sub unwrap_symb { + my $self = shift; + my $ressymb = shift; + my $discsymb = $ressymb; + if ($ressymb =~ m-^(bulletin___\d+___)adm/wrapper/(adm/[^/]+/[^/]+/\d+/bulletinboard)$-) { + $discsymb = $1.$2; + } + return $discsymb; +} + # Private method: Does the given resource (as a symb string) have # current feedback? Returns the string in the feedback hash, which # will be false if it does not exist. @@ -3657,8 +3664,7 @@ sub kind { my $self=shift; return $self- sub randomout { my $self=shift; return $self->navHash("randomout_", 1); } sub randompick { my $self = shift; - return $self->{NAV_MAP}->{PARM_HASH}->{$self->symb . - '.0.parameter_randompick'}; + return $self->parmval('randompick'); } sub link { my $self=shift; @@ -3776,6 +3782,16 @@ sub retrieveResources { return $self->{NAV_MAP}->retrieveResources(@_); } +sub is_exam { + my ($self,$part) = @_; + if ($self->parmval('type',$part) eq 'exam') { + return 1; + } + if ($self->src() =~ /\.(exam)$/) { + return 1; + } + return 0; +} sub is_html { my $self=shift; my $src = $self->src(); @@ -3814,7 +3830,6 @@ sub contains_problem { } sub is_sequence { my $self=shift; - my $src = $self->src(); return $self->navHash("is_map_", 1) && $self->navHash("map_type_" . $self->map_pc()) eq 'sequence'; } @@ -3889,7 +3904,7 @@ Returns a string with the type of the ma sub map_finish { my $self = shift; my $src = $self->src(); - $src = Apache::lonnet::clutter($src); + $src = &Apache::lonnet::clutter($src); my $res = $self->navHash("map_finish_$src", 0); $res = $self->{NAV_MAP}->getById($res); return $res; @@ -3902,7 +3917,7 @@ sub map_pc { sub map_start { my $self = shift; my $src = $self->src(); - $src = Apache::lonnet::clutter($src); + $src = &Apache::lonnet::clutter($src); my $res = $self->navHash("map_start_$src", 0); $res = $self->{NAV_MAP}->getById($res); return $res; @@ -4014,14 +4029,24 @@ sub awarded { if (!defined($part)) { $part = '0'; } return $self->{NAV_MAP}->{STUDENT_DATA}->{$self->symb()}->{'resource.'.$part.'.awarded'}; } +# this should work exactly like the copy in lonhomework.pm sub duedate { (my $self, my $part) = @_; + my $date; my $interval=$self->parmval("interval", $part); - if ($interval) { + my $due_date=$self->parmval("duedate", $part); + if (defined($interval)) { my $first_access=&Apache::lonnet::get_first_access('map',$self->symb); - if ($first_access) { return ($first_access+$interval); } + if (defined($first_access)) { + $interval = $first_access+$interval; + $date = ($interval < $due_date)? $interval : $due_date; + } else { + $date = $due_date; + } + } else { + $date = $due_date; } - return $self->parmval("duedate", $part); + return $date; } sub handgrade { (my $self, my $part) = @_; @@ -4258,7 +4283,7 @@ sub countResponses { sub responseTypes { my $self = shift; my %responses; - foreach my $part ($self->parts()) { + foreach my $part (@{$self->parts()}) { foreach my $responsetype ($self->responseType($part)) { $responses{$responsetype}++ if (defined($responsetype)); } @@ -4369,9 +4394,9 @@ sub extractParts { # So we have to use our knowlege of part names to figure out # where the part names begin and end, and even then, it is possible # to construct ambiguous situations. - foreach (split /,/, $metadata) { - if ($_ =~ /^([a-zA-Z]+)response_(.*)/ - || $_ =~ /^(Task)_(.*)/) { + foreach my $data (split /,/, $metadata) { + if ($data =~ /^([a-zA-Z]+)response_(.*)/ + || $data =~ /^(Task)_(.*)/) { my $responseType = $1; my $partStuff = $2; my $partIdSoFar = ''; @@ -4383,8 +4408,15 @@ sub extractParts { if ($parts{$partIdSoFar}) { my @otherChunks = @partChunks[$i+1..$#partChunks]; my $responseId = join('_', @otherChunks); - push @{$responseIdHash{$partIdSoFar}}, $responseId; - push @{$responseTypeHash{$partIdSoFar}}, $responseType; + if ($self->is_task()) { + push(@{$responseIdHash{$partIdSoFar}}, + $partIdSoFar); + } else { + push(@{$responseIdHash{$partIdSoFar}}, + $responseId); + } + push(@{$responseTypeHash{$partIdSoFar}}, + $responseType); } } }