--- loncom/homework/lonhomework.pm 2023/07/23 16:11:52 1.378 +++ 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.378 2023/07/23 16:11:52 raeburn Exp $ +# $Id: lonhomework.pm,v 1.395 2025/06/28 14:35:00 raeburn Exp $ # # Copyright Michigan State University Board of Trustees # @@ -163,9 +163,19 @@ sub get_target { return ('web','answer'); } elsif (($env{'form.problemmode'} eq 'saveedit') || ($env{'form.problemmode'} eq 'undo')) { - return ('modified','no_output_web','edit'); + my %editors = &Apache::loncommon::permitted_editors(); + if ($editors{'edit'}) { + return ('modified','no_output_web','edit'); + } else { + return ('web'); + } } elsif ($env{'form.problemmode'} eq 'edit') { - return ('no_output_web','edit'); + my %editors = &Apache::loncommon::permitted_editors(); + if ($editors{'edit'}) { + return ('no_output_web','edit'); + } else { + return ('web'); + } } else { return ('web'); } @@ -590,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); } @@ -634,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]', @@ -724,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)=@_; @@ -939,7 +1024,7 @@ STATE sub analyze_header { my ($request) = @_; - my $js = &Apache::structuretags::setmode_javascript(); + my $js = &Apache::lonxml::setmode_javascript(); # Breadcrumbs my $text = 'Authoring Space'; @@ -964,18 +1049,26 @@ sub analyze_header { {'bread_crumbs' => $brcrum,}) .&Apache::loncommon::head_subbox( &Apache::loncommon::CSTR_pageheader()); + my %lt = &Apache::lonlocal::texthash( + edit => 'Edit', + editxml => 'EditXML', + ); $result .= '
'. ''. &Apache::structuretags::remember_problem_state().' -
- - -
+
'; + my %editors = &Apache::loncommon::permitted_editors(); + foreach my $item ('editxml','edit') { + next unless ($editors{$item}); + $result .= ''. + "\n"; + } + $result .= + '

@@ -1180,7 +1273,7 @@ sub editxmlmode { my $js = &Apache::edit::js_change_detection(). &Apache::loncommon::resize_textarea_js(). - &Apache::structuretags::setmode_javascript(). + &Apache::lonxml::setmode_javascript(). &Apache::lonhtmlcommon::dragmath_js("EditMathPopup"); # Breadcrumbs @@ -1227,7 +1320,8 @@ sub editxmlmode { $result .= '
    '; - unless ($env{'environment.nocodemirror'}) { + my $nocodemirror = &Apache::loncommon::nocodemirror(); + unless ($nocodemirror) { # dropdown menus $result .= Apache::lonmenu::create_submenu("#", "", &mt("Problem Templates"), template_dropdown_datastructure()); @@ -1259,7 +1353,7 @@ sub editxmlmode { '
    '; my $resource = $env{'request.ambiguous'}; - unless($env{'environment.nocodemirror'}){ + unless ($nocodemirror) { $result .= '