# Difference between revisions of "MathObject Answers - PGML"

(add remark about using correct answer on left side of == in custom answer checkers) |
|||

(7 intermediate revisions by 4 users not shown) | |||

Line 1: | Line 1: | ||

− | == Answers from |
+ | == Answers from MathObjects == |

− | When you specify an answer following an answer blank and provide a number or a |
+ | When you specify an answer following an answer blank and provide a number or a string containing a formula, PGML turns your answer into a MathObject (essentially by passing it to <code>Compute()</code>). So you can provide any sort of MathObject-based answer by enclosing it in quotation marks. For example, |

Context("Interval"); |
Context("Interval"); |
||

Line 38: | Line 38: | ||

BEGIN_PGML |
BEGIN_PGML |
||

− | A vector perpendicular to [: <[$a],[$b]> :]* is [_____________ |
+ | A vector perpendicular to [: <[$a],[$b]> :]* is [_____________]{$v->cmp(parallel=>true)} |

END_PGML |
END_PGML |
||

Line 49: | Line 49: | ||

BEGIN_PGML |
BEGIN_PGML |
||

− | A vector perpendicular to [: <[$a],[$b]> :]* is [_____________ |
+ | A vector perpendicular to [: <[$a],[$b]> :]* is [_____________]{$cmp} |

END_PGML |
END_PGML |
||

− | This is particularly useful if you want to provide a custom checker. |
+ | This is particularly useful if you want to provide a [[#Custom_Checkers|custom checker]]. |

− | |||

− | Context("Point"); |
||

− | $a = random(2,10,1); |
||

− | $x = random(-5,5,1); |
||

− | $y = $a - $x; |
||

− | |||

− | $cmp = Point($x,$y)->cmp( |
||

− | showCoordinateHints => 0, # doesn't make sense to give hints in this case |
||

− | checker => sub { |
||

− | my ($correct,$student,$ansHash) = @_; # get correct and student MathObjects |
||

− | my ($sx,$sy) = $student->value; # get coordinates of student answer |
||

− | return ($sx + $sy == $a ? 1 : 0); # return 1 if correct, 0 otherwise |
||

− | } |
||

− | ); |
||

− | |||

− | BEGIN_PGML |
||

− | Find a point [:(x,y):] that is a solution to [: x+y = [$a] :]. |
||

− | |||

− | [: (x,y) :] = [______________________]{$cmp} |
||

− | END_TEXT |
||

== Answer Arrays == |
== Answer Arrays == |
||

− | For a Matrix, Vector, or Point object, you may want to ask the student to type each entry in a separate answer blank, rather than entering the whole object in one answer blank (for example, to prevent the use of vector calculations). In the traditional <code>BEGIN_TEXT/END_TEXT</code> setting, you would use its <code> |
+ | For a Matrix, Vector, or Point object, you may want to ask the student to type each entry in a separate answer blank, rather than entering the whole object in one answer blank (for example, to prevent the use of vector calculations). In the traditional <code>BEGIN_TEXT/END_TEXT</code> setting, you would use its <code>ans_array()</code> rather than its <code>ans_rule()</code> method. |

In PGML, you indicate that an answer blank should produce an answer array by putting an asterisk between the blank and the answer. |
In PGML, you indicate that an answer blank should produce an answer array by putting an asterisk between the blank and the answer. |
||

Line 93: | Line 93: | ||

END_PGML |
END_PGML |
||

− | See the [[http://webwork.maa.org/pod/ |
+ | See the [[http://webwork.maa.org/pod/pg/macros/parserMultiAnswer.html documentation for parserMultiAnswer.pl]] for more details about using MultiAnswer objects. |

== Custom Checkers == |
== Custom Checkers == |
||

+ | |||

+ | Since custom checkers for math objects usually consist of more than one line, it is awkward to include them within the PGML block itself. Instead, use a variable to store the answer checker with the custom checker and pass that to PGML. |
||

+ | |||

+ | Context("Point"); |
||

+ | $a = random(2,10,1); |
||

+ | $x = random(-5,5,1); |
||

+ | $y = $a - $x; |
||

+ | |||

+ | $cmp = Point($x,$y)->cmp( |
||

+ | showCoordinateHints => 0, # doesn't make sense to give hints in this case |
||

+ | checker => sub { |
||

+ | my ($correct,$student,$ansHash) = @_; # get correct and student MathObjects |
||

+ | my ($sx,$sy) = $student->value; # get coordinates of student answer |
||

+ | return ($sx + $sy == $a ? 1 : 0); # return 1 if correct, 0 otherwise |
||

+ | } |
||

+ | ); |
||

+ | |||

+ | BEGIN_PGML |
||

+ | Find a point [:(x,y):] that is a solution to [: x+y = [$a] :]. |
||

+ | |||

+ | [: (x,y) :] = [______________________]{$cmp} |
||

+ | END_PGML |
||

+ | |||

+ | '''Note:''' When doing comparisons of functions with "==" you should put the correct answer on the left. See: |
||

+ | * https://webwork.maa.org/wiki/CustomAnswerCheckers |
||

+ | * https://webwork.maa.org/moodle/mod/forum/discuss.php?d=422#p1658 |
||

+ | * https://webwork.maa.org/moodle/mod/forum/discuss.php?d=2309#p4519 |
||

+ | |||

[[Category:PGML]] |
[[Category:PGML]] |

## Latest revision as of 08:00, 6 June 2021

## Contents

## Answers from MathObjects

When you specify an answer following an answer blank and provide a number or a string containing a formula, PGML turns your answer into a MathObject (essentially by passing it to `Compute()`

). So you can provide any sort of MathObject-based answer by enclosing it in quotation marks. For example,

Context("Interval"); BEGIN_PGML The interval from 0 to 1 excluding 0 but including 1 is written: [___________]{"(0,1]"} END_PGML

provides an answer that is an interval. The answer is parsed in the current context, which is the Interval context in this example. This means that you are giving the answer exactly as the student will.

Instead of using quotation marks, you can use a MathObject creator function, like `Real()`

or `Matrix()`

if you prefer.

Context("Complex"); BEGIN_PGML As a complex number, [: sqrt(-1) :] is written [__________]{Complex(0,1)} END_PGML

If the determination of the answer involves computations, however, it may be more convenient to produce a MathObject earlier in the problem and pass that to PGML. You can do that by putting the variable that holds the math object into the braces following the answer blank.

Context("Vector"); $p = Point(0,2), $q = Point(1,-1); $v = Vector($q-$p); BEGIN_PGML A vector from [`[$p]`] to [`[$q]`] is [______________]{$v} END_PGML

## Passing Options to Answer Checkers

If you need to pass options to the answer checker for a MathObject, you can pass the answer checker to PGML rather than the MathObject itself.

Context("Vector"); $a = 3, $b = 5; $v = Vector(-$b,$a); BEGIN_PGML A vector perpendicular to [: <[$a],[$b]> :]* is [_____________]{$v->cmp(parallel=>true)} END_PGML

Alternatively, you can save the answer checker in a variable and pass that to PGML for easier reading.

Context("Vector"); $a = 3, $b = 5; $v = Vector(-$b,$a); $cmp = $v->cmp(parallel=>true); BEGIN_PGML A vector perpendicular to [: <[$a],[$b]> :]* is [_____________]{$cmp} END_PGML

This is particularly useful if you want to provide a custom checker.

## Answer Arrays

For a Matrix, Vector, or Point object, you may want to ask the student to type each entry in a separate answer blank, rather than entering the whole object in one answer blank (for example, to prevent the use of vector calculations). In the traditional `BEGIN_TEXT/END_TEXT`

setting, you would use its `ans_array()`

rather than its `ans_rule()`

method.

In PGML, you indicate that an answer blank should produce an answer array by putting an asterisk between the blank and the answer.

Context("Matrix"); $M = Matrix([1,2],[3,4]); BEGIN_PGML If [`M = [$M]`], then [`M^2 =`] [___]*{$M**2} END_PGML

Here, the size of the answer rule determines the size of each rule in the answer array.

## MultiAnswer Checkers

To use a MultiAnswer object in PGML, create it outside the PGML block, and use the MultiAnswer variable for more than one answer blank.

loadMacros("parserMultiAnswer.pl"); $mp = MultiAnswer(12,6)->with( singleResult => 1, separator => " and ", tex_separator => "\text{ and }", checker => sub { my $correct= shift; my $student = shift; my ($ca,$cb) = @$correct; my ($sa,$sb) = @$student; my $ok = ($ca == $sa && $cb == $sb) || ($ca == $sb && $cb == $sa); return ($ok ? (1,1) : (0,0)); }, ); BEGIN_PGML [_______]{$mp} and [_______]{$mp} END_PGML

See the [documentation for parserMultiAnswer.pl] for more details about using MultiAnswer objects.

## Custom Checkers

Since custom checkers for math objects usually consist of more than one line, it is awkward to include them within the PGML block itself. Instead, use a variable to store the answer checker with the custom checker and pass that to PGML.

Context("Point"); $a = random(2,10,1); $x = random(-5,5,1); $y = $a - $x; $cmp = Point($x,$y)->cmp( showCoordinateHints => 0, # doesn't make sense to give hints in this case checker => sub { my ($correct,$student,$ansHash) = @_; # get correct and student MathObjects my ($sx,$sy) = $student->value; # get coordinates of student answer return ($sx + $sy == $a ? 1 : 0); # return 1 if correct, 0 otherwise } ); BEGIN_PGML Find a point [:(x,y):] that is a solution to [: x+y = [$a] :]. [: (x,y) :] = [______________________]{$cmp} END_PGML

**Note:** When doing comparisons of functions with "==" you should put the correct answer on the left. See: