diff --git a/htdocs/js/ProblemGrader/singleproblemgrader.js b/htdocs/js/ProblemGrader/singleproblemgrader.js index 002c5b7f0d..8518c43586 100644 --- a/htdocs/js/ProblemGrader/singleproblemgrader.js +++ b/htdocs/js/ProblemGrader/singleproblemgrader.js @@ -125,6 +125,7 @@ version_id: saveData.versionId, problem_id: saveData.problemId, status: parseInt(scoreInput.value) / 100, + ...(saveData.saveSubStatus === '1' ? { sub_status: parseInt(scoreInput.value) / 100 } : {}), mark_graded: true }), signal: controller.signal diff --git a/lib/WeBWorK/ContentGenerator/Instructor/ProblemGrader.pm b/lib/WeBWorK/ContentGenerator/Instructor/ProblemGrader.pm index 7bf2c9ed78..dae595e356 100644 --- a/lib/WeBWorK/ContentGenerator/Instructor/ProblemGrader.pm +++ b/lib/WeBWorK/ContentGenerator/Instructor/ProblemGrader.pm @@ -13,6 +13,7 @@ use HTML::Entities; use WeBWorK::Utils::JITAR qw(jitar_id_to_seq); use WeBWorK::Utils::Rendering qw(renderPG); use WeBWorK::Utils::Sets qw(get_test_problem_position format_set_name_display); +use WeBWorK::Utils::DateTime qw(before); async sub initialize ($c) { my $authz = $c->authz; @@ -96,6 +97,17 @@ async sub initialize ($c) { if ($c->param('assignGrades')) { $c->addgoodmessage($c->maketext('Grades have been saved for all current users.')); + # Get all of the merged user sets for this set. These are needed to determine if the problem sub_status also + # needs to be set. The sub_status must be set if reduced scoring is not enabled for the course or set or if it + # is before the reduced scoring date. + my %mergedSets; + if ($c->stash->{set}->assignment_type =~ /gateway/) { + $mergedSets{ $_->user_id }{ $_->version_id } = $_ + for $db->getMergedSetVersionsWhere({ set_id => { like => "$setID,v\%" } }); + } else { + %mergedSets = map { $_->user_id => { 0 => $_ } } $db->getMergedSetsWhere({ set_id => $setID }); + } + for my $user (@{ $c->stash->{users} }) { my $userID = $user->user_id; for (@{ $user->{data} }) { @@ -115,9 +127,16 @@ async sub initialize ($c) { $_->{problem}{flags} =~ s/:needs_grading$//; if ($c->param("$userID.$versionID.mark_correct")) { $_->{problem}->status(1); + $_->{problem}->sub_status(1); } elsif (defined $c->param("$userID.$versionID.score")) { my $newscore = $c->param("$userID.$versionID.score") / 100; - if ($newscore != $_->{problem}->status) { $_->{problem}->status($newscore); } + if ($newscore != $_->{problem}->status) { + $_->{problem}->status($newscore); + $_->{problem}->sub_status($newscore) + if !$ce->{pg}{ansEvalDefaults}{enableReducedScoring} + || !$mergedSets{$userID}{$versionID}->enable_reduced_scoring + || before($mergedSets{$userID}{$versionID}->reduced_scoring_date); + } } if ($versionID) { $db->putProblemVersion($_->{problem}); } diff --git a/lib/WeBWorK/ContentGenerator/Problem.pm b/lib/WeBWorK/ContentGenerator/Problem.pm index af44e7afab..4d163e4692 100644 --- a/lib/WeBWorK/ContentGenerator/Problem.pm +++ b/lib/WeBWorK/ContentGenerator/Problem.pm @@ -1134,7 +1134,7 @@ sub output_message ($c) { # Output the problem grader if the user has permissions to grade problems sub output_grader ($c) { if ($c->{will}{showProblemGrader}) { - return WeBWorK::HTML::SingleProblemGrader->new($c, $c->{pg}, $c->{problem})->insertGrader; + return WeBWorK::HTML::SingleProblemGrader->new($c, $c->{pg}, $c->{problem}, $c->{set})->insertGrader; } return ''; diff --git a/lib/WeBWorK/HTML/SingleProblemGrader.pm b/lib/WeBWorK/HTML/SingleProblemGrader.pm index d10de75633..fa7bd24304 100644 --- a/lib/WeBWorK/HTML/SingleProblemGrader.pm +++ b/lib/WeBWorK/HTML/SingleProblemGrader.pm @@ -11,8 +11,9 @@ as a student. use WeBWorK::Localize; use WeBWorK::Utils 'wwRound'; +use WeBWorK::Utils::DateTime qw(before); -sub new ($class, $c, $pg, $userProblem) { +sub new ($class, $c, $pg, $userProblem, $mergedSet) { $class = ref($class) || $class; my $db = $c->db; @@ -43,7 +44,12 @@ sub new ($class, $c, $pg, $userProblem) { recorded_score => $recordedScore, past_answer_id => $userPastAnswerID // 0, comment_string => $comment, - c => $c + c => $c, + # The grader needs to also save the sub_status if reduced scoring is not enabled, + # or if it is but it is before the reduced scoring date. + save_sub_status => !$c->ce->{pg}{ansEvalDefaults}{enableReducedScoring} + || !$mergedSet->enable_reduced_scoring + || before($mergedSet->reduced_scoring_date) }; bless $self, $class; diff --git a/lib/WebworkWebservice.pm b/lib/WebworkWebservice.pm index b4715a48c8..ef4f03f29d 100644 --- a/lib/WebworkWebservice.pm +++ b/lib/WebworkWebservice.pm @@ -248,8 +248,8 @@ sub command_permission { # WebworkWebservice::ProblemActions getUserProblem => 'access_instructor_tools', - # Note: The modify_student_data permission is checked in the following three methods and only the status and - # comment_string can actually be modified by users with the problem_grader permission only. + # Note: The modify_student_data permission is checked in the following three methods and only the status, + # sub_status, and comment_string can actually be modified by users with the problem_grader permission only. putUserProblem => 'problem_grader', putProblemVersion => 'problem_grader', putPastAnswer => 'problem_grader', diff --git a/lib/WebworkWebservice/ProblemActions.pm b/lib/WebworkWebservice/ProblemActions.pm index 3305176361..a93babdf56 100644 --- a/lib/WebworkWebservice/ProblemActions.pm +++ b/lib/WebworkWebservice/ProblemActions.pm @@ -38,16 +38,17 @@ sub putUserProblem { 'source_file', 'value', 'max_attempts', 'showMeAnother', 'showMeAnotherCount', 'prPeriod', 'prCount', 'problem_seed', 'attempted', 'last_answer', 'num_correct', 'num_incorrect', - 'att_to_open_children', 'counts_parent_grade', 'sub_status', 'flags' + 'att_to_open_children', 'counts_parent_grade', 'flags' ) { $userProblem->{$_} = $params->{$_} if defined $params->{$_}; } } - # The status is the only thing that users with the problem_grader permission can change. + # The status and sub_status are the only things that users with the problem_grader permission can change. # This method cannot be called without the problem_grader permission. - $userProblem->{status} = $params->{status} if defined $params->{status}; + $userProblem->{status} = $params->{status} if defined $params->{status}; + $userProblem->{sub_status} = $params->{sub_status} if defined $params->{sub_status}; # Remove the needs_grading flag if the mark_graded parameter is set. $userProblem->{flags} =~ s/:needs_grading$// if $params->{mark_graded}; @@ -77,16 +78,17 @@ sub putProblemVersion { 'source_file', 'value', 'max_attempts', 'showMeAnother', 'showMeAnotherCount', 'prPeriod', 'prCount', 'problem_seed', 'attempted', 'last_answer', 'num_correct', 'num_incorrect', - 'att_to_open_children', 'counts_parent_grade', 'sub_status', 'flags' + 'att_to_open_children', 'counts_parent_grade', 'flags' ) { $problemVersion->{$_} = $params->{$_} if defined($params->{$_}); } } - # The status is the only thing that users with the problem_grader permission can change. + # The status and sub_status are the only things that users with the problem_grader permission can change. # This method cannot be called without the problem_grader permission. - $problemVersion->{status} = $params->{status} if defined $params->{status}; + $problemVersion->{status} = $params->{status} if defined $params->{status}; + $problemVersion->{sub_status} = $params->{sub_status} if defined $params->{sub_status}; # Remove the needs_grading flag if the mark_graded parameter is set. $problemVersion->{flags} =~ s/:needs_grading$// if $params->{mark_graded}; diff --git a/templates/ContentGenerator/GatewayQuiz.html.ep b/templates/ContentGenerator/GatewayQuiz.html.ep index 1b4b7c7c72..5cd878c230 100644 --- a/templates/ContentGenerator/GatewayQuiz.html.ep +++ b/templates/ContentGenerator/GatewayQuiz.html.ep @@ -643,7 +643,7 @@ % % # Initialize the problem graders for the problem. % if ($c->{will}{showProblemGrader} && !$pg->{flags}{error_flag}) { - <%= WeBWorK::HTML::SingleProblemGrader->new($c, $pg, $problems->[ $probOrder->[$i] ]) + <%= WeBWorK::HTML::SingleProblemGrader->new($c, $pg, $problems->[ $probOrder->[$i] ], $c->{set}) ->insertGrader =%> % } diff --git a/templates/HTML/SingleProblemGrader/grader.html.ep b/templates/HTML/SingleProblemGrader/grader.html.ep index b5caad01ba..8930cdffd7 100644 --- a/templates/HTML/SingleProblemGrader/grader.html.ep +++ b/templates/HTML/SingleProblemGrader/grader.html.ep @@ -271,7 +271,8 @@ data-set-id="<%= $grader->{set_id} %>" data-version-id="<%= $grader->{version_id} %>" data-problem-id="<%= $grader->{problem_id} %>" - data-past-answer-id="<%= $grader->{past_answer_id} %>"> + data-past-answer-id="<%= $grader->{past_answer_id} %>" + data-save-sub-status="<%= $grader->{save_sub_status} %>"> <%= maketext('Save') =%>