Skip to content

Commit

Permalink
Merge pull request #626 from abasyrov/periodicRandomization
Browse files Browse the repository at this point in the history
Periodic randomization
  • Loading branch information
goehle committed Oct 7, 2015
2 parents 19961e3 + e9dcd7d commit 8ba37cf
Show file tree
Hide file tree
Showing 10 changed files with 215 additions and 20 deletions.
27 changes: 27 additions & 0 deletions conf/defaults.config
Expand Up @@ -188,6 +188,16 @@ $pg{options}{showMeAnother}=[
"SMAshowCorrect",
"SMAshowHints",
];

###############################################################################
# periodicRandomization
################################################################################
# switch to enable periodic re-randomization
$pg{options}{enablePeriodicRandomization} = 0;
# course-wide default period for re-randomization, should be an integer
# the value of 0 disables re-randomization
$pg{options}{periodicRandomizationPeriod} = 5;

################################################################################
# Language
################################################################################
Expand Down Expand Up @@ -1164,6 +1174,13 @@ $problemDefaults{att_to_open_children} = 1;
# a problem. This only matters for JITAR sets
$problemDefaults{counts_parent_grade} = 0;

# The default prPeriod value (re-randomization period) to use for the newly created problem.
# It is suggested to use the value of -1, which means that the course-wide setting would be used
# Setting this to -1 defaults to the use of course-wide settings (suggested)
# Setting this to 0 disables periodic randomization regardless of the course-wide setting
# Setting this to a positive value will override the course-wide setting
$problemDefaults{prPeriod} = -1;

##### Answer evaluatior defaults

