Skip to content

Commit

Permalink
Rework the persistence hash.
Browse files Browse the repository at this point in the history
This replaces all of the previous persistence hash methods with a single
`peristent_data` method.  This method both saves to and retrieves from
the persistence hash.  The first (or second including self in PGcore)
parameter is the key in the persistence hash.  If the optional second
(or third including self in PGcore) parameter is not given then the
value of the key for the given label in the hash will be returned.  If
the second parameter is given then the value of the key in the hash will
be saved or updated.  Note that if third parameter is given but is
undefined then the key will be deleted from the hash.  Anything that can
be JSON encoded can be stored.

Any frontend should save the persistence hash in some way, and send it
back each time the problem is rendered.

The `store_persistent_data`, `update_persistent_data`, and
`get_peristent_data` methods from before still exist in PG.pl (but were
removed from PGcore.pl) and they all just call the new `persistent_data`
method.  However, they should be considered deprecated, and are only
left for backwards compatability.  Note that the `store_persistent_data`
method no longer warns if one tries to set the data for a key in the
hash that is already set.  There was no reason for that warning and
probably is why the `update_persistent_data` method was created that
does exactly the same thing except that it doesn't warn and it doesn't
return the label that was passed in (why do that anyway?). The whole
mechanism was rather poorly designed to begin with.
  • Loading branch information
drgrice1 committed Dec 18, 2024
1 parent d0175d5 commit 1936e20
Show file tree
Hide file tree
Showing 3 changed files with 46 additions and 28 deletions.
36 changes: 15 additions & 21 deletions lib/PGcore.pm
Original file line number Diff line number Diff line change
Expand Up @@ -75,18 +75,17 @@ sub new {

# Holds other data, besides answers, which persists during a session and beyond.
PERSISTENCE_HASH => $envir->{PERSISTENCE_HASH} // {}, # Main data, received from DB
PERSISTENCE_HASH_UPDATED => {}, # Keys whose updated values should be saved by the DB
answer_name_count => 0,
implicit_named_answer_stack => [],
implicit_answer_eval_stack => [],
explicit_answer_name_evals => {},
KEPT_EXTRA_ANSWERS => [],
ANSWER_PREFIX => 'AnSwEr',
ARRAY_PREFIX => 'ArRaY',
vec_num => 0, # for distinguishing matrices
vec_num => 0, # for distinguishing matrices
QUIZ_PREFIX => $envir->{QUIZ_PREFIX},
PG_VERSION => $ENV{PG_VERSION},
PG_ACTIVE => 1, # toggle to zero to stop processing
PG_ACTIVE => 1, # toggle to zero to stop processing
submittedAnswers => 0, # have any answers been submitted? is this the first time this session?
PG_session_persistence_hash => {}, # stores data from one invoction of the session to the next.
PG_original_problem_seed => 0,
Expand Down Expand Up @@ -477,25 +476,20 @@ sub extend_ans_group { # modifies the group type
return $label;
}

sub store_persistent_data { # will store strings only (so far)
my ($self, $label, @values) = @_;
if (defined($self->{PERSISTENCE_HASH}->{$label})) {
warn "can' overwrite $label in persistent data";
} else {
$self->{PERSISTENCE_HASH_UPDATED}{$label} = 1;
$self->{PERSISTENCE_HASH}{$label} = join("", @values);
# Save to or retrieve data from the persistence hash. The $label parameter is the key in the persistence hash. If the
# $value parameter is not given then the value of the $label key in the hash will be returned. If the $value parameter
# is given then the value of the $label key in the hash will be saved or updated. Note that if the $value parameter is
# given but is undefined then the $label key will be deleted from the hash. Anything that can be JSON encoded can be
# stored.
sub persistent_data {
my ($self, $label, $value) = @_;
if (@_ > 2) {
if (defined $value) {
$self->{PERSISTENCE_HASH}{$label} = $value;
} else {
delete $self->{PERSISTENCE_HASH}{$label};
}
}
$label;
}

sub update_persistent_data { # will store strings only (so far)
my ($self, $label, @values) = @_;
$self->{PERSISTENCE_HASH_UPDATED}{$label} = 1;
$self->{PERSISTENCE_HASH}{$label} = join("", @values);
}

sub get_persistent_data {
my ($self, $label) = @_;
return $self->{PERSISTENCE_HASH}{$label};
}

Expand Down
4 changes: 0 additions & 4 deletions lib/WeBWorK/PG.pm
Original file line number Diff line number Diff line change
Expand Up @@ -264,10 +264,6 @@ sub defineProblemEnvironment ($pg_envir, $options = {}, $image_generator = undef
showMessages => $options->{showMessages} // 1,
showCorrectAnswers => $options->{showCorrectAnswers} // 0,

# The next has marks what data was updated and needs to be saved
# by the front end.
PERSISTENCE_HASH_UPDATED => {},

inputs_ref => $options->{inputs_ref},

(map { $_ => $ansEvalDefaults->{$_} } keys %$ansEvalDefaults),
Expand Down
34 changes: 31 additions & 3 deletions macros/PG.pl
Original file line number Diff line number Diff line change
Expand Up @@ -545,19 +545,47 @@ sub ANS_NUM_TO_NAME {
$PG->new_label(@_);
}

=head2 persistent_data
Save to or retrieve data from the persistence hash. The persistence hash is data
that will persist for this problem. It is saved when answers are submitted, and
can be retrieved and used within a problem.
persistent_data($label);
persistent_data($label, $value);
The C<$label> parameter is the key in the persistence hash. If the C<$value>
parameter is not given then the value of the C<$label> key in the hash will be
returned. If the C<$value> parameter is given then the value of the C<$label>
key in the hash will be saved or updated. Note that if the C<$value> parameter
is given but is undefined then the C<$label> key will be deleted from the hash.
Anything that can be JSON encoded can be stored.
=cut

sub persistent_data {
my ($label, @value) = @_;
return $PG->persistent_data($label, @value);
}

# The store_persistent_data, update_persistent_data, and get_persistent_data methods are deprecated and are only still
# here for backward compatability. Use the persistent_data method instead which can do everything these three methods
# can do. Note that if you use the persistent_data method, then you will need to join the values as strings if you want
# that. Even better pass the persistent_data method an array reference containing the values so you can avoid the hassle
# of splitting the values when they are retrieved.
sub store_persistent_data {
my ($label, @values) = @_;
$PG->store_persistent_data($label, @values);
return $PG->persistent_data($label, join('', @values));
}

sub update_persistent_data {
my ($label, @values) = @_;
$PG->update_persistent_data($label, @values);
return $PG->persistent_data($label, join('', @values));
}

sub get_persistent_data {
my ($label) = @_;
return $PG->get_persistent_data($label);
return $PG->persistent_data($label);
}

sub add_content_post_processor {
Expand Down

0 comments on commit 1936e20

Please sign in to comment.