Skip to content

Commit

Permalink
Improvements to the essay "needs_grading" flag.
Browse files Browse the repository at this point in the history
First, the single problem grader now removes this flag when an essay
answer is graded.  A new `mark_graded` parameter for the
WebworkWebservice::ProblemActions `putUserProblem` and
`putProblemVersion` methods is added to accomodate this.

When a problem is rendered this flag now needs to be passed to PG to
indicated whether a problem still needs to be graded so that essay
answers can not always show "Ungraded".

The `create_ans_str_from_responses` method now handles adding this flag
instead of that code being duplicated in ProblemProcessing.pm and
GatewayQuiz.pm.
  • Loading branch information
drgrice1 committed Jan 8, 2024
1 parent a45ca4b commit dd0f417
Show file tree
Hide file tree
Showing 5 changed files with 37 additions and 30 deletions.
3 changes: 2 additions & 1 deletion htdocs/js/ProblemGrader/problemgrader.js
Original file line number Diff line number Diff line change
Expand Up @@ -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
});
Expand Down
13 changes: 4 additions & 9 deletions lib/WeBWorK/ContentGenerator/GatewayQuiz.pm
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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$/) {
Expand Down
42 changes: 22 additions & 20 deletions lib/WeBWorK/Utils/ProblemProcessing.pm
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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.');
Expand Down Expand Up @@ -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;
}

Expand All @@ -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
Expand Down
3 changes: 3 additions & 0 deletions lib/WeBWorK/Utils/Rendering.pm
Original file line number Diff line number Diff line change
Expand Up @@ -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 || '{}');

Expand Down
6 changes: 6 additions & 0 deletions lib/WebworkWebservice/ProblemActions.pm
Original file line number Diff line number Diff line change
Expand Up @@ -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: $@" }; }

Expand Down Expand Up @@ -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: $@" }; }

Expand Down

0 comments on commit dd0f417

Please sign in to comment.