--- loncom/interface/lonnavmaps.pm 2008/12/06 20:36:51 1.420 +++ loncom/interface/lonnavmaps.pm 2010/02/10 16:45:31 1.423.2.3 @@ -1,7 +1,7 @@ # The LearningOnline Network with CAPA # Navigate Maps Handler # -# $Id: lonnavmaps.pm,v 1.420 2008/12/06 20:36:51 schafran Exp $ +# $Id: lonnavmaps.pm,v 1.423.2.3 2010/02/10 16:45:31 raeburn Exp $ # # Copyright Michigan State University Board of Trustees # @@ -31,7 +31,7 @@ =head1 NAME -Apache::lonnavmaps.pm +Apache::lonnavmaps - Subroutines to handle and render the navigation =head1 SYNOPSIS @@ -530,6 +530,9 @@ 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 close { if ($env{'environment.remotenavmap'} ne 'on') { return ''; } return(<symb()); if ($map=~/\.page$/) { my $url=&Apache::lonnet::clutter($map); - $anchor=&escape($src->shown_symb()); + $anchor=&escape($res->shown_symb()); return ($url,$res->shown_symb(),$anchor); } } @@ -634,6 +637,35 @@ sub getDescription { if ($status == $res->OPEN_LATER) { return &mt("Open ") .timeToHumanString($open,'start'); } + if ($res->simpleStatus($part) == $res->OPEN) { + unless (&Apache::lonnet::allowed('mgr',$env{'request.course.id'})) { + my ($slot_status,$slot_time,$slot_name)=$res->check_for_slot($part); + if ($slot_status == $res->UNKNOWN) { + return &mt('Reservation status unknown'); + } elsif ($slot_status == $res->RESERVED) { + return &mt('Reserved - ends [_1]', + timeToHumanString($slot_time,'end')); + } elsif ($slot_status == $res->RESERVED_LOCATION) { + return &mt('Reserved - specific location(s) - ends [_1]', + timeToHumanString($slot_time,'end')); + } elsif ($slot_status == $res->RESERVED_LATER) { + return &mt('Reserved - next open [_1]', + timeToHumanString($slot_time,'start')); + } elsif ($slot_status == $res->RESERVABLE) { + return &mt('Reservable ending [_1]', + timeToHumanString($slot_time,'end')); + } elsif ($slot_status == $res->RESERVABLE_LATER) { + return &mt('Reservable starting [_1]', + timeToHumanString($slot_time,'start')); + } elsif ($slot_status == $res->NOT_IN_A_SLOT) { + return &mt('Reserve a time/place to work'); + } elsif ($slot_status == $res->NOTRESERVABLE) { + return &mt('Reservation not available'); + } elsif ($slot_status == $res->WAITING_FOR_GRADE) { + return &mt('Submission in grading queue'); + } + } + } if ($status == $res->OPEN) { if ($due) { if ($res->is_practice()) { @@ -670,7 +702,7 @@ sub getDescription { my $maxtries = $res->maxtries($part); my $triesString = ""; if ($tries && $maxtries) { - $triesString = '('.&mt('[_1] of [_2] tries used',$tries,$maxtries).')'; + $triesString = '('.&mt('[_1] of [quant,_2,try,tries] used',$tries,$maxtries).')'; if ($maxtries > 1 && $maxtries - $tries == 1) { $triesString = "$triesString"; } @@ -848,11 +880,6 @@ sub render_resource { my $link = $params->{"resourceLink"}; # The URL part is not escaped at this point, but the symb is... - # The stuff to the left of the ? must have ' replaced by \' since - # it will be quoted with ' in the href. - - my ($left,$right) = split(/\?/, $link); - $link = $left.'?'.$right; my $src = $resource->src(); my $it = $params->{"iterator"}; @@ -865,7 +892,8 @@ sub render_resource { my $location=&Apache::loncommon::lonhttpdurl("/adm/lonIcons"); # If this is a new branch, label it so if ($params->{'isNewBranch'}) { - $newBranchText = "Branch"; + $newBranchText = ''.
+                         &mt('Branch').''; } # links to open and close the folder @@ -1269,7 +1297,7 @@ sub render { if (!defined($navmap)) { $navmap = Apache::lonnavmaps::navmap->new(); if (!defined($navmap)) { - # no londer in course + # no longer in course return ''.&mt('No course selected').'
'.&mt('Select a course').'
'; } @@ -1337,6 +1365,11 @@ sub render { # Step 1: Check to see if we have a navmap if (!defined($navmap)) { $navmap = Apache::lonnavmaps::navmap->new(); + if (!defined($navmap)) { + # no longer in course + return ''.&mt('No course selected').'
+ '.&mt('Select a course').'
'; + } } # See if we're being passed a specific map @@ -1389,15 +1422,15 @@ sub render { my $location=&Apache::loncommon::lonhttpdurl("/adm/lonMisc"); if ($navmap->{LAST_CHECK}) { $result .= - ' '.&mt('New discussion since').' '. + ' '.&mt('New discussion since').' '. strftime("%A, %b %e at %I:%M %P", localtime($navmap->{LAST_CHECK})). '  '. - ' '.&mt('New message (click to open)').'

'. + ' '.&mt('New message (click to open)').'

'. ''; } else { $result .= '  '. - ' '.&mt('Discussions').''. - '   '.&mt('New message (click to open)'). + ' '.&mt('Discussions').''. + '   '.&mt('New message (click to open)'). ''; } @@ -1828,7 +1861,7 @@ ENDBLOCK $result.='}

- '."\n"; foreach my $link (@linkorder) { if (defined($linkitems->{$link})) { if ($linkitems->{$link}{'text'} ne '') { @@ -1839,7 +1872,7 @@ ENDBLOCK } $result .= '  -
'."\n"; + '."\n"; return $result; } @@ -3465,7 +3498,11 @@ sub navHash { my $self = shift; my $param = shift; my $id = shift; - return $self->{NAV_MAP}->navhash($param . ($id?$self->{ID}:"")); + my $arg = $param . ($id?$self->{ID}:""); + if (defined($arg)) { + return $self->{NAV_MAP}->navhash($arg); + } + return; } =pod @@ -3939,6 +3976,35 @@ sub awarded { if (!defined($part)) { $part = '0'; } return $self->{NAV_MAP}->{STUDENT_DATA}->{$self->symb()}->{'resource.'.$part.'.awarded'}; } +sub taskversion { + my $self = shift; my $part = shift; + $self->{NAV_MAP}->get_user_data(); + if (!defined($part)) { $part = '0'; } + return $self->{NAV_MAP}->{STUDENT_DATA}->{$self->symb()}->{'resource.'.$part.'.version'}; +} +sub taskstatus { + my $self = shift; my $part = shift; + $self->{NAV_MAP}->get_user_data(); + if (!defined($part)) { $part = '0'; } + return $self->{NAV_MAP}->{STUDENT_DATA}->{$self->symb()}->{'resource.'.$self->taskversion($part).'.'.$part.'.status'}; +} +sub solved { + my $self = shift; my $part = shift; + $self->{NAV_MAP}->get_user_data(); + if (!defined($part)) { $part = '0'; } + return $self->{NAV_MAP}->{STUDENT_DATA}->{$self->symb()}->{'resource.'.$part.'.solved'}; +} +sub checkedin { + my $self = shift; my $part = shift; + $self->{NAV_MAP}->get_user_data(); + if (!defined($part)) { $part = '0'; } + if ($self->is_task()) { + my $version = $self->taskversion($part); + return ($self->{NAV_MAP}->{STUDENT_DATA}->{$self->symb()}->{'resource.'.$version .'.'.$part.'.checkedin'},$self->{NAV_MAP}->{STUDENT_DATA}->{$self->symb()}->{'resource.'.$version .'.'.$part.'.checkedin.slot'}); + } else { + return ($self->{NAV_MAP}->{STUDENT_DATA}->{$self->symb()}->{'resource.'.$part.'.checkedin'},$self->{NAV_MAP}->{STUDENT_DATA}->{$self->symb()}->{'resource.'.$part.'.checkedin.slot'}); + } +} # this should work exactly like the copy in lonhomework.pm sub duedate { (my $self, my $part) = @_; @@ -4034,6 +4100,14 @@ sub part_display { } return $display; } +sub slot_control { + my $self=shift(); my $part = shift(); + if (!defined($part)) { $part = '0'; } + my $useslots = $self->parmval("useslots", $part); + my $availablestudent = $self->parmval("availablestudent", $part); + my $available = $self->parmval("available", $part); + return ($useslots,$availablestudent,$available); +} # Multiple things need this sub getReturnHash { @@ -4682,6 +4756,17 @@ sub TRIES_LEFT { return 20; } sub ANSWER_SUBMITTED { return 21; } sub PARTIALLY_CORRECT{ return 22; } +sub RESERVED_LATER { return 30; } +sub RESERVED { return 31; } +sub RESERVED_LOCATION { return 32; } +sub RESERVABLE { return 33; } +sub RESERVABLE_LATER { return 34; } +sub NOTRESERVABLE { return 35; } +sub NOT_IN_A_SLOT { return 36; } +sub NEEDS_CHECKIN { return 37; } +sub WAITING_FOR_GRADE { return 38; } +sub UNKNOWN { return 39; } + sub status { my $self = shift; my $part = shift; @@ -4773,6 +4858,108 @@ sub status { return OPEN; } +sub check_for_slot { + my $self = shift; + my $part = shift; + 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)); + my $cid=$env{'request.course.id'}; + my $cdom=$env{'course.'.$cid.'.domain'}; + my $cnum=$env{'course.'.$cid.'.num'}; + my $now = time; + 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 ($checkedin,$checkedinslot); + foreach my $slot_name (@sorted_slots) { + 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); + } + } + return (RESERVED,$end,$slot_name); + } + } else { + if ($start > $now) { + return (RESERVABLE,$startreserve,$slot_name); + } + } + } + } + } + my ($is_correct,$got_grade); + if ($self->is_task()) { + my $taskstatus = $self->taskstatus(); + $is_correct = (($taskstatus eq 'pass') || + ($self->solved() =~ /^correct_/)); + $got_grade = ($self->solved() =~ /^(?:pass|fail)$/); + } else { + $got_grade = 1; + $is_correct = ($self->solved() =~ /^correct_/); + } + ($checkedin,$checkedinslot) = $self->checkedin(); + if ($checkedin) { + if (!$got_grade) { + return (WAITING_FOR_GRADE); + } elsif ($is_correct) { + 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) { + 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 ++; + } + } + return $future_slots; +} + sub CLOSED { return 23; } sub ERROR { return 24; }