--- loncom/homework/lonhomework.pm 2025/01/17 15:05:47 1.394 +++ loncom/homework/lonhomework.pm 2025/06/28 14:35:00 1.395 @@ -1,7 +1,7 @@ # The LearningOnline Network with CAPA # The LON-CAPA Homework handler # -# $Id: lonhomework.pm,v 1.394 2025/01/17 15:05:47 raeburn Exp $ +# $Id: lonhomework.pm,v 1.395 2025/06/28 14:35:00 raeburn Exp $ # # Copyright Michigan State University Board of Trustees # @@ -600,10 +600,12 @@ sub check_access { return ('SHOW_ANSWER'); } } - foreach my $temp ("opendate","duedate","answerdate") { + foreach my $temp ("opendate","duedate","overduedate","answerdate") { $lastdate = $date; if ($temp eq 'duedate') { $date = &due_date($id,$symb); + } elsif ($temp eq 'overduedate') { + $date = &overdue_date($id,$symb); } else { $date = &Apache::lonnet::EXT("resource.$id.$temp",$symb); } @@ -644,6 +646,9 @@ sub check_access { } elsif ($type eq 'duedate') { $status='CAN_ANSWER'; $datemsg = &mt('is due at [_1]',$date); + } elsif ($type eq 'overduedate') { + $status='CAN_ANSWER'; + $datemsg = &mt('past-due grace period until [_1]',$date); } elsif ($type eq 'answerdate') { $status='CLOSED'; $datemsg = &mt('was due on [_1], and answers will be available on [_2]', @@ -734,6 +739,76 @@ sub due_date { return $date; } +sub overdue_date { + my ($part_id,$symb,$udom,$uname)=@_; + my $date; + my $duedate= &Apache::lonnet::EXT("resource.$part_id.duedate",$symb, + $udom,$uname); + if ($duedate ne '') { + my $grace = &Apache::lonnet::EXT("resource.$part_id.grace",$symb, + $udom,$uname); + if ($grace) { + my $grace_end = (split(/,/,$grace))[-1]; + my ($offset) = split(/:/,$grace_end,2); + if ($offset > 0) { + $date = $offset + $duedate; + } + } + } + return $date; +} + +sub partial_credit_overdue { + my ($part_id,$symb,$udom,$uname)=@_; + my $reduction; + my $duedate = &Apache::lonnet::EXT("resource.$part_id.duedate",$symb, + $udom,$uname); + if ($duedate) { + my $grace = &Apache::lonnet::EXT("resource.$part_id.grace",$symb, + $udom,$uname); + if ($grace) { + my $lateness = time - $duedate; + if ($lateness > 0) { + my ($start,$end,$startfrac,$endfrac,$usegrad); + $start = 0; + $startfrac = 1.0; + $usegrad = 0; + foreach my $item (split(/,/,$grace)) { + my ($offset,$frac,$grad) = split(/:/,$item); + if ($lateness > $offset) { + $start = $offset; + $startfrac = $frac; + next; + } elsif ($lateness <= $offset) { + $end = $offset; + $endfrac = $frac; + $usegrad = $grad; + last; + } + } + if ($end) { + if (($end == $start) || ($startfrac == $endfrac)) { + $reduction = $endfrac; + } elsif ($end - $start > 0) { + if (($endfrac <= 1.0) && ($endfrac >= 0)) { + $reduction = $endfrac; + if ($usegrad) { + my $decline = $startfrac - $endfrac; + my $fraction = ($lateness - $start)/($end - $start); + if (($fraction <= 1) && ($fraction >= 0)) { + my $value = $startfrac - ($decline*$fraction); + $reduction = sprintf("%.2f", $value); + } + } + } + } + } + } + } + } + return $reduction; +} + sub seconds_to_human_length { my ($length)=@_;