Skip to content

Commit

Permalink
Patches to allow preventing scaffold from changing which sections
Browse files Browse the repository at this point in the history
are open when Preview is called: (a) Allow preventing opening an additional
section when all answers of the last open section are correct during
processing a Preview render, and (b) Allow preventing scaffold closing
previously open sections if an answer to a prior section became incorrect
when processing a Preview render.

Control switches control if these modified behaviors are used or not.

The defaults maintain the prior behavior.

Some contributions to a prior version of this code by Glenn Rice.
  • Loading branch information
taniwallach committed Apr 20, 2023
1 parent 4b947ad commit 106b3a2
Showing 1 changed file with 65 additions and 10 deletions.
75 changes: 65 additions & 10 deletions macros/core/scaffold.pl
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,21 @@ =head1 DESCRIPTION
have the student open it by hand before anwering the questions. In
this case, set this value to 0 (it is 1 by default).
=item C<S<< allow_next_section_to_open_on_preview => 0 or 1 >>>
This determines whether Preview My Answers should be allowed to open
a new section. Set this to 0 to prevent the next section from opening
after Preview My Answers is clicked (it is 1 by default).
=item C<S<< prevent_close_by_preview => 0 or 1 >>>
This determines whether Preview My Answers should be allowed to close
a section which was open before, if the prior answers were changed to be
incorrect. By default the setting is 0, so such section closures can
occur due to a Preview, while when set to 1 sections will not be closed by
Preview.
=item C<S<< numbered => 0 or 1 >>>
This determines whether each section is automatically numbered before
Expand Down Expand Up @@ -316,6 +331,7 @@ sub Begin {
unshift(@scaffolds, $self);
$scaffold = $self;
$scaffold_depth++;
$self->{key_last_open} = "ScAfFoLd_${PREFIX}_SC-" . $self->{number} . "_last_open";
$self->{previous_output} =
[ splice(@{$PG_OUTPUT}, 0) ]; # get output and clear it without changing the array pointer
$self->{output} = []; # the contents of the scaffold
Expand All @@ -338,6 +354,12 @@ sub End {
$self->hide_other_results(@{ $self->{open} }); # hide results of unnopened sections in the results table
push(@$PG_OUTPUT, @{ $self->{previous_output} }, @{ $self->{output} })
; # put back original output and scaffold output

if (!$self->{isPreview}) {
# Record the last_open value for future renders
main::update_persistent_data($self->{key_last_open}, $self->{open}[-1] ? $self->{open}[-1] : 0);
}

delete $self->{previous_output};
delete $self->{output}; # don't need these any more
shift(@scaffolds);
Expand Down Expand Up @@ -372,6 +394,11 @@ sub new {
hardcopy_is_open => "always", # open all possible sections in hardcopy
open_first_section => 1, # 0 means don't open any sections initially
numbered => 0, # 1 means sections will be printed with their number

# control whether Preview should be allowed to open/close sections
allow_next_section_to_open_on_preview => 1, # can Preview open another section
prevent_close_by_preview => 0, # can Preview close previously open sections

@_,
number => ++$scaffold_no, # the number for this scaffold
depth => $scaffold_depth, # the nesting depth for this scaffold
Expand Down Expand Up @@ -402,7 +429,7 @@ sub start_section {

#
# Add the content from the current section into the scaffold's output
# and remove the current_section (so we can tell that no sectionis open).
# and remove the current_section (so we can tell that no section is open).
#
sub end_section {
my $self = shift;
Expand All @@ -415,8 +442,10 @@ sub end_section {
# keeping the scores for future reference.
#
sub section_answers {
my $self = shift;
my ($self, @this_section_answers) = @_;
my %answers;
my $section_no = $self->{section_no};
my $prior_last_open = main::get_persistent_data($self->{key_last_open});
#
# MultiAnswer objects can set the answer hash score when the last answer is evaluated,
# so save the hashes and look up the scores after they have all been called.
Expand All @@ -425,8 +454,8 @@ sub section_answers {
# to consider the score to be 1 (bug in PGessaymacros.pl prevents us from using
# it for essay_cmp(), though).
#
push(@{ $self->{ans_names} }, @_);
foreach my $name (@_) {
push(@{ $self->{ans_names} }, @this_section_answers);
foreach my $name (@this_section_answers) {
my $input = $main::inputs_ref->{$name};
my $evaluator = $PG_ANSWERS_HASH->{$name}->ans_eval;
Parser::Eval(sub { $answers{$name} = $evaluator->evaluate($input) }) if defined($input) && $input ne "";
Expand All @@ -435,11 +464,37 @@ sub section_answers {
$evaluator->{rh_ans}{ans_message} = "";
delete $evaluator->{rh_ans}{error_message};
}
foreach my $name (@_) { $self->{scores}{$name} = $answers{$name}{score} if $answers{$name} }

my $myLastSet; # we save the name of the last answer field whose score was set
for my $name (@this_section_answers) {
if ($answers{$name}) {
$self->{scores}{$name} = $answers{$name}{score};
$myLastSet = $name;
}
}
if ($myLastSet) {
$self->{isPreview} = $answers{$myLastSet}{isPreview} if (!defined($self->{isPreview}));
if ($self->{isPreview}) { # Only handle for Preview mode
if (
($section_no == $prior_last_open) # Only should consider modifying the last previously open section
&& !$self->{allow_next_section_to_open_on_preview}
)
{
# This should prevent the next section from opening on Preview
# if all answers to this section are correct, unless it would open anyway.
$self->{scores}{$myLastSet} = 0;
} elsif (($section_no < $prior_last_open) && $self->{prevent_close_by_preview}) {
# This section was open before - AVOID closing it due to a change in prior sections and a Preview
for my $name (@{ $self->{ans_names} }) {
$self->{scores}{$name} = 1.0 if ($answers{$name}); # to prevent it from being closed
}
}
}
}
}

#
# Add the given sections to the list of sections to be openned
# Add the given sections to the list of sections to be opened
# for this scaffold
#
sub is_open {
Expand Down Expand Up @@ -601,7 +656,7 @@ sub new {
# Adds the necessary HTML around the content of the section.
#
# First, determine the is_correct and can_open status and save them.
# Then check if the section is to be openned, and if so, add it
# Then check if the section is to be opened, and if so, add it
# to the open list of the scaffold.
#
# The $PG_OUTPUT variable holds just the contents of this section,
Expand Down Expand Up @@ -745,11 +800,11 @@ sub new_answers {
package Section::can_open;

#
# Always can be openned
# Always can be opened
#
sub always { return 1 }
#
# Can be openned when all the answers from previous sections are correct
# Can be opened when all the answers from previous sections are correct
#
sub when_previous_correct {
my $section = shift;
Expand All @@ -772,7 +827,7 @@ sub incorrect {
return !$section->{is_correct};
}
#
# Never can be openned
# Never can be opened
#
sub never { return 0 }

Expand Down

0 comments on commit 106b3a2

Please sign in to comment.