From 7d7fd79b892e37160fac069e3e8a020a8167c15c Mon Sep 17 00:00:00 2001 From: Danny Glin Date: Fri, 13 Feb 2026 03:38:05 +0000 Subject: [PATCH 1/8] Fix ressurect achievement items --- lib/WeBWorK/AchievementItems/ResurrectGW.pm | 80 ++++++++++++++++----- 1 file changed, 63 insertions(+), 17 deletions(-) diff --git a/lib/WeBWorK/AchievementItems/ResurrectGW.pm b/lib/WeBWorK/AchievementItems/ResurrectGW.pm index 00b99ca4ce..3372693290 100644 --- a/lib/WeBWorK/AchievementItems/ResurrectGW.pm +++ b/lib/WeBWorK/AchievementItems/ResurrectGW.pm @@ -13,26 +13,60 @@ sub new ($class) { id => 'ResurrectGW', name => x('Necromancers Charm'), description => x( - 'Reopens any test for an additional 24 hours. This allows you to take a test even if the ' - . 'close date has past. This item does not allow you to take additional versions of the test.' + 'Reopens any test for an additional 24 hours. If you are allowed to start new versions of the test, then this allows you to start a new test even if the ' + . 'close date has past. If you were not allowed to start a new version of the test, then this item will not allow you to take additional versions of the test.' + . 'This item will not extend the time limit for any tests that you have already started.' ) }, $class; } sub can_use($self, $set, $records) { return $set->assignment_type =~ /gateway/ - && (after($set->due_date) || ($set->reduced_scoring_date && after($set->reduced_scoring_date))); + && (after($set->due_date) || ($set->enable_reduced_scoring && after($set->reduced_scoring_date))); # TODO: Check if a new version can be created, and only allow using this reward in that case. } sub print_form ($self, $set, $records, $c) { - return $c->tag( - 'p', - $c->maketext( - 'Reopen this test for the next 24 hours. This item does not allow you to take any additional ' - . 'versions of the test.' - ) - ); + if(after($set->due_date)) { + return $c->tag( + 'p', + $c->maketext( + 'Reopen this test for the next 24 hours. If you were allowed to start new versions of the test, then this will allow you to start a new test. ' + . 'If you were not allowed to start a new version of the test, then you should not use this item. ' + . 'This item will not extend the time limit for any tests that you have already started.' + ) + ); + } else { + if(after($set->due_date - ONE_DAY)) { + return $c->tag( + 'p', + $c->maketext( + 'Reopen this test for full credit for the next 24 hours. If you are allowed to start new versions of the test, then this will allow you to start a new test. ' + . 'If you were not allowed to start a new version of the test, then you should not use this item. ' + . 'This item will not extend the time limit for any tests that you have already started.' + ) + ); + } else { + return $c->c ( + $c->tag( + 'p', + $c->maketext( + 'Reopen this test for full credit for the next 24 hours. After 24 hours any tests will revert to counting for ' + . $c->ce->{pg}{ansEvalDefaults}{reducedScoringValue} * 100 . '% of their value until [_1].', + $c->formatDateTime($set->due_date, $c->ce->{studentDateDisplayFormat}) + ) + ), + $c->tag( + 'p', + $c->maketext( + ' If you are allowed to start new versions of the test, then this will allow you to start a new test. ' + . 'If you were not allowed to start a new version of the test, then you should not use this item. ' + . 'This item will not extend the time limit for any tests that you have already started.' + ) + ) + )->join(''); + } + } } sub use_item ($self, $set, $records, $c) { @@ -44,18 +78,30 @@ sub use_item ($self, $set, $records, $c) { $set->reduced_scoring_date(time + ONE_DAY); $userSet->reduced_scoring_date($set->reduced_scoring_date); } - $set->due_date(time + ONE_DAY); - $userSet->due_date($set->due_date); - if ($set->due_date > $set->answer_date) { - $set->answer_date(time + ONE_DAY); - $userSet->answer_date($set->answer_date); + if (after($set->due_date - ONE_DAY)) { + $set->due_date(time + ONE_DAY); + $userSet->due_date($set->due_date); + if ($set->due_date > $set->answer_date) { + $set->answer_date(time + ONE_DAY); + $userSet->answer_date($set->answer_date); + } } $db->putUserSet($userSet); - return $c->maketext( + if ($set->enable_reduced_scoring && ($set->reduced_scoring_date != $set->due_date)) { + return $c->maketext( + 'This assignment has been reopened and is due on [_1]. After that date any work ' + . 'completed will count for '. $c->ce->{pg}{ansEvalDefaults}{reducedScoringValue} * 100 . '% ' + . 'of its value until [_2]', + $c->formatDateTime($set->reduced_scoring_date, $c->ce->{studentDateDisplayFormat}), + $c->formatDateTime($set->due_date, $c->ce->{studentDateDisplayFormat}) + ); + } else { + return $c->maketext( 'This assignment has been reopened and will now close on [_1].', $c->formatDateTime($set->due_date, $c->ce->{studentDateDisplayFormat}) - ); + ); + } } 1; From 68f98e2cbcdca56bd83a0f0224d60e46ec8274e2 Mon Sep 17 00:00:00 2001 From: Danny Glin Date: Thu, 26 Mar 2026 20:08:01 +0000 Subject: [PATCH 2/8] Fix resurrect achievement items --- lib/WeBWorK/AchievementItems/ResurrectGW.pm | 31 +++++--- lib/WeBWorK/AchievementItems/ResurrectHW.pm | 84 +++++++++++++++------ 2 files changed, 83 insertions(+), 32 deletions(-) diff --git a/lib/WeBWorK/AchievementItems/ResurrectGW.pm b/lib/WeBWorK/AchievementItems/ResurrectGW.pm index 3372693290..04ab3f9fe1 100644 --- a/lib/WeBWorK/AchievementItems/ResurrectGW.pm +++ b/lib/WeBWorK/AchievementItems/ResurrectGW.pm @@ -13,8 +13,10 @@ sub new ($class) { id => 'ResurrectGW', name => x('Necromancers Charm'), description => x( - 'Reopens any test for an additional 24 hours. If you are allowed to start new versions of the test, then this allows you to start a new test even if the ' - . 'close date has past. If you were not allowed to start a new version of the test, then this item will not allow you to take additional versions of the test.' + 'Reopens any test for an additional 24 hours. If you are allowed to start new versions of the test, ' + . 'then this allows you to start a new test even if the close date has past. ' + . 'If you were not allowed to start a new version of the test, ' + . 'then this item will not allow you to take additional versions of the test. ' . 'This item will not extend the time limit for any tests that you have already started.' ) }, $class; @@ -31,8 +33,10 @@ sub print_form ($self, $set, $records, $c) { return $c->tag( 'p', $c->maketext( - 'Reopen this test for the next 24 hours. If you were allowed to start new versions of the test, then this will allow you to start a new test. ' - . 'If you were not allowed to start a new version of the test, then you should not use this item. ' + 'Reopen this test for the next 24 hours. If you were allowed to start new versions of the test, ' + . 'then this will allow you to start a new test. ' + . 'If you have already started all of the versions of the test that you are allowed to start, ' + . 'then you should not use this item. ' . 'This item will not extend the time limit for any tests that you have already started.' ) ); @@ -41,8 +45,10 @@ sub print_form ($self, $set, $records, $c) { return $c->tag( 'p', $c->maketext( - 'Reopen this test for full credit for the next 24 hours. If you are allowed to start new versions of the test, then this will allow you to start a new test. ' - . 'If you were not allowed to start a new version of the test, then you should not use this item. ' + 'Reopen this test for full credit for the next 24 hours. If you are allowed to start new versions ' + . 'of the test, then this will allow you to start a new test. ' + . 'If you have already started all of the versions of the test that you are allowed to start, ' + . 'then you should not use this item. ' . 'This item will not extend the time limit for any tests that you have already started.' ) ); @@ -51,16 +57,19 @@ sub print_form ($self, $set, $records, $c) { $c->tag( 'p', $c->maketext( - 'Reopen this test for full credit for the next 24 hours. After 24 hours any tests will revert to counting for ' - . $c->ce->{pg}{ansEvalDefaults}{reducedScoringValue} * 100 . '% of their value until [_1].', + 'Reopen this test for full credit for the next 24 hours. After 24 hours any tests will revert ' + . 'to counting for [_1]% of their value until [_2].', + $c->ce->{pg}{ansEvalDefaults}{reducedScoringValue} * 100, $c->formatDateTime($set->due_date, $c->ce->{studentDateDisplayFormat}) ) ), $c->tag( 'p', $c->maketext( - ' If you are allowed to start new versions of the test, then this will allow you to start a new test. ' - . 'If you were not allowed to start a new version of the test, then you should not use this item. ' + ' If you are allowed to start new versions of the test, ' + . 'then this will allow you to start a new test. ' + . 'If you have already started all of the versions of the test that you are allowed to start, ' + . 'then you should not use this item. ' . 'This item will not extend the time limit for any tests that you have already started.' ) ) @@ -82,7 +91,7 @@ sub use_item ($self, $set, $records, $c) { $set->due_date(time + ONE_DAY); $userSet->due_date($set->due_date); if ($set->due_date > $set->answer_date) { - $set->answer_date(time + ONE_DAY); + $set->answer_date($set->due_date); $userSet->answer_date($set->answer_date); } } diff --git a/lib/WeBWorK/AchievementItems/ResurrectHW.pm b/lib/WeBWorK/AchievementItems/ResurrectHW.pm index da8364822f..bca0dcbbdf 100644 --- a/lib/WeBWorK/AchievementItems/ResurrectHW.pm +++ b/lib/WeBWorK/AchievementItems/ResurrectHW.pm @@ -18,26 +18,55 @@ sub new ($class) { sub can_use($self, $set, $records) { return $set->assignment_type eq 'default' - && (after($set->due_date) || ($set->reduced_scoring_date && after($set->reduced_scoring_date))); + && (after($set->due_date) || ($set->enable_reduced_scoring && after($set->reduced_scoring_date))); } sub print_form ($self, $set, $records, $c) { - return $c->tag('p', - $c->maketext('Reopen this homework assignment for the next 24 hours. All problems will be rerandomized.')); + if(after($set->due_date)) { + return $c->tag( + 'p', + $c->maketext( + 'Reopen this homework assignment for the next 24 hours. All problems will be rerandomized.' + ) + ); + } else { + if(after($set->due_date - ONE_DAY)) { + return $c->tag( + 'p', + $c->maketext( + 'Reopen this homework assignment for full credit for the next 24 hours. ' + ) + ); + } else { + return $c->tag( + 'p', + $c->maketext( + 'Reopen this homework assignment for full credit for the next 24 hours. After 24 hours ' + . 'any progress will revert to counting for [_1]% of the value until [_2].', + $c->ce->{pg}{ansEvalDefaults}{reducedScoringValue} * 100, + $c->formatDateTime($set->due_date, $c->ce->{studentDateDisplayFormat}) + ) + ); + } + } } sub use_item ($self, $set, $records, $c) { my $db = $c->db; my $userSet = $db->getUserSet($set->user_id, $set->set_id); + my $rerandomizeMessage = ''; - # Change the seed for all of the problems since the set is currently closed. - my %userProblems = - map { $_->problem_id => $_ } $db->getUserProblemsWhere({ user_id => $set->user_id, set_id => $set->set_id }); - for my $problem (@$records) { - my $userProblem = $userProblems{ $problem->problem_id }; - $userProblem->problem_seed($userProblem->problem_seed % 2**31 + 1); - $problem->problem_seed($userProblem->problem_seed); - $db->putUserProblem($userProblem); + # Change the seed for all of the problems if the set is currently closed. + if (after($set->due_date)) { + my %userProblems = + map { $_->problem_id => $_ } $db->getUserProblemsWhere({ user_id => $set->user_id, set_id => $set->set_id }); + for my $problem (@$records) { + my $userProblem = $userProblems{ $problem->problem_id }; + $userProblem->problem_seed($userProblem->problem_seed % 2**31 + 1); + $problem->problem_seed($userProblem->problem_seed); + $db->putUserProblem($userProblem); + } + $rerandomizeMessage = $c->maketext('Problems have been rerandomized.'); } # Add time to the reduced scoring date if it was defined in the first place @@ -45,19 +74,32 @@ sub use_item ($self, $set, $records, $c) { $set->reduced_scoring_date(time + ONE_DAY); $userSet->reduced_scoring_date($set->reduced_scoring_date); } - # Add time to the close date - $set->due_date(time + ONE_DAY); - $userSet->due_date($set->due_date); - # This may require also extending the answer date. - if ($set->due_date > $set->answer_date) { - $set->answer_date($set->due_date); - $userSet->answer_date($set->answer_date); + # Add time to the close date if necessary + if (after($set->due_date - ONE_DAY)) { + $set->due_date(time + ONE_DAY); + $userSet->due_date($set->due_date); + # This may require also extending the answer date. + if ($set->due_date > $set->answer_date) { + $set->answer_date($set->due_date); + $userSet->answer_date($set->answer_date); + } } $db->putUserSet($userSet); - return $c->maketext( - 'This assignment has been reopened and will now close on [_1]. Problems have been rerandomized.', - $c->formatDateTime($set->due_date, $c->ce->{studentDateDisplayFormat})); + if ($set->enable_reduced_scoring && ($set->reduced_scoring_date != $set->due_date)) { + return $c->maketext( + 'This assignment has been reopened and is due on [_1]. After that date any work ' + . 'completed will count for [_2]% of its value until [_3]. ', + $c->formatDateTime($set->reduced_scoring_date, $c->ce->{studentDateDisplayFormat}), + $c->ce->{pg}{ansEvalDefaults}{reducedScoringValue} * 100, + $c->formatDateTime($set->due_date, $c->ce->{studentDateDisplayFormat}) + ) . $rerandomizeMessage; + } else { + return $c->maketext( + 'This assignment has been reopened and will now close on [_1]. ', + $c->formatDateTime($set->due_date, $c->ce->{studentDateDisplayFormat}) + ) . $rerandomizeMessage; + } } 1; From 2a4996a7d5ca6b98d36e65f492869b5a229e5179 Mon Sep 17 00:00:00 2001 From: Danny Glin Date: Thu, 26 Mar 2026 20:08:53 +0000 Subject: [PATCH 3/8] fix resurrect achievement items --- lib/WeBWorK/AchievementItems/ResurrectGW.pm | 51 +++++++++++---------- lib/WeBWorK/AchievementItems/ResurrectHW.pm | 48 +++++++++---------- 2 files changed, 48 insertions(+), 51 deletions(-) diff --git a/lib/WeBWorK/AchievementItems/ResurrectGW.pm b/lib/WeBWorK/AchievementItems/ResurrectGW.pm index 04ab3f9fe1..e4cabd8830 100644 --- a/lib/WeBWorK/AchievementItems/ResurrectGW.pm +++ b/lib/WeBWorK/AchievementItems/ResurrectGW.pm @@ -14,7 +14,7 @@ sub new ($class) { name => x('Necromancers Charm'), description => x( 'Reopens any test for an additional 24 hours. If you are allowed to start new versions of the test, ' - . 'then this allows you to start a new test even if the close date has past. ' + . 'then this allows you to start a new test even if the close date has past. ' . 'If you were not allowed to start a new version of the test, ' . 'then this item will not allow you to take additional versions of the test. ' . 'This item will not extend the time limit for any tests that you have already started.' @@ -22,43 +22,43 @@ sub new ($class) { }, $class; } -sub can_use($self, $set, $records) { +sub can_use ($self, $set, $records) { return $set->assignment_type =~ /gateway/ && (after($set->due_date) || ($set->enable_reduced_scoring && after($set->reduced_scoring_date))); # TODO: Check if a new version can be created, and only allow using this reward in that case. } sub print_form ($self, $set, $records, $c) { - if(after($set->due_date)) { + if (after($set->due_date)) { return $c->tag( 'p', $c->maketext( 'Reopen this test for the next 24 hours. If you were allowed to start new versions of the test, ' - . 'then this will allow you to start a new test. ' - . 'If you have already started all of the versions of the test that you are allowed to start, ' - . 'then you should not use this item. ' - . 'This item will not extend the time limit for any tests that you have already started.' + . 'then this will allow you to start a new test. ' + . 'If you have already started all of the versions of the test that you are allowed to start, ' + . 'then you should not use this item. ' + . 'This item will not extend the time limit for any tests that you have already started.' ) ); } else { - if(after($set->due_date - ONE_DAY)) { + if (after($set->due_date - ONE_DAY)) { return $c->tag( 'p', $c->maketext( 'Reopen this test for full credit for the next 24 hours. If you are allowed to start new versions ' - . 'of the test, then this will allow you to start a new test. ' - . 'If you have already started all of the versions of the test that you are allowed to start, ' - . 'then you should not use this item. ' - . 'This item will not extend the time limit for any tests that you have already started.' + . 'of the test, then this will allow you to start a new test. ' + . 'If you have already started all of the versions of the test that you are allowed to start, ' + . 'then you should not use this item. ' + . 'This item will not extend the time limit for any tests that you have already started.' ) ); } else { - return $c->c ( + return $c->c( $c->tag( 'p', $c->maketext( 'Reopen this test for full credit for the next 24 hours. After 24 hours any tests will revert ' - . 'to counting for [_1]% of their value until [_2].', + . 'to counting for [_1]% of their value until [_2].', $c->ce->{pg}{ansEvalDefaults}{reducedScoringValue} * 100, $c->formatDateTime($set->due_date, $c->ce->{studentDateDisplayFormat}) ) @@ -67,10 +67,10 @@ sub print_form ($self, $set, $records, $c) { 'p', $c->maketext( ' If you are allowed to start new versions of the test, ' - . 'then this will allow you to start a new test. ' - . 'If you have already started all of the versions of the test that you are allowed to start, ' - . 'then you should not use this item. ' - . 'This item will not extend the time limit for any tests that you have already started.' + . 'then this will allow you to start a new test. ' + . 'If you have already started all of the versions of the test that you are allowed to start, ' + . 'then you should not use this item. ' + . 'This item will not extend the time limit for any tests that you have already started.' ) ) )->join(''); @@ -99,16 +99,17 @@ sub use_item ($self, $set, $records, $c) { if ($set->enable_reduced_scoring && ($set->reduced_scoring_date != $set->due_date)) { return $c->maketext( - 'This assignment has been reopened and is due on [_1]. After that date any work ' - . 'completed will count for '. $c->ce->{pg}{ansEvalDefaults}{reducedScoringValue} * 100 . '% ' - . 'of its value until [_2]', - $c->formatDateTime($set->reduced_scoring_date, $c->ce->{studentDateDisplayFormat}), - $c->formatDateTime($set->due_date, $c->ce->{studentDateDisplayFormat}) + 'This assignment has been reopened and is due on [_1]. After that date any work ' + . 'completed will count for ' + . $c->ce->{pg}{ansEvalDefaults}{reducedScoringValue} * 100 . '% ' + . 'of its value until [_2]', + $c->formatDateTime($set->reduced_scoring_date, $c->ce->{studentDateDisplayFormat}), + $c->formatDateTime($set->due_date, $c->ce->{studentDateDisplayFormat}) ); } else { return $c->maketext( - 'This assignment has been reopened and will now close on [_1].', - $c->formatDateTime($set->due_date, $c->ce->{studentDateDisplayFormat}) + 'This assignment has been reopened and will now close on [_1].', + $c->formatDateTime($set->due_date, $c->ce->{studentDateDisplayFormat}) ); } } diff --git a/lib/WeBWorK/AchievementItems/ResurrectHW.pm b/lib/WeBWorK/AchievementItems/ResurrectHW.pm index bca0dcbbdf..6a14c31ae6 100644 --- a/lib/WeBWorK/AchievementItems/ResurrectHW.pm +++ b/lib/WeBWorK/AchievementItems/ResurrectHW.pm @@ -16,50 +16,46 @@ sub new ($class) { }, $class; } -sub can_use($self, $set, $records) { +sub can_use ($self, $set, $records) { return $set->assignment_type eq 'default' && (after($set->due_date) || ($set->enable_reduced_scoring && after($set->reduced_scoring_date))); } sub print_form ($self, $set, $records, $c) { - if(after($set->due_date)) { + if (after($set->due_date)) { return $c->tag( 'p', $c->maketext( - 'Reopen this homework assignment for the next 24 hours. All problems will be rerandomized.' - ) + 'Reopen this homework assignment for the next 24 hours. All problems will be rerandomized.') ); } else { - if(after($set->due_date - ONE_DAY)) { + if (after($set->due_date - ONE_DAY)) { + return $c->tag('p', + $c->maketext('Reopen this homework assignment for full credit for the next 24 hours. ')); + } else { return $c->tag( 'p', $c->maketext( - 'Reopen this homework assignment for full credit for the next 24 hours. ' + 'Reopen this homework assignment for full credit for the next 24 hours. After 24 hours ' + . 'any progress will revert to counting for [_1]% of the value until [_2].', + $c->ce->{pg}{ansEvalDefaults}{reducedScoringValue} * 100, + $c->formatDateTime($set->due_date, $c->ce->{studentDateDisplayFormat}) ) ); - } else { - return $c->tag( - 'p', - $c->maketext( - 'Reopen this homework assignment for full credit for the next 24 hours. After 24 hours ' - . 'any progress will revert to counting for [_1]% of the value until [_2].', - $c->ce->{pg}{ansEvalDefaults}{reducedScoringValue} * 100, - $c->formatDateTime($set->due_date, $c->ce->{studentDateDisplayFormat}) - ) - ); } } } sub use_item ($self, $set, $records, $c) { - my $db = $c->db; - my $userSet = $db->getUserSet($set->user_id, $set->set_id); + my $db = $c->db; + my $userSet = $db->getUserSet($set->user_id, $set->set_id); my $rerandomizeMessage = ''; # Change the seed for all of the problems if the set is currently closed. if (after($set->due_date)) { my %userProblems = - map { $_->problem_id => $_ } $db->getUserProblemsWhere({ user_id => $set->user_id, set_id => $set->set_id }); + map { $_->problem_id => $_ } + $db->getUserProblemsWhere({ user_id => $set->user_id, set_id => $set->set_id }); for my $problem (@$records) { my $userProblem = $userProblems{ $problem->problem_id }; $userProblem->problem_seed($userProblem->problem_seed % 2**31 + 1); @@ -88,16 +84,16 @@ sub use_item ($self, $set, $records, $c) { if ($set->enable_reduced_scoring && ($set->reduced_scoring_date != $set->due_date)) { return $c->maketext( - 'This assignment has been reopened and is due on [_1]. After that date any work ' - . 'completed will count for [_2]% of its value until [_3]. ', - $c->formatDateTime($set->reduced_scoring_date, $c->ce->{studentDateDisplayFormat}), - $c->ce->{pg}{ansEvalDefaults}{reducedScoringValue} * 100, - $c->formatDateTime($set->due_date, $c->ce->{studentDateDisplayFormat}) + 'This assignment has been reopened and is due on [_1]. After that date any work ' + . 'completed will count for [_2]% of its value until [_3]. ', + $c->formatDateTime($set->reduced_scoring_date, $c->ce->{studentDateDisplayFormat}), + $c->ce->{pg}{ansEvalDefaults}{reducedScoringValue} * 100, + $c->formatDateTime($set->due_date, $c->ce->{studentDateDisplayFormat}) ) . $rerandomizeMessage; } else { return $c->maketext( - 'This assignment has been reopened and will now close on [_1]. ', - $c->formatDateTime($set->due_date, $c->ce->{studentDateDisplayFormat}) + 'This assignment has been reopened and will now close on [_1]. ', + $c->formatDateTime($set->due_date, $c->ce->{studentDateDisplayFormat}) ) . $rerandomizeMessage; } } From 1ccb5385abd5b93c862a201ae07da7392f316e9a Mon Sep 17 00:00:00 2001 From: Danny Glin Date: Thu, 26 Mar 2026 21:23:19 +0000 Subject: [PATCH 4/8] Fix maketext call --- lib/WeBWorK/AchievementItems/ResurrectGW.pm | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/lib/WeBWorK/AchievementItems/ResurrectGW.pm b/lib/WeBWorK/AchievementItems/ResurrectGW.pm index e4cabd8830..9f0b81b037 100644 --- a/lib/WeBWorK/AchievementItems/ResurrectGW.pm +++ b/lib/WeBWorK/AchievementItems/ResurrectGW.pm @@ -100,11 +100,10 @@ sub use_item ($self, $set, $records, $c) { if ($set->enable_reduced_scoring && ($set->reduced_scoring_date != $set->due_date)) { return $c->maketext( 'This assignment has been reopened and is due on [_1]. After that date any work ' - . 'completed will count for ' - . $c->ce->{pg}{ansEvalDefaults}{reducedScoringValue} * 100 . '% ' - . 'of its value until [_2]', + . 'completed will count for [_2]% of its value until [_3].', $c->formatDateTime($set->reduced_scoring_date, $c->ce->{studentDateDisplayFormat}), - $c->formatDateTime($set->due_date, $c->ce->{studentDateDisplayFormat}) + $c->ce->{pg}{ansEvalDefaults}{reducedScoringValue} * 100, + $c->formatDateTime($set->due_date, $c->ce->{studentDateDisplayFormat}) ); } else { return $c->maketext( From 34bfbe63c612708c362dc096a770cda6d336ae1b Mon Sep 17 00:00:00 2001 From: Danny Glin Date: Mon, 13 Apr 2026 20:49:12 +0000 Subject: [PATCH 5/8] Add controller object to can_use --- lib/WeBWorK/AchievementItems.pm | 4 ++-- lib/WeBWorK/AchievementItems/AddNewTestGW.pm | 2 +- lib/WeBWorK/AchievementItems/DoubleProb.pm | 2 +- lib/WeBWorK/AchievementItems/DoubleSet.pm | 2 +- lib/WeBWorK/AchievementItems/DuplicateProb.pm | 2 +- lib/WeBWorK/AchievementItems/ExtendDueDate.pm | 2 +- lib/WeBWorK/AchievementItems/ExtendDueDateGW.pm | 2 +- lib/WeBWorK/AchievementItems/ExtendReducedDate.pm | 3 ++- lib/WeBWorK/AchievementItems/FullCreditProb.pm | 2 +- lib/WeBWorK/AchievementItems/FullCreditSet.pm | 2 +- lib/WeBWorK/AchievementItems/HalfCreditProb.pm | 2 +- lib/WeBWorK/AchievementItems/HalfCreditSet.pm | 2 +- lib/WeBWorK/AchievementItems/NoReducedCred.pm | 3 ++- lib/WeBWorK/AchievementItems/ReducedCred.pm | 2 +- lib/WeBWorK/AchievementItems/ResetIncorrectAttempts.pm | 2 +- lib/WeBWorK/AchievementItems/ResurrectGW.pm | 9 +++++++-- lib/WeBWorK/AchievementItems/ResurrectHW.pm | 10 +++++----- lib/WeBWorK/AchievementItems/SuperExtendDueDate.pm | 2 +- lib/WeBWorK/AchievementItems/SuperExtendReducedDate.pm | 2 +- lib/WeBWorK/AchievementItems/Surprise.pm | 2 +- 20 files changed, 33 insertions(+), 26 deletions(-) diff --git a/lib/WeBWorK/AchievementItems.pm b/lib/WeBWorK/AchievementItems.pm index a9ad736516..3ee7e5b5ec 100644 --- a/lib/WeBWorK/AchievementItems.pm +++ b/lib/WeBWorK/AchievementItems.pm @@ -80,7 +80,7 @@ sub UserItems ($c, $userName, $set, $records) { push(@items, $achievementItem); next; } - next unless $achievementItem->can_use($set, $records); + next unless $achievementItem->can_use($set, $records, $c); # Use the achievement item. if ($use_item_id eq $item) { @@ -104,7 +104,7 @@ sub UserItems ($c, $userName, $set, $records) { my @new_items; for (@items) { my $item = $_->[0]; - next unless $item->{count} && $item->can_use($set, $records); + next unless $item->{count} && $item->can_use($set, $records, $c); push(@new_items, [ $item, $item->print_form($set, $records, $c) ]); } return \@new_items; diff --git a/lib/WeBWorK/AchievementItems/AddNewTestGW.pm b/lib/WeBWorK/AchievementItems/AddNewTestGW.pm index 9eadafbe69..8204d8d0ab 100644 --- a/lib/WeBWorK/AchievementItems/AddNewTestGW.pm +++ b/lib/WeBWorK/AchievementItems/AddNewTestGW.pm @@ -17,7 +17,7 @@ sub new ($class) { }, $class; } -sub can_use ($self, $set, $records) { +sub can_use ($self, $set, $records, $c) { return $set->assignment_type =~ /gateway/ && $set->set_id !~ /,v\d+$/ diff --git a/lib/WeBWorK/AchievementItems/DoubleProb.pm b/lib/WeBWorK/AchievementItems/DoubleProb.pm index 15ca7dc072..296f5c17a2 100644 --- a/lib/WeBWorK/AchievementItems/DoubleProb.pm +++ b/lib/WeBWorK/AchievementItems/DoubleProb.pm @@ -14,7 +14,7 @@ sub new ($class) { }, $class; } -sub can_use ($self, $set, $records) { +sub can_use ($self, $set, $records, $c) { return $set->assignment_type eq 'default' && after($set->open_date); } diff --git a/lib/WeBWorK/AchievementItems/DoubleSet.pm b/lib/WeBWorK/AchievementItems/DoubleSet.pm index b91629f717..aa85bf2b01 100644 --- a/lib/WeBWorK/AchievementItems/DoubleSet.pm +++ b/lib/WeBWorK/AchievementItems/DoubleSet.pm @@ -14,7 +14,7 @@ sub new ($class) { }, $class; } -sub can_use ($self, $set, $records) { +sub can_use ($self, $set, $records, $c) { return $set->assignment_type eq 'default' && after($set->open_date); } diff --git a/lib/WeBWorK/AchievementItems/DuplicateProb.pm b/lib/WeBWorK/AchievementItems/DuplicateProb.pm index 20c90d726d..d5fb9e0e9c 100644 --- a/lib/WeBWorK/AchievementItems/DuplicateProb.pm +++ b/lib/WeBWorK/AchievementItems/DuplicateProb.pm @@ -14,7 +14,7 @@ sub new ($class) { }, $class; } -sub can_use ($self, $set, $records) { +sub can_use ($self, $set, $records, $c) { return $set->assignment_type eq 'default' && between($set->open_date, $set->due_date); } diff --git a/lib/WeBWorK/AchievementItems/ExtendDueDate.pm b/lib/WeBWorK/AchievementItems/ExtendDueDate.pm index 2391ab916d..630cd360ba 100644 --- a/lib/WeBWorK/AchievementItems/ExtendDueDate.pm +++ b/lib/WeBWorK/AchievementItems/ExtendDueDate.pm @@ -19,7 +19,7 @@ sub new ($class) { }, $class; } -sub can_use ($self, $set, $records) { +sub can_use ($self, $set, $records, $c) { return $set->assignment_type eq 'default' && between($set->open_date, $set->due_date + ONE_DAY); } diff --git a/lib/WeBWorK/AchievementItems/ExtendDueDateGW.pm b/lib/WeBWorK/AchievementItems/ExtendDueDateGW.pm index 6900d1f828..d91c2f5c77 100644 --- a/lib/WeBWorK/AchievementItems/ExtendDueDateGW.pm +++ b/lib/WeBWorK/AchievementItems/ExtendDueDateGW.pm @@ -17,7 +17,7 @@ sub new ($class) { }, $class; } -sub can_use ($self, $set, $records) { +sub can_use ($self, $set, $records, $c) { return $set->assignment_type =~ /gateway/ && $set->set_id !~ /,v\d+$/ diff --git a/lib/WeBWorK/AchievementItems/ExtendReducedDate.pm b/lib/WeBWorK/AchievementItems/ExtendReducedDate.pm index 7c24c0d4b8..f9422baf43 100644 --- a/lib/WeBWorK/AchievementItems/ExtendReducedDate.pm +++ b/lib/WeBWorK/AchievementItems/ExtendReducedDate.pm @@ -20,9 +20,10 @@ sub new ($class) { }, $class; } -sub can_use ($self, $set, $records) { +sub can_use ($self, $set, $records, $c) { return 0 unless $set->assignment_type eq 'default' + && $c->ce->{pg}{ansEvalDefaults}{enableReducedScoring} && $set->enable_reduced_scoring && $set->reduced_scoring_date && $set->reduced_scoring_date < $set->due_date; diff --git a/lib/WeBWorK/AchievementItems/FullCreditProb.pm b/lib/WeBWorK/AchievementItems/FullCreditProb.pm index 50e15639b5..1645c92c19 100644 --- a/lib/WeBWorK/AchievementItems/FullCreditProb.pm +++ b/lib/WeBWorK/AchievementItems/FullCreditProb.pm @@ -14,7 +14,7 @@ sub new ($class) { }, $class; } -sub can_use ($self, $set, $records) { +sub can_use ($self, $set, $records, $c) { return 0 unless $set->assignment_type eq 'default' && after($set->open_date); diff --git a/lib/WeBWorK/AchievementItems/FullCreditSet.pm b/lib/WeBWorK/AchievementItems/FullCreditSet.pm index 6c9065fa48..fa025c339f 100644 --- a/lib/WeBWorK/AchievementItems/FullCreditSet.pm +++ b/lib/WeBWorK/AchievementItems/FullCreditSet.pm @@ -14,7 +14,7 @@ sub new ($class) { }, $class; } -sub can_use ($self, $set, $records) { +sub can_use ($self, $set, $records, $c) { return 0 unless $set->assignment_type eq 'default' && after($set->open_date); diff --git a/lib/WeBWorK/AchievementItems/HalfCreditProb.pm b/lib/WeBWorK/AchievementItems/HalfCreditProb.pm index 307e3d32af..26ec5545db 100644 --- a/lib/WeBWorK/AchievementItems/HalfCreditProb.pm +++ b/lib/WeBWorK/AchievementItems/HalfCreditProb.pm @@ -14,7 +14,7 @@ sub new ($class) { }, $class; } -sub can_use($self, $set, $records) { +sub can_use ($self, $set, $records, $c) { return 0 unless $set->assignment_type eq 'default' && after($set->open_date); diff --git a/lib/WeBWorK/AchievementItems/HalfCreditSet.pm b/lib/WeBWorK/AchievementItems/HalfCreditSet.pm index 37496e9bdd..eb6861c9f1 100644 --- a/lib/WeBWorK/AchievementItems/HalfCreditSet.pm +++ b/lib/WeBWorK/AchievementItems/HalfCreditSet.pm @@ -14,7 +14,7 @@ sub new ($class) { }, $class; } -sub can_use($self, $set, $records) { +sub can_use ($self, $set, $records, $c) { return 0 unless $set->assignment_type eq 'default' && after($set->open_date); diff --git a/lib/WeBWorK/AchievementItems/NoReducedCred.pm b/lib/WeBWorK/AchievementItems/NoReducedCred.pm index d0e034eab2..bc46b3601b 100644 --- a/lib/WeBWorK/AchievementItems/NoReducedCred.pm +++ b/lib/WeBWorK/AchievementItems/NoReducedCred.pm @@ -18,9 +18,10 @@ sub new ($class) { }, $class; } -sub can_use ($self, $set, $records) { +sub can_use ($self, $set, $records, $c) { return $set->assignment_type eq 'default' + && $c->ce->{pg}{ansEvalDefaults}{enableReducedScoring} && $set->enable_reduced_scoring && $set->reduced_scoring_date && $set->reduced_scoring_date < $set->due_date diff --git a/lib/WeBWorK/AchievementItems/ReducedCred.pm b/lib/WeBWorK/AchievementItems/ReducedCred.pm index 340d960815..0a2349c9fc 100644 --- a/lib/WeBWorK/AchievementItems/ReducedCred.pm +++ b/lib/WeBWorK/AchievementItems/ReducedCred.pm @@ -21,7 +21,7 @@ sub new ($class) { }, $class; } -sub can_use ($self, $set, $records) { +sub can_use ($self, $set, $records, $c) { return $set->assignment_type eq 'default' && between($set->open_date, $set->due_date + ONE_DAY); } diff --git a/lib/WeBWorK/AchievementItems/ResetIncorrectAttempts.pm b/lib/WeBWorK/AchievementItems/ResetIncorrectAttempts.pm index cd0ef5a330..94a7c7b83c 100644 --- a/lib/WeBWorK/AchievementItems/ResetIncorrectAttempts.pm +++ b/lib/WeBWorK/AchievementItems/ResetIncorrectAttempts.pm @@ -14,7 +14,7 @@ sub new ($class) { }, $class; } -sub can_use ($self, $set, $records) { +sub can_use ($self, $set, $records, $c) { return 0 unless $set->assignment_type eq 'default' && between($set->open_date, $set->due_date); diff --git a/lib/WeBWorK/AchievementItems/ResurrectGW.pm b/lib/WeBWorK/AchievementItems/ResurrectGW.pm index 9f0b81b037..3d56b90d3c 100644 --- a/lib/WeBWorK/AchievementItems/ResurrectGW.pm +++ b/lib/WeBWorK/AchievementItems/ResurrectGW.pm @@ -22,9 +22,14 @@ sub new ($class) { }, $class; } -sub can_use ($self, $set, $records) { +sub can_use ($self, $set, $records, $c) { return $set->assignment_type =~ /gateway/ - && (after($set->due_date) || ($set->enable_reduced_scoring && after($set->reduced_scoring_date))); + && ( + after($set->due_date) + || ($c->ce->{pg}{ansEvalDefaults}{enableReducedScoring} + && $set->enable_reduced_scoring + && after($set->reduced_scoring_date)) + ); # TODO: Check if a new version can be created, and only allow using this reward in that case. } diff --git a/lib/WeBWorK/AchievementItems/ResurrectHW.pm b/lib/WeBWorK/AchievementItems/ResurrectHW.pm index 6a14c31ae6..37504bb165 100644 --- a/lib/WeBWorK/AchievementItems/ResurrectHW.pm +++ b/lib/WeBWorK/AchievementItems/ResurrectHW.pm @@ -16,7 +16,7 @@ sub new ($class) { }, $class; } -sub can_use ($self, $set, $records) { +sub can_use ($self, $set, $records, $c) { return $set->assignment_type eq 'default' && (after($set->due_date) || ($set->enable_reduced_scoring && after($set->reduced_scoring_date))); } @@ -85,16 +85,16 @@ sub use_item ($self, $set, $records, $c) { if ($set->enable_reduced_scoring && ($set->reduced_scoring_date != $set->due_date)) { return $c->maketext( 'This assignment has been reopened and is due on [_1]. After that date any work ' - . 'completed will count for [_2]% of its value until [_3]. ', + . 'completed will count for [_2]% of its value until [_3].', $c->formatDateTime($set->reduced_scoring_date, $c->ce->{studentDateDisplayFormat}), $c->ce->{pg}{ansEvalDefaults}{reducedScoringValue} * 100, $c->formatDateTime($set->due_date, $c->ce->{studentDateDisplayFormat}) - ) . $rerandomizeMessage; + ) . ($rerandomizeMessage ? " $rerandomizeMessage" : ''); } else { return $c->maketext( - 'This assignment has been reopened and will now close on [_1]. ', + 'This assignment has been reopened and will now close on [_1].', $c->formatDateTime($set->due_date, $c->ce->{studentDateDisplayFormat}) - ) . $rerandomizeMessage; + ) . ($rerandomizeMessage ? " $rerandomizeMessage" : ''); } } diff --git a/lib/WeBWorK/AchievementItems/SuperExtendDueDate.pm b/lib/WeBWorK/AchievementItems/SuperExtendDueDate.pm index 7932e6de20..b70c597d88 100644 --- a/lib/WeBWorK/AchievementItems/SuperExtendDueDate.pm +++ b/lib/WeBWorK/AchievementItems/SuperExtendDueDate.pm @@ -19,7 +19,7 @@ sub new ($class) { }, $class; } -sub can_use ($self, $set, $records) { +sub can_use ($self, $set, $records, $c) { return $set->assignment_type eq 'default' && between($set->open_date, $set->due_date + TWO_DAYS); } diff --git a/lib/WeBWorK/AchievementItems/SuperExtendReducedDate.pm b/lib/WeBWorK/AchievementItems/SuperExtendReducedDate.pm index 8e5fa42c79..656b85d5ac 100644 --- a/lib/WeBWorK/AchievementItems/SuperExtendReducedDate.pm +++ b/lib/WeBWorK/AchievementItems/SuperExtendReducedDate.pm @@ -20,7 +20,7 @@ sub new ($class) { }, $class; } -sub can_use ($self, $set, $records) { +sub can_use ($self, $set, $records, $c) { return 0 unless $set->assignment_type eq 'default' && $set->enable_reduced_scoring diff --git a/lib/WeBWorK/AchievementItems/Surprise.pm b/lib/WeBWorK/AchievementItems/Surprise.pm index b598b75352..c3c4331a86 100644 --- a/lib/WeBWorK/AchievementItems/Surprise.pm +++ b/lib/WeBWorK/AchievementItems/Surprise.pm @@ -18,7 +18,7 @@ sub remaining_title ($self, $c) { return $c->maketext($self->name); } -sub can_use ($self, $set, $records) { return 1; } +sub can_use ($self, $set, $records, $c) { return 1; } sub print_form ($self, $set, $records, $c) { $self->{hideUseButton} = 1; From f7a5a940a82c2bd9fa68a5d7f0cddbb2ac15eb03 Mon Sep 17 00:00:00 2001 From: Danny Glin Date: Tue, 14 Apr 2026 09:26:03 -0600 Subject: [PATCH 6/8] Update lib/WeBWorK/AchievementItems/ResurrectHW.pm Co-authored-by: Glenn Rice <47527406+drgrice1@users.noreply.github.com> --- lib/WeBWorK/AchievementItems/ResurrectHW.pm | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/lib/WeBWorK/AchievementItems/ResurrectHW.pm b/lib/WeBWorK/AchievementItems/ResurrectHW.pm index 37504bb165..3726b964a6 100644 --- a/lib/WeBWorK/AchievementItems/ResurrectHW.pm +++ b/lib/WeBWorK/AchievementItems/ResurrectHW.pm @@ -18,7 +18,12 @@ sub new ($class) { sub can_use ($self, $set, $records, $c) { return $set->assignment_type eq 'default' - && (after($set->due_date) || ($set->enable_reduced_scoring && after($set->reduced_scoring_date))); + && ( + after($set->due_date) + || ($c->ce->{pg}{ansEvalDefaults}{enableReducedScoring} + && $set->enable_reduced_scoring + && after($set->reduced_scoring_date)) + ); } sub print_form ($self, $set, $records, $c) { From 447cecb5bb7583374d3043dffbbec23de714591c Mon Sep 17 00:00:00 2001 From: Danny Glin Date: Tue, 14 Apr 2026 09:26:28 -0600 Subject: [PATCH 7/8] Update lib/WeBWorK/AchievementItems/ResurrectHW.pm Co-authored-by: Glenn Rice <47527406+drgrice1@users.noreply.github.com> --- lib/WeBWorK/AchievementItems/ResurrectHW.pm | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/lib/WeBWorK/AchievementItems/ResurrectHW.pm b/lib/WeBWorK/AchievementItems/ResurrectHW.pm index 3726b964a6..4c5e9e862d 100644 --- a/lib/WeBWorK/AchievementItems/ResurrectHW.pm +++ b/lib/WeBWorK/AchievementItems/ResurrectHW.pm @@ -87,7 +87,10 @@ sub use_item ($self, $set, $records, $c) { } $db->putUserSet($userSet); - if ($set->enable_reduced_scoring && ($set->reduced_scoring_date != $set->due_date)) { + if ($c->ce->{pg}{ansEvalDefaults}{enableReducedScoring} + && $set->enable_reduced_scoring + && ($set->reduced_scoring_date != $set->due_date)) + { return $c->maketext( 'This assignment has been reopened and is due on [_1]. After that date any work ' . 'completed will count for [_2]% of its value until [_3].', From 25c9dc608bb7f8be91e8d6e3a0a3bb4eea5a840e Mon Sep 17 00:00:00 2001 From: Danny Glin Date: Tue, 14 Apr 2026 09:26:46 -0600 Subject: [PATCH 8/8] Update lib/WeBWorK/AchievementItems/ResurrectGW.pm Co-authored-by: Glenn Rice <47527406+drgrice1@users.noreply.github.com> --- lib/WeBWorK/AchievementItems/ResurrectGW.pm | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/lib/WeBWorK/AchievementItems/ResurrectGW.pm b/lib/WeBWorK/AchievementItems/ResurrectGW.pm index 3d56b90d3c..bbd93b419f 100644 --- a/lib/WeBWorK/AchievementItems/ResurrectGW.pm +++ b/lib/WeBWorK/AchievementItems/ResurrectGW.pm @@ -102,7 +102,10 @@ sub use_item ($self, $set, $records, $c) { } $db->putUserSet($userSet); - if ($set->enable_reduced_scoring && ($set->reduced_scoring_date != $set->due_date)) { + if ($c->ce->{pg}{ansEvalDefaults}{enableReducedScoring} + && $set->enable_reduced_scoring + && ($set->reduced_scoring_date != $set->due_date)) + { return $c->maketext( 'This assignment has been reopened and is due on [_1]. After that date any work ' . 'completed will count for [_2]% of its value until [_3].',