$pg{ansEvalDefaults} = {
Expand Down Expand Up @@ -1537,6 +1554,16 @@ $ConfigValues = [
doc2 => 'A switch to govern the use of a Progress Bar for the student; this also enables/disables the highlighting of the current problem in the side bar, and whether it is correct (✓), in progress (…), incorrect (✗), or unattempted (no symbol).',
type => 'boolean'
},
{ var => 'pg{options}{enablePeriodicRandomization}',
doc => 'Enable periodic re-randomization of problems',
doc2 => 'Enables periodic re-randomization of problems after a given number of attempts. Student would have to click Request New Version to obtain new version of the problem and to continue working on the problem',
type => 'boolean'
},
{ var => 'pg{options}{periodicRandomizationPeriod}',
doc => 'The number of attempts between re-randomization of the problems ( 0 => never)',
doc2 => 'The number of attempts before the problem is re-randomized. ( 0 => never )',
type => 'number'
},
],
['E-Mail',
{ var => 'mail{feedbackSubjectFormat}',
Expand Down
18 changes: 18 additions & 0 deletions conf/localOverrides.conf.dist
Expand Up @@ -257,6 +257,24 @@ $problemDefaults{max_attempts} = -1;
# setting this to -1 disables the showMeAnother button
$problemDefaults{showMeAnother} = -1;

# The default prPeriod value (re-randomization period) to use for the newly created problem.
# It is suggested to use the value of -1, which means that the course-wide setting would be used
# Setting this to -1 defaults to the use of course-wide settings (suggested)
# Setting this to 0 disables periodic randomization regardless of the course-wide setting
# Setting this to a positive value will override the course-wide setting
$problemDefaults{prPeriod} = -1;


################################################################################
# Periodic re-randomization
################################################################################
# switch to enable periodic re-randomization
$pg{options}{enablePeriodicRandomization} = 0;
# course-wide default period for re-randomization, should be an integer
# the value of 0 disables re-randomization
$pg{options}{periodicRandomizationPeriod} = 5;


################################################################################
# "Special" PG environment variables. (Stuff that doesn't fit in anywhere else.)
################################################################################
Expand Down
7 changes: 7 additions & 0 deletions lib/WeBWorK/ContentGenerator/Instructor.pm
Expand Up @@ -523,6 +523,7 @@ sub addProblemToSet {
my $showMeAnother_default = $self->{ce}->{problemDefaults}->{showMeAnother};
my $att_to_open_children_default = $self->{ce}->{problemDefaults}->{att_to_open_children};
my $counts_parent_grade_default = $self->{ce}->{problemDefaults}->{counts_parent_grade};
my $prPeriod_default = $self->{ce}->{problemDefaults}->{prPeriod};
# showMeAnotherCount is the number of times that showMeAnother has been clicked; initially 0
my $showMeAnotherCount = 0;

Expand All @@ -541,6 +542,10 @@ sub addProblemToSet {

my $maxAttempts = $args{maxAttempts} || $max_attempts_default;
my $showMeAnother = $args{showMeAnother} || $showMeAnother_default;
my $prPeriod = $prPeriod_default;
if (defined($args{prPeriod})){
$prPeriod = $args{prPeriod};
}
my $problemID = $args{problemID};
my $countsParentGrade = $args{countsParentGrade} || $counts_parent_grade_default;
my $attToOpenChildren = $args{attToOpenChildren} || $att_to_open_children_default;
Expand Down Expand Up @@ -569,6 +574,8 @@ sub addProblemToSet {
$problemRecord->counts_parent_grade($countsParentGrade);
$problemRecord->showMeAnother($showMeAnother);
$problemRecord->{showMeAnotherCount}=$showMeAnotherCount;
$problemRecord->prPeriod($prPeriod);
$problemRecord->prCount(0);
$db->addGlobalProblem($problemRecord);

return $problemRecord;
Expand Down
23 changes: 19 additions & 4 deletions lib/WeBWorK/ContentGenerator/Instructor/ProblemSetDetail.pm
Expand Up @@ -40,12 +40,12 @@ use WeBWorK::Utils::DatePickerScripts;

# these constants determine which fields belong to what type of record
use constant SET_FIELDS => [qw(set_header hardcopy_header open_date reduced_scoring_date due_date answer_date visible description enable_reduced_scoring restricted_release restricted_status restrict_ip relax_restrict_ip assignment_type attempts_per_version version_time_limit time_limit_cap versions_per_interval time_interval problem_randorder problems_per_page hide_score:hide_score_by_problem hide_work hide_hint)];
use constant PROBLEM_FIELDS =>[qw(source_file value max_attempts showMeAnother)];
use constant PROBLEM_FIELDS =>[qw(source_file value max_attempts showMeAnother prPeriod)];
use constant USER_PROBLEM_FIELDS => [qw(problem_seed status num_correct num_incorrect)];

# these constants determine what order those fields should be displayed in
use constant HEADER_ORDER => [qw(set_header hardcopy_header)];
use constant PROBLEM_FIELD_ORDER => [qw(problem_seed status value max_attempts showMeAnother attempted last_answer num_correct num_incorrect)];
use constant PROBLEM_FIELD_ORDER => [qw(problem_seed status value max_attempts showMeAnother prPeriod attempted last_answer num_correct num_incorrect)];
# for gateway sets, we don't want to allow users to change max_attempts on a per
# problem basis, as that's nothing but confusing.
use constant GATEWAY_PROBLEM_FIELD_ORDER => [qw(problem_seed status value attempted last_answer num_correct num_incorrect)];
Expand Down Expand Up @@ -340,6 +340,17 @@ use constant FIELD_PROPERTIES => {
"-1" => "Never",
},
},
prPeriod => {
name => "Rerandomize after",
type => "edit",
size => "6",
override => "any",
default=>"-1",
labels => {
"-1" => "Default",
"0" => "Never",
},
},
problem_seed => {
name => "Seed",
type => "edit",
Expand Down Expand Up @@ -496,6 +507,10 @@ sub FieldTable {
next if ( $field eq 'showMeAnother' &&
!$ce->{pg}->{options}->{enableShowMeAnother} );

# skip the periodic re-randomization field if it is not enabled
next if ( $field eq 'prPeriod' &&
!$ce->{pg}->{options}->{enablePeriodicRandomization} );

unless ($properties{type} eq "hidden") {
$output .= CGI::Tr({}, CGI::td({}, [$self->FieldHTML($userID, $setID, $problemID, $globalRecord, $userRecord, $field)])) . "\n";
}
Expand Down Expand Up @@ -588,8 +603,8 @@ sub FieldHTML {
}

# use defined instead of value in order to allow 0 to printed, e.g. for the 'value' field
$globalValue = (defined($globalValue)) ? ($labels{$globalValue || ""} || $globalValue) : "";
$userValue = (defined($userValue)) ? ($labels{$userValue || ""} || $userValue) : $blankfield;
$globalValue = (defined($globalValue)) ? ($labels{$globalValue // ""} || $globalValue) : ""; # this allows for a label if value is 0
$userValue = (defined($userValue)) ? ($labels{$userValue // ""} || $userValue) : $blankfield; # this allows for a label if value is 0

if ($field =~ /_date/) {
$globalValue = $self->formatDateTime($globalValue,'','%m/%d/%Y at %I:%M%P') if defined $globalValue && $globalValue ne $labels{""};
Expand Down
24 changes: 20 additions & 4 deletions lib/WeBWorK/ContentGenerator/Instructor/ProblemSetDetail2.pm
Expand Up @@ -41,12 +41,12 @@ use WeBWorK::Utils::DatePickerScripts;

# these constants determine which fields belong to what type of record
use constant SET_FIELDS => [qw(set_header hardcopy_header open_date reduced_scoring_date due_date answer_date visible description enable_reduced_scoring restricted_release restricted_status restrict_ip relax_restrict_ip assignment_type attempts_per_version version_time_limit time_limit_cap versions_per_interval time_interval problem_randorder problems_per_page hide_score:hide_score_by_problem hide_work hide_hint restrict_prob_progression email_instructor)];
use constant PROBLEM_FIELDS =>[qw(source_file value max_attempts showMeAnother att_to_open_children counts_parent_grade)];
use constant PROBLEM_FIELDS =>[qw(source_file value max_attempts showMeAnother prPeriod att_to_open_children counts_parent_grade)];
use constant USER_PROBLEM_FIELDS => [qw(problem_seed status num_correct num_incorrect)];

# these constants determine what order those fields should be displayed in
use constant HEADER_ORDER => [qw(set_header hardcopy_header)];
use constant PROBLEM_FIELD_ORDER => [qw(problem_seed status value max_attempts showMeAnother attempted last_answer num_correct num_incorrect)];
use constant PROBLEM_FIELD_ORDER => [qw(problem_seed status value max_attempts showMeAnother prPeriod attempted last_answer num_correct num_incorrect)];
# for gateway sets, we don't want to allow users to change max_attempts on a per
# problem basis, as that's nothing but confusing.
use constant GATEWAY_PROBLEM_FIELD_ORDER => [qw(problem_seed status value attempted last_answer num_correct num_incorrect)];
Expand Down Expand Up @@ -367,6 +367,18 @@ use constant FIELD_PROPERTIES => {
},
help_text => "When a student has more attempts than is specified here they will be able to view another version of this problem. The new version is guaranteed to be different or the feature will fail gracefully. Depending on the course configuration students will be able to attempt this new version as many times as they want or see a worked out solution, if one exists."
},
prPeriod => {
name => "Rerandomize after",
type => "edit",
size => "6",
override => "any",
default=>"-1",
labels => {
"-1" => "Default",
"0" => "Never",
},
help_text => "This specifies the rerandomization period: the number of attempts before a new version of the problem is generated by changing the Seed value. The value of -1 uses the default from course configuration. The value of 0 disables rerandomization.",
},
problem_seed => {
name => "Seed",
type => "edit",
Expand Down Expand Up @@ -554,6 +566,10 @@ sub FieldTable {
next if ( $field eq 'showMeAnother' &&
!$ce->{pg}->{options}->{enableShowMeAnother} );

# skip the periodic re-randomization field if it is not enabled
next if ( $field eq 'prPeriod' &&
!$ce->{pg}->{options}->{enablePeriodicRandomization} );

unless ($properties{type} eq "hidden") {
$output .= CGI::Tr({}, CGI::td({}, [$self->FieldHTML($userID, $setID, $problemID, $globalRecord, $userRecord, $field)])) . "\n";
}
Expand Down Expand Up @@ -647,8 +663,8 @@ sub FieldHTML {
}

# use defined instead of value in order to allow 0 to printed, e.g. for the 'value' field
$globalValue = (defined($globalValue)) ? ($labels{$globalValue || ""} || $globalValue) : "";
$userValue = (defined($userValue)) ? ($labels{$userValue || ""} || $userValue) : $blankfield;
$globalValue = (defined($globalValue)) ? ($labels{$globalValue // ""} || $globalValue) : ""; # this allows for a label if value is 0
$userValue = (defined($userValue)) ? ($labels{$userValue // ""} || $userValue) : $blankfield; # this allows for a label if value is 0

if ($field =~ /_date/) {
$globalValue = $self->formatDateTime($globalValue,'','%m/%d/%Y at %I:%M%P') if defined $globalValue && $globalValue ne $labels{""};
Expand Down
34 changes: 25 additions & 9 deletions lib/WeBWorK/ContentGenerator/Instructor/ProblemSetList2.pm
Expand Up @@ -1794,6 +1794,7 @@ sub importSetsFromDef {
value => $rh_problem->{value},
maxAttempts => $rh_problem->{max_attempts},
showMeAnother => $rh_problem->{showMeAnother},
prPeriod => $rh_problem->{prPeriod},
attToOpenChildren => $rh_problem->{attToOpenChildren},
countsParentGrade => $rh_problem->{countsParentGrade}
);
Expand Down Expand Up @@ -1838,7 +1839,8 @@ sub readSetDef {
my $counts_parent_grade_default =
$self->{ce}->{problemDefaults}->{counts_parent_grade};
my $showMeAnother_default = $self->{ce}->{problemDefaults}->{showMeAnother};

my $prPeriod_default=$self->{ce}->{problemDefaults}->{prPeriod};

my $setName = '';

my $r = $self->r;
Expand Down Expand Up @@ -1866,9 +1868,12 @@ sub readSetDef {
# added fields for gateway test/versioned set definitions:
my ( $assignmentType, $attemptsPerVersion, $timeInterval,
$versionsPerInterval, $versionTimeLimit, $problemRandOrder,
$problemsPerPage, $restrictLoc, $emailInstructor, $restrictProbProgression, $countsParentGrade, $attToOpenChildren, $problemID, $showMeAnother, $listType
$problemsPerPage, $restrictLoc,
$emailInstructor, $restrictProbProgression,
$countsParentGrade, $attToOpenChildren,
$problemID, $showMeAnother, $prPeriod, $listType
) =
('')x8; # initialize these to ''
('')x16; # initialize these to ''
my ( $timeCap, $restrictIP, $relaxRestrictIP ) = ( 0, 'No', 'No');
# additional fields currently used only by gateways; later, the world?
my ( $hideScore, $hideWork, ) = ( 'N', 'N' );
Expand Down Expand Up @@ -2059,9 +2064,11 @@ sub readSetDef {
# can't put continuation flag onto the first problem
push(@problemData, {source_file => $name,
value => $weight,
max_attempts =>, $attemptLimit,
showMeAnother =>, $showMeAnother,
continuation => $continueFlag
max_attempts => $attemptLimit,
showMeAnother => $showMeAnother,
# use default since it's not going to be in the file
prPeriod => $prPeriod_default,
continuation => $continueFlag,
});
}
} else {
Expand Down Expand Up @@ -2095,6 +2102,8 @@ sub readSetDef {
$attemptLimit = ( $value ) ? $value : $max_attempts_default;
} elsif ( $item eq 'showMeAnother' ) {
$showMeAnother = ( $value ) ? $value : 0;
} elsif ( $item eq 'prPeriod' ) {
$prPeriod = ( $value ) ? $value : 0;
} elsif ( $item eq 'restrictProbProgression' ) {
$restrictProbProgression = ( $value ) ? $value : 'No';
} elsif ( $item eq 'problem_id' ) {
Expand Down Expand Up @@ -2122,6 +2131,9 @@ sub readSetDef {
unless ($showMeAnother =~ /-?\d+/) {$showMeAnother = $showMeAnother_default;}
$showMeAnother =~ s/[^-?\d-]*//g;

unless ($prPeriod =~ /-?\d+/) {$prPeriod = $prPeriod_default;}
$prPeriod =~ s/[^-?\d-]*//g;

unless ($attToOpenChildren =~ /\d+/) {$attToOpenChildren = $att_to_open_children_default;}
$attToOpenChildren =~ s/[^\d-]*//g;

Expand All @@ -2138,10 +2150,11 @@ sub readSetDef {
push(@problemData, {source_file => $name,
problemID => $problemID,
value => $weight,
max_attempts =>, $attemptLimit,
showMeAnother =>, $showMeAnother,
max_attempts => $attemptLimit,
showMeAnother => $showMeAnother,
prPeriod => $prPeriod,
attToOpenChildren => $attToOpenChildren,
countsParentGrade => $countsParentGrade
countsParentGrade => $countsParentGrade,
});


Expand Down Expand Up @@ -2249,6 +2262,7 @@ SET: foreach my $set (keys %filenames) {
my $value = $problemRecord->value();
my $max_attempts = $problemRecord->max_attempts();
my $showMeAnother = $problemRecord->showMeAnother();
my $prPeriod = $problemRecord->prPeriod();
my $countsParentGrade = $problemRecord->counts_parent_grade();
my $attToOpenChildren = $problemRecord->att_to_open_children();

Expand All @@ -2257,6 +2271,7 @@ SET: foreach my $set (keys %filenames) {
$value =~ s/([,\\])/\\$1/g;
$max_attempts =~ s/([,\\])/\\$1/g;
$showMeAnother =~ s/([,\\])/\\$1/g;
$prPeriod =~ s/([,\\])/\\$1/g;

# This is the new way of saving problem information
# the labelled list makes it easier to add variables and
Expand All @@ -2266,6 +2281,7 @@ SET: foreach my $set (keys %filenames) {
$problemList .= "value = $value\n";
$problemList .= "max_attempts = $max_attempts\n";
$problemList .= "showMeAnother = $showMeAnother\n";
$problemList .= "prPeriod = $prPeriod\n";
$problemList .= "problem_id = $problem_id\n";
$problemList .= "counts_parent_grade = $countsParentGrade\n";
$problemList .= "att_to_open_children = $attToOpenChildren \n";
Expand Down

0 comments on commit 8ba37cf

Please sign in to comment.