WeBWorK Problems

Display of correct MultiAnswer with student input

Display of correct MultiAnswer with student input

by Steven Fiedler -
Number of replies: 2

I'm having difficulty setting the correct answers in the parserMultiAnswer.pl macro when the input is determined on the fly.  While the grading of these sort of problems is fine, it would be nice to have the correct answers displayed for students after the due date (for example).  

This issue can be shown using the linked code as an example, which I've also listed below. The attached screenshot reveals that the "correct" answers are the dummy zero values which were given when MultiAnswer function is initialized.

DOCUMENT();

loadMacros('PGstandard.pl', 'PGML.pl', 'parserMultiAnswer.pl', 'PGcourse.pl');

$ma = MultiAnswer(0, 0, 0, 0, 0)->with(
    checker => sub {
        my ($correct, $student, $self, $ansHash) = @_;
        my $mass        = $student->[0];
        my $h2o_cyl     = $student->[1];
        my $h2o_bar_cyl = $student->[2];
        my $vol         = $student->[3];

        my $den     = $mass / $vol;
        my $bar_vol = $h2o_bar_cyl - $h2o_cyl;

        return (
            1, 1, 1,
            $bar_vol == $vol      ? 1 : 0,
            $den == $student->[4] ? 1 : 0
        );
    }
);

BEGIN_PGML
*_Determining the Density of a Solid Metal Bar_*

A. Mass of your metal bar: [_]{$ma}{10} g.

B. Initial volume of water in the graduated cylinder: [_]{$ma}{10} mL.

C. Volume of water and metal bar in the graduated cylinder: [_]{$ma}{10} mL.

D. Calculate the volume of your metal bar: [_]{$ma}{10} mL.

E. Calculate the density of your metal bar: [_]{$ma}{10} g/mL.
END_PGML

ENDDOCUMENT();
Attachment Screenshot_2025-10-12_19-41-01.png
In reply to Steven Fiedler

Display of correct MultiAnswer with student input

by Glenn Rice -

First, I would recommend not giving zeros for the correct answers.  Give an actual correct answers for the problem.  Choose answers for the first three questions, and the compute the other two answers based on those.  Then give those to the MultiAnswer constructor.  Then those answers will be shown for the correct answers if the student does not answer all parts.  The answers will not match the student's answers, but they will represent correct answers for the problem.  You can't do much better unless all parts are answered.

Then add a post filter to the last answer part of the MultiAnswer (the MultiAnswer really does its checking of all parts in the last answer part).  The post filter can then set the correct answers for all parts based on the students answers for the first three parts.

Here is code that does all of that.

DOCUMENT();

loadMacros('PGstandard.pl', 'PGML.pl', 'parserMultiAnswer.pl', 'PGcourse.pl');

$ma = MultiAnswer(6, 10, 15, 5, 1.2)->with(
    checker => sub {
        my ($correct, $student, $self, $ansHash) = @_;
        return (
            $student->[0] > 0                              ? 1 : 0,
            $student->[1] > 0                              ? 1 : 0,
            $student->[2] > $student->[1]                  ? 1 : 0,
            $student->[2] == $student->[1] + $student->[3] ? 1 : 0,
            $student->[0] == $student->[4] * $student->[3] ? 1 : 0
        );
    }
);

@ma_cmp = $ma->cmp;
$ma_cmp[-1]->withPostFilter(sub {
    my $ans = shift;
    return $ans
        unless defined $ma->{ans}[0]{student_value}
        && $ma->{ans}[0]{student_value} > 0
        && defined $ma->{ans}[1]{student_value}
        && $ma->{ans}[1]{student_value} > 0
        && defined $ma->{ans}[2]{student_value}
        && $ma->{ans}[2]{student_value} > $ma->{ans}[1]{student_value};
    my $barVolume =
        $ma->{ans}[2]{student_value} - $ma->{ans}[1]{student_value};
    my $barDensity = $ma->{ans}[0]{student_value} / $barVolume;
    $ma->{ans}[0]{correct_ans} = $ma->{ans}[0]{student_value}->string;
    $ma->{ans}[0]{correct_ans_latex_string} =
        $ma->{ans}[0]{student_value}->TeX;
    $ma->{ans}[1]{correct_ans} = $ma->{ans}[1]{student_value}->string;
    $ma->{ans}[1]{correct_ans_latex_string} =
        $ma->{ans}[1]{student_value}->TeX;
    $ma->{ans}[2]{correct_ans} = $ma->{ans}[2]{student_value}->string;
    $ma->{ans}[2]{correct_ans_latex_string} =
        $ma->{ans}[2]{student_value}->TeX;
    $ma->{ans}[3]{correct_ans}              = $barVolume->string;
    $ma->{ans}[4]{correct_ans}              = $barDensity->string;
    $ma->{ans}[3]{correct_ans_latex_string} = $barVolume->TeX;
    $ma->{ans}[4]{correct_ans_latex_string} = $barDensity->TeX;
    return $ans;
});

BEGIN_PGML
*_Determining the Density of a Solid Metal Bar_*

A. Mass of your metal bar: [_]{ width => 10 } g.

B. Initial volume of water in the graduated cylinder: [_]{ width => 10 } mL.

C. Volume of water and metal bar in the graduated cylinder: [_]{ width => 10 } mL.

D. Calculate the volume of your metal bar: [_]{ width => 10 } mL.

E. Calculate the density of your metal bar: [_]{ width => 10 } g/mL.
END_PGML

ANS(@ma_cmp);

ENDDOCUMENT();
In reply to Glenn Rice

Display of correct MultiAnswer with student input

by Steven Fiedler -

Thank you Glenn. 

I was amused by your (reasonable) assertion that

$student->[2] > $student->[1]                  ? 1 : 0,

in the MultiAnswer body. The mass of the graduated cylinder + water + metal bar should be greater than the mass of just the graduated cylinder + water. However, I had a few students last week with data that indicated otherwise. Frustratingly, they were not particularly troubled by it.