You can use the MultiPart object to do this, but it is a little awkward. Here is one approach:
DOCUMENT(); # This should be the first executable line in the problem.
loadMacros( "PG.pl", "PGbasicmacros.pl", "PGanswermacros.pl", "PGunion.pl", "Parser.pl", "parserMultiPart.pl", );
TEXT(beginproblem); BEGIN_PROBLEM();
Context("Numeric")->strings->are(True=>{}, False=>{});
$mp = MultiPart(random(0,1,1)? ("True",5,""): ("False","",10))->with( allowBlankAnswers => 1, checkTypes => 0, checker => sub { my ($correct,$student) = @_; my ($tf,$a,$b) = @{$correct}; my ($TF,$A,$B) = @{$student};
return 0 unless $TF->type eq "String" && $TF->value ne ''; $mp->setMessage(3,"When your first answer is 'True' you shouldn't answer this one") if ($TF->value eq 'True' && $B ne ''); $mp->setMessage(2,"When your first answer is 'False' you shouldn't answer this one") if ($TF->value eq 'False' && $A ne '');
return $tf eq $TF && $a == $A && $b == $B; } );
##############################################
BEGIN_TEXT True or false? \{$mp->ans_rule(5)\} $PAR If true, then \(x =\) {$mp->ans_rule(10)\} $PAR If false, then \(y = \) \{$mp->ans_rule(10)\} END_TEXT
##############################################
ANS($mp->cmp);
##############################################
END_PROBLEM(); ENDDOCUMENT(); # This should be the last executable line in the problem.
The MultiPart object has three parts: the TRUE/FALSE question
determines which of the two other values must be filled out. We set the
allowBlankAnswers field so that the student can leave those blank, and we set the checkTypes
field to 0 so that the checker will run even when the student's answers
are of the wrong type (e.g., the empty string when the answer is a
real).
The checker get the student and correct answers and checks to see that
the T/F answer is actually a string (it will have to be one of the
valid strings in that case). It also checks if the student has entered
an answer in the boxes that should be left blank and gives a message if
so.
Then it marks all the answers correct or incorrect depending on whether the student answers match the professor's answers.
Really the only advantage to this over using three separate checkers is
that you can inform the student that the blank problem should be left
blank if it isn't, and that you give credit only when all three are
correct (though you could have done that with the grader anyway). Not
sure if this is really what you were looking for or not.
For a T/F problem like this, it would be nice to be able to use a
pop-up menu rather than a text string, but the Multipart object only
accepts Parser object as its inputs. So I have made a Value object that
is a shell around a pop-up menu so that you can use it in this sort of
situation. In that case, you can leave off the strings from the Context
(since the parser popup menu handles that itself), and replace "True"
and "False" by PopUp(["True","False"],"True") and
PopUp(["True","False"],"False"). You also have to load the
parserPopUp.pl macro file. That makes the modified example:
DOCUMENT(); # This should be the first executable line in the problem.
loadMacros( "PG.pl", "PGbasicmacros.pl", "PGanswermacros.pl", "Parser.pl", "parserMultiPart.pl", "parserPopUp.pl", );
TEXT(beginproblem); BEGIN_PROBLEM();
Context("Numeric");
$mp = MultiPart( random(0,1,1)? (PopUp(["True","False"],"True"),5,""): (PopUp(["True","False"],"False"),"",10) )->with( allowBlankAnswers => 1, checkTypes => 0, checker => sub { my ($correct,$student) = @_; my ($tf,$a,$b) = @{$correct}; my ($TF,$A,$B) = @{$student};
return 0 unless $TF->type eq "String" && $TF->value ne ''; $mp->setMessage(3,"When your first answer is 'True' you shouldn't answer this one") if ($TF->value eq 'True' && $B ne ''); $mp->setMessage(2,"When your first answer is 'False' you shouldn't answer this one") if ($TF->value eq 'False' && $A ne '');
return $tf eq $TF && $a == $A && $b == $B; } );
##############################################
BEGIN_TEXT True or false? \{$mp->ans_rule(5)\} $PAR If true, then \(x =\) \{$mp->ans_rule(10)\} $PAR If false, then \(y = \) \{$mp->ans_rule(10)\} END_TEXT
##############################################
ANS($mp->cmp);
##############################################
END_PROBLEM(); ENDDOCUMENT(); # This should be the last executable line in the problem.
Hope that is what you are looking for.
Davide
<| Post or View Comments |> |