--- loncom/interface/lonnavmaps.pm 2010/09/13 03:07:56 1.440.2.2 +++ loncom/interface/lonnavmaps.pm 2011/09/22 12:48:40 1.464 @@ -1,7 +1,7 @@ # The LearningOnline Network with CAPA # Navigate Maps Handler # -# $Id: lonnavmaps.pm,v 1.440.2.2 2010/09/13 03:07:56 raeburn Exp $ +# $Id: lonnavmaps.pm,v 1.464 2011/09/22 12:48:40 raeburn Exp $ # # Copyright Michigan State University Board of Trustees @@ -478,11 +478,12 @@ use Apache::loncommon(); use Apache::lonenc(); use Apache::lonlocal; use Apache::lonnet; + use POSIX qw (floor strftime); use Time::HiRes qw( gettimeofday tv_interval ); use LONCAPA; use DateTime(); - +use Data::Dumper; # symbolic constants sub SYMB { return 1; } sub URL { return 2; } @@ -492,7 +493,7 @@ sub NOTHING { return 3; } my $resObj = "Apache::lonnavmaps::resource"; -# Keep these mappings in sync with lonquickgrades, which uses the colors +# Keep these mappings in sync with lonquickgrades, which usesthe colors # instead of the icons. my %statusIconMap = ( @@ -508,7 +509,7 @@ my %statusIconMap = my %iconAltTags = #texthash does not work here ( 'navmap.correct.gif' => 'Correct', 'navmap.wrong.gif' => 'Incorrect', - 'navmap.open.gif' => 'Open', + 'navmap.open.gif' => 'Is Open', 'navmap.partial.gif' => 'Partially Correct', 'navmap.ellipsis.gif' => 'Attempted', ); @@ -527,6 +528,7 @@ my %colormap = $resObj->OPEN => '', $resObj->NOTHING_SET => '', $resObj->ATTEMPTED => '', + $resObj->CREDIT_ATTEMPTED => '', $resObj->ANSWER_SUBMITTED => '', $resObj->PARTIALLY_CORRECT => '#006600' ); @@ -537,35 +539,6 @@ my $hurryUpColor = "#FF0000"; my $future_slots_checked = 0; my $future_slots = 0; -sub close { - if ($env{'environment.remotenavmap'} ne 'on') { return ''; } - return(< -window.status='Accessing Nav Control'; -menu=window.open("/adm/rat/empty.html","loncapanav", - "height=600,width=400,scrollbars=1"); -window.status='Closing Nav Control'; -menu.close(); -window.status='Done.'; - -ENDCLOSE -} - -sub update { - if ($env{'environment.remotenavmap'} ne 'on') { return ''; } - if (!$env{'request.course.id'}) { return ''; } - if ($ENV{'REQUEST_URI'}=~m|^/adm/navmaps|) { return ''; } - return(< - -ENDUPDATE -} - - sub addToFilter { my $hashIn = shift; my $addition = shift; @@ -636,10 +609,10 @@ sub getDescription { return &mt("Having technical difficulties; please check status later"); } if ($status == $res->NOTHING_SET) { - return &mt("Not currently assigned."); + return &Apache::lonhtmlcommon::direct_parm_link(&mt("Not currently assigned.",$res->symb(),'opendate'),$part); } if ($status == $res->OPEN_LATER) { - return &mt("Open ") .timeToHumanString($open,'start'); + 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'})) { @@ -673,38 +646,43 @@ sub getDescription { if ($status == $res->OPEN) { if ($due) { if ($res->is_practice()) { - return &mt("Closes ")." " .timeToHumanString($due,'start'); + return &mt("Closes [_1]",&Apache::lonhtmlcommon::direct_parm_link(&timeToHumanString($due,'start')),$res->symb(),'duedate',$part); } else { - return &mt("Due")." " .timeToHumanString($due,'end'); + return &mt("Due [_1]",&Apache::lonhtmlcommon::direct_parm_link(&timeToHumanString($due,'end')),$res->symb(),'duedate',$part); } } else { - return &mt("Open, no due date"); + 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")." " .timeToHumanString($answer,'start'); + 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")." " . timeToHumanString($due,'start'); + return &mt("Closed [_1]",&Apache::lonhtmlcommon::direct_parm_link(&timeToHumanString($due,'start')),$res->symb(),'answerdate,duedate',$part); } else { - return &mt("Was due")." " . timeToHumanString($due,'end'); + 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) && $res->handgrade($part) ne 'yes') { - return &mt("Answer available"); + return &Apache::lonhtmlcommon::direct_parm_link(&mt("Answer available"),$res->symb(),'answerdate,duedate',$part); } if ($status == $res->EXCUSED) { return &mt("Excused by instructor"); } if ($status == $res->ATTEMPTED) { - if ($res->src() eq '/res/gci/gci/internal/submission.problem') { - return &mt('Question(s) submitted for review'); + if ($res->is_anonsurvey($part) || $res->is_survey($part)) { + return &mt("Survey submission recorded"); } else { return &mt("Answer submitted, not yet graded"); } } + if ($status == $res->CREDIT_ATTEMPTED) { + if ($res->is_anonsurvey($part) || $res->is_survey($part)) { + return &mt("Credit for survey submission"); + } + } if ($status == $res->TRIES_LEFT) { my $tries = $res->tries($part); my $maxtries = $res->maxtries($part); @@ -716,18 +694,14 @@ sub getDescription { } } if ($due) { - return &mt("Due")." " . timeToHumanString($due,'end') . + return &mt("Due [_1]",&Apache::lonhtmlcommon::direct_parm_link(&timeToHumanString($due,'end')),$res->symb(),'duedate',$part) . " $triesString"; } else { - return &mt("No due date")." $triesString"; + return &Apache::lonhtmlcommon::direct_parm_link(&mt("No due date"),$res->symb(),'duedate',$part)." $triesString"; } } if ($status == $res->ANSWER_SUBMITTED) { - if ($res->src() eq '/res/gci/gci/internal/submission.problem') { - return &mt('Question(s) submitted for review'); - } else { - return &mt('Answer submitted'); - } + return &mt('Answer submitted'); } } @@ -805,14 +779,31 @@ sub timeToHumanString { # Less than an hour if ( $delta < $hour ) { - # If so, use minutes + # If so, use minutes; or minutes, seconds (if format requires) my $minutes = floor($delta / 60); + if (($format ne '') && ($format =~ /\%(T|S)/)) { + my $display; + if ($minutes == 1) { + $display = "${prefix}1 minute"; + } else { + $display = "$prefix$minutes minutes"; + } + my $seconds = $delta % $minute; + if ($seconds == 0) { + $display .= $tense; + } elsif ($seconds == 1) { + $display .= ", 1 second$tense"; + } else { + $display .= ", $seconds seconds$tense"; + } + return $display; + } if ($minutes == 1) { return "${prefix}1 minute$tense"; } return "$prefix$minutes minutes$tense"; } # Is it less than 24 hours away? If so, - # display hours + minutes + # display hours + minutes, (and + seconds, if format specified it) if ( $delta < $hour * 24) { my $hours = floor($delta / $hour); my $minutes = floor(($delta % $hour) / $minute); @@ -827,15 +818,30 @@ sub timeToHumanString { if ($minutes == 0) { $minuteString = ""; } + if (($format ne '') && ($format =~ /\%(T|S)/)) { + my $display = "$prefix$hourString$minuteString"; + my $seconds = $delta-(($hours * $hour)+($minutes * $minute)); + if ($seconds == 0) { + $display .= $tense; + } elsif ($seconds == 1) { + $display .= ", 1 second$tense"; + } else { + $display .= ", $seconds seconds$tense"; + } + return $display; + } return "$prefix$hourString$minuteString$tense"; } + # Date/time is more than 24 hours away + my $dt = DateTime->from_epoch(epoch => $time) ->set_time_zone(&Apache::lonlocal::gettimezone()); - # If there's a caller supplied format, use it. + # If there's a caller supplied format, use it, unless it only displays + # H:M:S or H:M. - if ($format ne '') { + if (($format ne '') && ($format ne '%T') && ($format ne '%R')) { my $timeStr = $dt->strftime($format); return $timeStr.' ('.$dt->time_zone_short_name().')'; } @@ -971,10 +977,10 @@ sub render_resource { } if ($resource->randomout()) { - $nonLinkedText .= ' ('.&mt('hidden').') '; + $nonLinkedText .= ' ('.&mt('hidden').') '; } if (!$resource->condval()) { - $nonLinkedText .= ' ('.&mt('conditionally hidden').') '; + $nonLinkedText .= ' ('.&mt('conditionally hidden').') '; } if (($resource->is_practice()) && ($resource->is_raw_problem())) { $nonLinkedText .=' '.&mt('not graded').''; @@ -1018,12 +1024,8 @@ sub render_resource { $nonLinkedText .= ' ('.&mt('[_1] parts', $resource->countParts()).')'; } - my $target; - if ($env{'environment.remotenavmap'} eq 'on') { - $target=' target="loncapaclient" '; - } if (!$params->{'resource_nolink'} && !$resource->is_sequence() && !$resource->is_empty_sequence) { - $result .= "$curMarkerBegin$title$partLabel$curMarkerEnd$nonLinkedText"; + $result .= "$curMarkerBegin$title$partLabel$curMarkerEnd$nonLinkedText"; } else { $result .= "$curMarkerBegin$linkopen$title$partLabel$curMarkerEnd$nonLinkedText"; } @@ -1036,16 +1038,12 @@ sub render_communication_status { my $discussionHTML = ""; my $feedbackHTML = ""; my $errorHTML = ""; my $link = $params->{"resourceLink"}; - my $target; - if ($env{'environment.remotenavmap'} eq 'on') { - $target=' target="loncapaclient" '; - } - my $linkopen = ""; + my $linkopen = ""; my $linkclose = ""; my $location=&Apache::loncommon::lonhttpdurl("/adm/lonMisc"); if ($resource->hasDiscussion()) { $discussionHTML = $linkopen . - ''.&mt('New Discussion').'' . + ''.&mt('New Discussion').'' . $linkclose; } @@ -1053,9 +1051,9 @@ sub render_communication_status { my $feedback = $resource->getFeedback(); foreach my $msgid (split(/\,/, $feedback)) { if ($msgid) { - $feedbackHTML .= ' ' - . ''.&mt('New E-mail').''; + . ''.&mt('New E-mail').''; } } } @@ -1067,9 +1065,9 @@ sub render_communication_status { last if ($errorcount>=10); # Only output 10 bombs maximum if ($msgid) { $errorcount++; - $errorHTML .= ' ' - . ''.&mt('New Error').''; + . ''.&mt('New Error').''; } } } @@ -1087,11 +1085,7 @@ sub render_quick_status { $params->{'multipart'} && $part eq "0"; my $link = $params->{"resourceLink"}; - my $target; - if ($env{'environment.remotenavmap'} eq 'on') { - $target=' target="loncapaclient" '; - } - my $linkopen = ""; + my $linkopen = ""; my $linkclose = ""; $result .= ''; @@ -1129,7 +1123,7 @@ sub render_long_status { } if ($resource->kind() eq "res" && - ($resource->is_problem() || $resource->is_practice()) && + $resource->is_raw_problem() && !$firstDisplayed) { if ($color) {$result .= ""; } $result .= getDescription($resource, $part); @@ -1444,19 +1438,22 @@ sub render { if ($printCloseAll && !$args->{'resource_no_folder_link'}) { my ($link,$text); if ($condition) { - $link='"navmaps?condition=0&filter=&'.$queryString. - '&here='.&escape($here).'"'; + $link='navmaps?condition=0&filter=&'.$queryString. + '&here='.&escape($here); $text='Close all folders'; } else { - $link='"navmaps?condition=1&filter=&'.$queryString. - '&here='.&escape($here).'"'; + $link='navmaps?condition=1&filter=&'.$queryString. + '&here='.&escape($here); $text='Open all folders'; } + if ($env{'form.register'}) { + $link .= '&register='.$env{'form.register'}; + } if ($args->{'caller'} eq 'navmapsdisplay') { &add_linkitem($args->{'linkitems'},'changefolder', - 'location.href='.$link,$text); + "location.href='$link'",$text); } else { - $result.=''.&mt($text).''; + $result.= ''.&mt($text).''; } $result .= "\n"; } @@ -1472,6 +1469,9 @@ sub render { END + if ($env{'form.register'}) { + $result .= ''; + } if ($args->{'sort'} eq 'discussion') { my $totdisc = 0; my $haveDisc = ''; @@ -1493,26 +1493,16 @@ END $result.=''; } - if ($args->{'caller'} eq 'navmapsdisplay') { $result .= ''; - if ($env{'environment.remotenavmap'} ne 'on') { $result .= ''; - } else { - $result .= ''; - } - $result.=""; + $result.=''; $result.=&show_linkitems_toolbar($args->{'linkitems'}); if ($args->{'sort_html'}) { - if ($env{'environment.remotenavmap'} ne 'on') { - $result.=''. - ''; - } else { - $result.=''; - } - } + $result.=''. + ''; + } $result .= '
'. &Apache::loncommon::help_open_menu('Navigation Screen','Navigation_Screen',undef,'RAT').' 
".mt('Tools:')."'.&mt('Tools:').'   '.$args->{'sort_html'}.'

