A method to match explanations with a shuffled list of matching problems is presented in
http://webwork.maa.org/wiki/MatchingProblems
The method involves creating a list of explanations whose order matches the object->qa list, then looping through the shuffled list of asked questions to arrange the explanations in matching order, followed by explicit lines to present those explanations in the problem's Solution block.
That method also works with a shuffled list of True/False items as presented in
http://webwork.maa.org/wiki/ManyMultipleChoice1
I request some additions to PGchoicemacros.pl for handling a list of triples: Question, Answer, Explanation. The new functionality would remove the need for looping to match explanations with asked questions and would provide a single command for display of all explanations in Solutions. Maintenance and revision of a single QAE list is apt to be easier than managing a pair of QA and E lists.
Some of my WeBWorK assignments are Reading Question assignments, close an hour before a class with answers & solutions available after class, which I use for Just-in-Time info to help me adjust my agenda for a class (encouraging students to read the text before class is also important). I plan to adapt some ConcepTest and Check-Your-Understanding items to use in my RQ assignments. I am a strong believer in providing explanations or solutions in all problems I write, so my request is for tools to simplify writing a batch of problems with each problem presenting several (e.g., 5 chosen from 8) True/False items.
The looping is already completely unnecessary, as the indices of the selected questions are already available in a field of the match object, in this case
Using an array
$ml->{slice}
. See the POD documentation for ChoiceList (the root class for the match list) for a list of the data available.Using an array
@explanations
of explanations and this slice data, you can get the explanation corresponding to the i-th question as $explanations[$ml->{slice}[$i]]
.
Thanks, Davide --- that is great information.
After a standard setup, it seems sufficient to create an @explain array followed by concatenating appropriate pieces for display in the Solution block. Here's my first draft of such code.
$n = 0 ;
$why = '' ;
foreach $i ( @{$tf->slice} ) {
$n++ ;
$why .= "$BR $n. "
. "$tf->{answers}[$i], " . $SPACE
. "$explain[$i]" . "$BR"
} ;
Context() -> texStrings;
BEGIN_SOLUTION
$SOLUTION
$why
END_SOLUTION
Context() -> normalStrings;
After a standard setup, it seems sufficient to create an @explain array followed by concatenating appropriate pieces for display in the Solution block. Here's my first draft of such code.
$n = 0 ;
$why = '' ;
foreach $i ( @{$tf->slice} ) {
$n++ ;
$why .= "$BR $n. "
. "$tf->{answers}[$i], " . $SPACE
. "$explain[$i]" . "$BR"
} ;
Context() -> texStrings;
BEGIN_SOLUTION
$SOLUTION
$why
END_SOLUTION
Context() -> normalStrings;
Your code looks good, except I think you need
One simplification is that you don't need
$tf->{slice}
not $tf->slice
(though I guess there may be a method as well; I didn't check).One simplification is that you don't need
Context()->texStrings
or Context()->normalStrings
, as these only affect the substitution of MathObjects into the text. You aren't doing that, so they have no effect, here.
The attached example incorporates Davide's remark that MathObjects stuff is apt to be superfluous for forced-choice (multiple-choice, match, select) tasks.
The POD Documentation for ChoiceList concludes by saying "cmp
Usage ANS($ml -> cmp);
provides a MathObject like comparison method
returns a string of comparison methods for checking the list object"
If I replace
ANS( str_cmp( $tf -> ra_correct_ans ) ) ;
with
ANS( $tf -> cmp() ) ;
the error message is
Variable 'F' is not defined in this context; see position 1 of formula at line 358 of [PG]/lib/ChoiceList.pm
Died within ChoiceList::cmp called at line 37 of (eval 91702)
I'm content to stay with an old-style checker that works, but don't want to overlook possible improvements.
The POD Documentation for ChoiceList concludes by saying "cmp
Usage ANS($ml -> cmp);
provides a MathObject like comparison method
returns a string of comparison methods for checking the list object"
If I replace
ANS( str_cmp( $tf -> ra_correct_ans ) ) ;
with
ANS( $tf -> cmp() ) ;
the error message is
Variable 'F' is not defined in this context; see position 1 of formula at line 358 of [PG]/lib/ChoiceList.pm
Died within ChoiceList::cmp called at line 37 of (eval 91702)
I'm content to stay with an old-style checker that works, but don't want to overlook possible improvements.
Although this works with a select list, it fails with a match list.
My bugzilla report includes an attachment showing slice gets its indices from choose_extra rather than choose.
My bugzilla report includes an attachment showing slice gets its indices from choose_extra rather than choose.
The solution here might be to capture the slice after your
$ml->choose
and before the $ml->choose_extra
. For example
$ml->choose(2) ; @slice = @{$ml->slice}; ... foreach $i ( @slice ) { $n++ ; $why .= "$BR $n. " . "$explain[$i]" . "$BR" } ;(it turns out the
$ml->slice
is OK for this).
Alternatively,
$ml->choose(2) ; $ml->{original_slice} = [@{$ml->slice}]; ... foreach $i ( @{$ml->{original_slice}} ) { $n++ ; $why .= "$BR $n. " . "$explain[$i]" . "$BR" } ;See if either of those does what you want.
Davide
I opted for a mild variant of the first.
$ml->choose(2);
is immediately followed by
#### assemble the explanation while slice has indices from choose()
#### [choose_extra() will subsequently put its indices into slice]
$n = 0 ;
$why = '' ;
foreach my $i ( @{$ml->{slice}} ) {
$n++ ;
$why .= "$BR $n. $explain[$i] $BR"
} ;
Once again --- thanks, Davide, for your help.
$ml->choose(2);
is immediately followed by
#### assemble the explanation while slice has indices from choose()
#### [choose_extra() will subsequently put its indices into slice]
$n = 0 ;
$why = '' ;
foreach my $i ( @{$ml->{slice}} ) {
$n++ ;
$why .= "$BR $n. $explain[$i] $BR"
} ;
Once again --- thanks, Davide, for your help.
Sure, that works well, too, and doesn't need to save any extra data. Good solution.