diff --git a/htdocs/js/ProblemGrader/problemgrader.js b/htdocs/js/ProblemGrader/problemgrader.js index 31629a6ca1..a5da03370a 100644 --- a/htdocs/js/ProblemGrader/problemgrader.js +++ b/htdocs/js/ProblemGrader/problemgrader.js @@ -104,7 +104,8 @@ set_id: saveData.setId, version_id: saveData.versionId, problem_id: saveData.problemId, - status: parseInt(scoreInput.value) / 100 + status: parseInt(scoreInput.value) / 100, + mark_graded: true }), signal: controller.signal }); diff --git a/lib/WeBWorK/ContentGenerator/GatewayQuiz.pm b/lib/WeBWorK/ContentGenerator/GatewayQuiz.pm index 6ed7e562b7..fa7e2520de 100644 --- a/lib/WeBWorK/ContentGenerator/GatewayQuiz.pm +++ b/lib/WeBWorK/ContentGenerator/GatewayQuiz.pm @@ -926,7 +926,7 @@ async sub pre_header_initialize ($c) { if (ref $pg_result) { my ($past_answers_string, $scores); # Not used here ($past_answers_string, $encoded_last_answer_string, $scores, $answer_types_string) = - create_ans_str_from_responses($c, $pg_result); + create_ans_str_from_responses($c->{formFields}, $pg_result); # Transfer persistent problem data from the PERSISTENCE_HASH: # - Get keys to update first, to avoid extra work when no updated ar @@ -982,13 +982,8 @@ async sub pre_header_initialize ($c) { $pureProblem->num_correct($pg_result->{state}{num_of_correct_ans}); $pureProblem->num_incorrect($pg_result->{state}{num_of_incorrect_ans}); - if ($answer_types_string) { - # Add flags which are really a comma separated list of answer types. If its an essay question and - # the user is submitting an answer then there could be potential changes. So the problem is also - # flagged as needing grading by appending ":needs_grading" to the answer types. - $pureProblem->flags( - $answer_types_string . ($answer_types_string =~ /essay/ ? ':needs_grading' : '')); - } + # Add flags which are really a comma separated list of answer types. + $pureProblem->flags($answer_types_string); if ($db->putProblemVersion($pureProblem)) { # Use a simple untranslated value here. This message will never be shown, and will later be @@ -1065,7 +1060,7 @@ async sub pre_header_initialize ($c) { my $problem = $problems[ $probOrder[$i] ]; my ($past_answers_string, $encoded_last_answer_string, $scores, $answer_types_string) = - create_ans_str_from_responses($c, $pg_results[ $probOrder[$i] ]); + create_ans_str_from_responses($c->{formFields}, $pg_results[ $probOrder[$i] ]); $past_answers_string =~ s/\t+$/\t/; if (!$past_answers_string || $past_answers_string =~ /^\t$/) { diff --git a/lib/WeBWorK/Utils/ProblemProcessing.pm b/lib/WeBWorK/Utils/ProblemProcessing.pm index 262709fdc8..cc21971f52 100644 --- a/lib/WeBWorK/Utils/ProblemProcessing.pm +++ b/lib/WeBWorK/Utils/ProblemProcessing.pm @@ -93,7 +93,7 @@ async sub process_and_log_answer ($c) { if (defined($answer_log) && defined($pureProblem) && $submitAnswers) { my $past_answers_string; ($past_answers_string, $encoded_last_answer_string, $scores2, $answer_types_string) = - create_ans_str_from_responses($c, $pg); + create_ans_str_from_responses($c->{formFields}, $pg); if (!$authz->hasPermissions($effectiveUser, 'dont_log_past_answers')) { # Use the time the submission processing began, but must convert the @@ -161,10 +161,8 @@ async sub process_and_log_answer ($c) { $pureProblem->num_correct($pg->{state}{num_of_correct_ans}); $pureProblem->num_incorrect($pg->{state}{num_of_incorrect_ans}); - # Add flags which are really a comma separated list of answer types. If its an essay question and the - # user is submitting an answer then there could be potential changes. So the problem is also flagged as - # needing grading by appending ":needs_grading" to the answer types. - $pureProblem->flags($answer_types_string . ($answer_types_string =~ /essay/ ? ':needs_grading' : '')); + # Add flags which are really a comma separated list of answer types. + $pureProblem->flags($answer_types_string); if ($db->putUserProblem($pureProblem)) { $scoreRecordedMessage = $c->maketext('Your score was recorded.'); @@ -307,40 +305,44 @@ sub compute_reduced_score ($ce, $problem, $set, $score, $submitTime) { } # create answer string from responses hash -# ($past_answers_string, $encoded_last_answer_string, $scores, $answer_types_string) -# = create_ans_str_from_responses($problem, $pg) +# ($past_answers_string, $encoded_last_answer_string, $scores_string, $answer_types_string) +# = create_ans_str_from_responses($formFields, $pg) # -# input: $problem - a 'WeBWorK::ContentGenerator::Problem object that has $problem->{formFields} set to a hash -# containing the appropriate data. -# $pg - a 'WeBWorK::PG' object -# output: (str, str, str, bool) +# input: $formFields - a hash containing the form field input data for the submission. +# $pg - a 'WeBWorK::PG' object. +# output: (str, str, str, str) # # The extra persistence objects do need to be included in problem->last_answer # in order to keep those objects persistent -- as long as RECORD_FORM_ANSWER # is used to preserve objects by piggy backing on the persistence mechanism for answers. -sub create_ans_str_from_responses ($problem, $pg) { - my $scores2 = ''; +sub create_ans_str_from_responses ($formFields, $pg) { + my $scores_string = ''; my @answerTypes; + my $needsGrading = ''; my %answers_to_store; my @past_answers_order; my @last_answer_order; my %pg_answers_hash = %{ $pg->{PG_ANSWERS_HASH} }; - foreach my $ans_id (@{ $pg->{flags}{ANSWER_ENTRY_ORDER} // [] }) { - $scores2 .= ($pg_answers_hash{$ans_id}{rh_ans}{score} // 0) >= 1 ? "1" : "0"; + for my $ans_id (@{ $pg->{flags}{ANSWER_ENTRY_ORDER} // [] }) { + $scores_string .= ($pg_answers_hash{$ans_id}{rh_ans}{score} // 0) >= 1 ? '1' : '0'; push @answerTypes, $pg_answers_hash{$ans_id}{rh_ans}{type} // ''; - foreach my $response_id (@{ $pg_answers_hash{$ans_id}{response_obj}{response_order} }) { - $answers_to_store{$response_id} = $problem->{formFields}{$response_id}; + for my $response_id (@{ $pg_answers_hash{$ans_id}{response_obj}{response_order} }) { + $answers_to_store{$response_id} = $formFields->{$response_id}; push @past_answers_order, $response_id; push @last_answer_order, $response_id; + + # Determine if this is an essay answer and thus needs to be graded. + $needsGrading = ':needs_grading' if $answerTypes[-1] eq 'essay'; } } + # KEPT_EXTRA_ANSWERS needs to be stored in last_answer in order to preserve persistence items. # The persistence items do not need to be stored in past_answers_string. # Don't add _ext_data items. Those are stored elsewhere. - foreach my $entry_id (@{ $pg->{flags}{KEPT_EXTRA_ANSWERS} }) { + for my $entry_id (@{ $pg->{flags}{KEPT_EXTRA_ANSWERS} }) { next if exists($answers_to_store{$entry_id}) || $entry_id =~ /^_ext_data/; - $answers_to_store{$entry_id} = $problem->{formFields}{$entry_id}; + $answers_to_store{$entry_id} = $formFields->{$entry_id}; push @last_answer_order, $entry_id; } @@ -356,7 +358,7 @@ sub create_ans_str_from_responses ($problem, $pg) { my $encoded_last_answer_string = encodeAnswers(%answers_to_store, @last_answer_order); # past_answers_string is stored in past_answer table. # encoded_last_answer_string is used in `last_answer` entry of the problem_user table. - return ($past_answers_string, $encoded_last_answer_string, $scores2, join(',', @answerTypes)); + return ($past_answers_string, $encoded_last_answer_string, $scores_string, join(',', @answerTypes) . $needsGrading); } # If you provide this subroutine with a userProblem it will notify the instructors of the course that the student has diff --git a/lib/WeBWorK/Utils/Rendering.pm b/lib/WeBWorK/Utils/Rendering.pm index 60df75e5b0..1ec5da5155 100644 --- a/lib/WeBWorK/Utils/Rendering.pm +++ b/lib/WeBWorK/Utils/Rendering.pm @@ -126,6 +126,9 @@ sub constructPGOptions ($ce, $user, $set, $problem, $psvn, $formFields, $transla $options{num_of_correct_ans} = $problem->num_correct; $options{num_of_incorrect_ans} = $problem->num_incorrect; + # This means that there are essay questions in the problem that have not been graded. + $options{needs_grading} = $problem->flags =~ /:needs_grading$/; + # Persistent problem data $options{PERSISTENCE_HASH} = decode_json($problem->problem_data || '{}'); diff --git a/lib/WebworkWebservice/ProblemActions.pm b/lib/WebworkWebservice/ProblemActions.pm index ed699601c3..c30dc95e86 100644 --- a/lib/WebworkWebservice/ProblemActions.pm +++ b/lib/WebworkWebservice/ProblemActions.pm @@ -57,6 +57,9 @@ sub putUserProblem { $userProblem->{$_} = $params->{$_} if defined($params->{$_}); } + # Remove the needs_grading flag if the mark_graded parameter is set. + $userProblem->{flags} =~ s/:needs_grading$// if $params->{mark_graded}; + eval { $db->putUserProblem($userProblem) }; if ($@) { return { text => "putUserProblem: $@" }; } @@ -88,6 +91,9 @@ sub putProblemVersion { $problemVersion->{$_} = $params->{$_} if defined($params->{$_}); } + # Remove the needs_grading flag if the mark_graded parameter is set. + $problemVersion->{flags} =~ s/:needs_grading$// if $params->{mark_graded}; + eval { $db->putProblemVersion($problemVersion) }; if ($@) { return { text => "putProblemVersion: $@" }; }