'. - $args->{'sort_html'}.'
   '.$args->{'sort_html'}.'
'; } elsif ($args->{'sort_html'}) { $result.=$args->{'sort_html'}; @@ -1763,7 +1753,7 @@ END if (defined($anchor)) { $anchor='#'.$anchor; } my $srcHasQuestion = $src =~ /\?/; $args->{"resourceLink"} = $src. - ($srcHasQuestion?'&':'?') . + ($srcHasQuestion?'&':'?') . 'symb=' . &escape($symb).$anchor; } # Now, we've decided what parts to show. Loop through them and @@ -1825,12 +1815,11 @@ END # it's quite likely this might fix other browsers, too, and # certainly won't hurt anything. if ($displayedJumpMarker) { - $result .= " -"; +"); } $result.=&Apache::loncommon::end_data_table(); @@ -1850,71 +1839,38 @@ sub add_linkitem { $$linkitems{$name}{'text'}=&mt($text); } -sub show_linkitems { - my ($linkitems)=@_; - my @linkorder = ("blank","launchnav","closenav","firsthomework", - "everything","uncompleted","changefolder","clearbubbles"); - - my $result .= (< - -
-   -
'."\n"; - - return $result; -} - sub show_linkitems_toolbar { my ($linkitems,$condition)=@_; - my @linkorder = ("blank","launchnav","closenav","firsthomework", - "everything","uncompleted","changefolder","clearbubbles"); - - my $result .=' - - '."\n
    "; - foreach my $link (@linkorder) { - my $link_id = "LC_content_toolbar_".$link; - if (defined($linkitems->{$link})) { - if ($linkitems->{$link}{'text'} ne '') { - $linkitems->{$link}{'cmd'}=~s/"/'/g; - if($linkitems->{$link}{'cmd'}){ - if($link eq 'changefolder'){ - if($condition){$link_id='LC_content_toolbar_changefolder_toggled'} - else{$link_id='LC_content_toolbar_changefolder'} - } - $result .= '
  • '."\n"; - } - - } - } + my @linkorder = ('firsthomework','everything','uncompleted', + 'changefolder','clearbubbles'); + my $result .=''."\n". + ''."\n". + '
      '; + foreach my $link (@linkorder) { + my $link_id = 'LC_content_toolbar_'.$link; + if (defined($linkitems->{$link})) { + if ($linkitems->{$link}{'text'} ne '') { + $linkitems->{$link}{'cmd'}=~s/"/'/g; + if ($linkitems->{$link}{'cmd'}) { + if ($link eq 'changefolder') { + if ($condition) { + $link_id='LC_content_toolbar_changefolder_toggled'; + } else { + $link_id='LC_content_toolbar_changefolder'; + } + } + $result .= '
    • '. + '
    • '."\n"; + } + } + } } - $result .= '
    '; - $result .= '
    '."\n"; - + $result .= '
'. + '
'."\n"; return $result; } @@ -2006,6 +1962,9 @@ sub new { my $class = ref($proto) || $proto; my $self = {}; + $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} = {}; @@ -2044,8 +2003,9 @@ sub generate_course_user_opt { my $self = shift; if ($self->{COURSE_USER_OPT_GENERATED}) { return; } - my $uname=$env{'user.name'}; - my $udom=$env{'user.domain'}; + my $uname=$self->{USERNAME}; + my $udom=$self->{DOMAIN}; + my $cid=$env{'request.course.id'}; my $cdom=$env{'course.'.$cid.'.domain'}; my $cnum=$env{'course.'.$cid.'.num'}; @@ -2088,7 +2048,7 @@ sub generate_email_discuss_status { my $cdom=$env{'course.'.$cid.'.domain'}; my $cnum=$env{'course.'.$cid.'.num'}; - my %emailstatus = &Apache::lonnet::dump('email_status'); + my %emailstatus = &Apache::lonnet::dump('email_status',$self->{DOMAIN},$self->{USERNAME}); my $logoutTime = $emailstatus{'logout'}; my $courseLeaveTime = $emailstatus{'logout_'.$env{'request.course.id'}}; $self->{LAST_CHECK} = (($courseLeaveTime > $logoutTime) ? @@ -2096,7 +2056,7 @@ sub generate_email_discuss_status { my %discussiontime = &Apache::lonnet::dump('discussiontimes', $cdom, $cnum); my %lastread = &Apache::lonnet::dump('nohist_'.$cid.'_discuss', - $env{'user.domain'},$env{'user.name'},'lastread'); + $self->{DOMAIN},$self->{USERNAME},'lastread'); my %lastreadtime = (); foreach my $key (keys %lastread) { my $shortkey = $key; @@ -2106,8 +2066,8 @@ sub generate_email_discuss_status { my %feedback=(); my %error=(); - my @keys = &Apache::lonnet::getkeys('nohist_email',$env{'user.domain'}, - $env{'user.name'}); + my @keys = &Apache::lonnet::getkeys('nohist_email',$self->{DOMAIN}, + $self->{USERNAME}); foreach my $msgid (@keys) { if ((!$emailstatus{$msgid}) || ($emailstatus{$msgid} eq 'new')) { @@ -2155,8 +2115,8 @@ sub get_user_data { # Retrieve performance data on problems my %student_data = Apache::lonnet::currentdump($env{'request.course.id'}, - $env{'user.domain'}, - $env{'user.name'}); + $self->{DOMAIN}, + $self->{USERNAME}); $self->{STUDENT_DATA} = \%student_data; $self->{RETRIEVED_USER_DATA} = 1; @@ -2470,7 +2430,7 @@ sub parmval { my $self = shift; my ($what,$symb,$recurse)=@_; my $hashkey = $what."|||".$symb; - + my $cache = $self->{PARM_CACHE}; if (defined($self->{PARM_CACHE}->{$hashkey})) { if (ref($self->{PARM_CACHE}->{$hashkey}) eq 'ARRAY') { if (defined($self->{PARM_CACHE}->{$hashkey}->[0])) { @@ -2507,8 +2467,8 @@ sub parmval_real { @cgrps = sort(@cgrps); $cgroup = $cgrps[0]; } - my $uname=$env{'user.name'}; - my $udom=$env{'user.domain'}; + my $uname=$self->{USERNAME}; + my $udom=$self->{DOMAIN}; unless ($symb) { return ['']; } my $result=''; @@ -2655,7 +2615,7 @@ in the filter function. Retrieves version infomation for a url. Returns the version (a number, or the string "mostrecent") for resources which have version information in the big hash. - + =cut @@ -2910,6 +2870,9 @@ sub new { weaken($self->{NAV_MAP} = shift); return undef unless ($self->{NAV_MAP}); + $self->{USERNAME} = $self->{NAV_MAP}->{USERNAME}; + $self->{DOMAIN} = $self->{NAV_MAP}->{DOMAIN}; + # Handle the parameters $self->{FIRST_RESOURCE} = shift || $self->{NAV_MAP}->firstResource(); $self->{FINISH_RESOURCE} = shift || $self->{NAV_MAP}->finishResource(); @@ -3283,6 +3246,9 @@ sub new { weaken($self->{NAV_MAP} = shift); return undef unless ($self->{NAV_MAP}); + $self->{USERNAME} = $self->{NAV_MAP}->{USERNAME}; + $self->{DOMAIN} = $self->{NAV_MAP}->{DOMAIN}; + $self->{FIRST_RESOURCE} = shift || $self->{NAV_MAP}->firstResource(); $self->{FINISH_RESOURCE} = shift || $self->{NAV_MAP}->finishResource(); @@ -3519,6 +3485,9 @@ sub new { weaken($self->{NAV_MAP} = shift); $self->{ID} = shift; + $self->{USERNAME} = $self->{NAV_MAP}->{USERNAME}; + $self->{DOMAIN} = $self->{NAV_MAP}->{DOMAIN}; + # Store this new resource in the parent nav map's cache. $self->{NAV_MAP}->{RESOURCE_CACHE}->{$self->{ID}} = $self; $self->{RESOURCE_ERROR} = 0; @@ -3540,7 +3509,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 (ref($self) && ref($self->{NAV_MAP}) && defined($arg)) { + return $self->{NAV_MAP}->navhash($arg); + } + return; } =pod @@ -3783,6 +3756,33 @@ sub is_problem { } return 0; } +# +# The has below is the set of status that are considered 'incomplete' +# +my %incomplete_hash = +( + TRIES_LEFT() => 1, + OPEN() => 1, + ATTEMPTED() => 1 + + ); +# +# Return tru if a problem is incomplete... for now incomplete means that +# any part of the problem is incomplete. +# Note that if the resources is not a problem, 0 is returned. +# +sub is_incomplete { + my $self = shift; + if ($self->is_problem()) { + foreach my $part (@{$self->parts()}) { + if (exists($incomplete_hash{$self->status($part)})) { + return 1; + } + } + } + return 0; + +} sub is_raw_problem { my $self=shift; my $src = $self->src(); @@ -3818,7 +3818,7 @@ sub is_survey { my $self = shift(); my $part = shift(); my $type = $self->parmval('type',$part); - if ($type eq 'survey') { + if (($type eq 'survey') || ($type eq 'surveycred')) { return 1; } if ($self->src() =~ /\.(survey)$/) { @@ -3826,6 +3826,15 @@ sub is_survey { } return 0; } +sub is_anonsurvey { + my $self = shift(); + my $part = shift(); + my $type = $self->parmval('type',$part); + if (($type eq 'anonsurvey') || ($type eq 'anonsurveycred')) { + return 1; + } + return 0; +} sub is_task { my $self=shift; my $src = $self->src(); @@ -3950,7 +3959,17 @@ their code.) =over 4 -=item * B: +=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 +entire resource printable. + +=item * B Get the Client IP/Name Access Control information. @@ -4003,6 +4022,55 @@ 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 $end = $self->parmval("printenddate", $part); + + # The following cases apply: + # - No dates set: Printable. + # - Start date set but no end date: Printable if now >= start date. + # - End date set but no start date: Printable if now <= end date. + # - both defined: printable if start <= now <= end + # + my $now = time(); + + my $startok = 1; + my $endok = 1; + + if ((defined $start) && ($start ne '')) { + $startok = $start <= $now; + } + if ((defined $end) && ($end != '')) { + $endok = $end >= $now; + } + return $startok && $endok; +} + +sub resprintable { + my $self = shift; + + # get parts...or realize there are no parts. + + my $partsref = $self->parts(); + my @parts = @$partsref; + + if ((!defined(@parts)) || (scalar(@parts) == 0)) { + return $self->printable(0); + } else { + foreach my $part (@parts) { + if (!$self->printable($part)) { + return 0; + } + } + return 1; + } +} + sub acc { (my $self, my $part) = @_; my $acc = $self->parmval("acc", $part); @@ -4055,6 +4123,11 @@ sub checkedin { } } # this should work exactly like the copy in lonhomework.pm +# Why is there a copy in lonhomework? Why not centralized? +# +# TODO: Centralize duedate. +# + sub duedate { (my $self, my $part) = @_; my $date; @@ -4134,8 +4207,8 @@ sub weight { my $self = shift; my $part = shift; if (!defined($part)) { $part = '0'; } my $weight = &Apache::lonnet::EXT('resource.'.$part.'.weight', - $self->symb(), $env{'user.domain'}, - $env{'user.name'}, + $self->symb(), $self->{DOMAIN}, + $self->{USERNAME}, $env{'request.course.sec'}); return $weight; } @@ -4163,7 +4236,7 @@ sub getReturnHash { my $self = shift; if (!defined($self->{RETURN_HASH})) { - my %tmpHash = &Apache::lonnet::restore($self->symb()); + my %tmpHash = &Apache::lonnet::restore($self->symb(),undef,$self->{DOMAIN},$self->{USERNAME}); $self->{RETURN_HASH} = \%tmpHash; } } @@ -4675,6 +4748,10 @@ Information not available due to network Attempted, and not yet graded. +=item * B: + +Attempted, and credit received for attempt (survey and anonymous survey only). + =back =cut @@ -4686,6 +4763,7 @@ sub CORRECT { return 13; } sub CORRECT_BY_OVERRIDE { return 14; } sub EXCUSED { return 15; } sub ATTEMPTED { return 16; } +sub CREDIT_ATTEMPTED { return 17; } sub getCompletionStatus { my $self = shift; @@ -4704,6 +4782,13 @@ sub getCompletionStatus { if ($status eq 'incorrect_by_override') {return $self->INCORRECT_BY_OVERRIDE; } if ($status eq 'excused') {return $self->EXCUSED; } if ($status eq 'ungraded_attempted') {return $self->ATTEMPTED; } + if ($status eq 'credit_attempted') { + if ($self->is_anonsurvey($part) || $self->is_survey($part)) { + return $self->CREDIT_ATTEMPTED; + } else { + return $self->ATTEMPTED; + } + } return $self->NOT_ATTEMPTED; } @@ -4793,6 +4878,10 @@ The item is open and not yet tried. The problem has been attempted. +=item * B: + +The problem has been attempted, and credit given for the attempt (survey and anonymous survey only). + =item * B: An answer has been submitted, but the student should not see it. @@ -4866,6 +4955,10 @@ sub status { return ATTEMPTED; } + if ($completionStatus == CREDIT_ATTEMPTED) { + return CREDIT_ATTEMPTED; + } + # If it's EXCUSED, then return that no matter what if ($completionStatus == EXCUSED) { return EXCUSED; @@ -4968,7 +5061,7 @@ sub check_for_slot { my $taskstatus = $self->taskstatus(); $is_correct = (($taskstatus eq 'pass') || ($self->solved() =~ /^correct_/)); - $got_grade = ($self->solved() =~ /^(?:pass|fail)$/); + $got_grade = ($taskstatus =~ /^(?:pass|fail)$/); } else { $got_grade = 1; $is_correct = ($self->solved() =~ /^correct_/); @@ -5058,6 +5151,7 @@ my %compositeToSimple = INCORRECT() => INCORRECT, OPEN() => OPEN, ATTEMPTED() => ATTEMPTED, + CREDIT_ATTEMPTED() => CORRECT, ANSWER_SUBMITTED() => ATTEMPTED ); @@ -5132,6 +5226,7 @@ sub completable { # and it is not "attempted" (manually graded problem), it is # not "complete" if ($self->getCompletionStatus($part) == ATTEMPTED() || + $self->getCompletionStatus($part) == CREDIT_ATTEMPTED() || $status == ANSWER_SUBMITTED() ) { # did this part already, as well as we can next;