Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 41 additions & 0 deletions macros/contexts/contextSignificantFiguresUnits.pl
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@

BEGIN { strict->import }

loadMacros('contextUnits.pl', 'contextSignificantFigures.pl');

sub _contextSignificantFiguresUnits_init {
context::SignificantFiguresUnits::Init(@_);
}

package context::SignificantFiguresUnits::NumberWithUnit;
our @ISA = ('context::Units::NumberWithUnit');

# call the postprocess for handling error messages and flags.
# This needs to be called for the SignificantFigure and Units separately.

sub cmp_postprocess {
my ($self, $ansHash) = @_;
$self->unit->cmp_postprocess($ansHash);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think you should be calling $self->SUPER::cmp_postprocess($ansHash) not the unit's post-processor in order to get the correct tests and messages. You don't want to post-process a student answer that is a number with units against just a unit (the unit cmp_postprocess() function returns immediately if the student value isn't a Unit object a number-with-units isn't a Unit.

Also, you may wish to return early if cmp_postprocess() produces any messages. Otherwise you may overwrite them. You will have to decide whose messages and partial credit take precedence, but I would say that you shouldn't give messages about the number being close if the units are not correct, so breaking out early seems the right solution.

# Since the current $ansHash has the correct and student value as the NumberWithUnits type
# pass in just the number (SignificantFigure) to the postprocess.
$ansHash->{correct_value} = $ansHash->{correct_value}->number;
$ansHash->{student_value} = $ansHash->{student_value}->number;
Comment on lines +22 to +23

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think you should probably cache the old values and replace them after doing the cmp_postprocess() call. You don't know if there are other post-filters that will run after yours, and having these values change on them could be a problem.

$self->number->cmp_postprocess($ansHash);
}

package context::SignificantFiguresUnits;

sub Init {
my $context = $main::context{SignificantFiguresUnits} = context::Units::extending('SignificantFigures');
$context->{value}{NumberWithUnit} = 'context::SignificantFiguresUnits::NumberWithUnit';
$context->{value}{'Number-with-Unit'} = 'context::SignificantFiguresUnits::NumberWithUnit';
$context = $main::context{LimitedSignificantFiguresUnits} = $context->copy;
$context->{name} = 'LimitedSignificantFiguresUnits';
$context->parens->undefine('|', '{', '[');
$context->variables->remove('x');
$context->operators->undefine('-', '+', '/', '//', ' /', '/ ', '!', '_', '.', 'U', '><');
$context->flags->set(limitedSigFigs => 1);
}

1;
61 changes: 61 additions & 0 deletions t/contexts/significant_figures_units.t
Original file line number Diff line number Diff line change
Expand Up @@ -42,4 +42,65 @@ subtest 'Test a number with length units and significant figures' => sub {
ok $a == Compute('4.036 ft'), 'Value in feet (a little off, but when converted to m is correct)';
};

subtest 'Test an actual problem' => sub {

my $source = <<~'END_SOURCE';
DOCUMENT();

loadMacros("PGstandard.pl","PGML.pl",'contextSignificantFiguresUnits.pl');

Context('SignificantFiguresUnits')->withUnitsFor('mass');

Context()->flags->set(
tolerance => 0.01,
partial_incorrect_sf => 0.6,
partial_sf_within_tolerance => 0.8,
);

$a = Compute("123.0 g");
$b = Compute("45.3 g");
$c = $a+$b;

BEGIN_PGML
A lab technician has a beaker with [$a] of water. She adds [$b] to the beaker. Using the proper number of significant figures, what is the total amount in the beaker?

[_]{$c}
END_PGML

ENDDOCUMENT();
END_SOURCE

ok my $pg = WeBWorK::PG->new(
r_source => \$source,
inputs_ref => { AnSwEr0001 => '168.3 g' },
processAnswers => 1
),
'source string renders';

is $pg->{result}{score}, 1, 'correct answer is scored correctly';

my $pg2 = WeBWorK::PG->new(
r_source => \$source,
inputs_ref => { AnSwEr0001 => '168.30 g' },
processAnswers => 1
);

is $pg2->{result}{score}, 0.6, 'check deduction for wrong number of significant figures.';
like $pg2->{answers}{AnSwEr0001}{ans_message}, qr/Incorrect number of significant figures/,
'Answer processed showing message.';

my $pg3 = WeBWorK::PG->new(
r_source => \$source,
inputs_ref => { AnSwEr0001 => '168.2 g' },
processAnswers => 1
);

is $pg3->{result}{score}, 0.8,
'check deduction for right number of significant figures, but answer within tolerance.';
like $pg3->{answers}{AnSwEr0001}{ans_message},
qr/Correct number of significant figures, but the value is not correct/,
'Answer processed showing message.';

};

done_testing;
Loading