Forums

Search results: 135

Davide,
I decided that I would try first to get the restricted version to work. It is my
impression that I wrote the context as you suggested, but my proofreading is so
dreadful that I can't guarantee that. In any event, in the file contextLeadingZero.pl
is now stored:

[root@homework macros]# more contextLeadingZero.pl
################################################################################

=head1 NAME

contextLeadingZero.pl - implements contextLimitedNumeric with the additional
feature that decimals need integer before decimal pt

=head1 DESCRIPTION

=cut


loadMacros("contextLimitedNumeric.pl");

$context{LeadingZero} = Parser::Context->getCopy("contextLimitedNumeric");
$context{LeadingZero}=>flags->set(
NumberCheck => sub {
my $self = shift;
$self->Error("Decimals must have a number before the decimal point")
if $self->{value_string} =~ m/^\./;
}
);
I embedded this in the problem as shown below (with error message preceding
file listing.

set1: Problem 3

This set is visible to students.

WeBWorK Error

WeBWorK has encountered a software error while attempting to process this problem. It is likely that there is an error in the problem itself. If you are a student, report this error message to your professor to have it corrected. If you are a professor, please consult the error output below for more information.

Error messages

Error detected while loading [PG]/macros/contextLeadingZero.pl: Can't locate object method "set" via package "flags" (perhaps you forgot to load "flags"?) at line 24 of [PG]/macros/contextLeadingZero.pl, chunk 1 Died within main::compile_file called at line 308 of (eval 1122) from within main::loadMacros called at line 6 of [TMPL]/msprobs/mn+o5-1inter13b.pg

Error details

 Problem3
ERROR caught by Translator while processing problem file:msprobs/mn+o5-1inter13b.pg
****************
Error detected while loading [PG]/macros/contextLeadingZero.pl:
Can't locate object method "set" via package "flags" (perhaps you forgot to load "flags"?) at line 24 of [PG]/macros/contextLeadingZero.pl,  chunk 1
 Died within main::compile_file called at line 308 of (eval 1122)
 from within main::loadMacros called at line 6 of [TMPL]/msprobs/mn+o5-1inter13b.pg

****************

------Input Read
1 #DESCRIPTION
2 ##Type of
3 #ENDDESCRIPTION
4
5 DOCUMENT();
6 loadMacros(
7 "PGstandard.pl",
8 "PGchoicemacros.pl",
9 "PGgraphmacros.pl",
10 "MathObjects.pl",
11 "compoundProblem.pl",
12 "contextCurrency.pl",
13 "unionLists.pl",
14 "unionMacros.pl",
15 "contextLimitedNumeric.pl",
16 "contextLeadingZero.pl",
17 );
18 Context()->texStrings;
19 TEXT(beginproblem());
20 $showPartialCorrectAnswers = 1;
21 $a=random(61,69,1);
22 $b=random(31,39,1);
23 $c=random(1,9,1);
24 $ans1= $a/100;
25 $ans2=$b/100;
26 $ans3=$c/100;
27 $ans4=.19;
28 $ans5=.78;
29 Context()->texStrings;
30 BEGIN_TEXT
31 $PAR
32 Write each as a decimal
33 $PAR
34 \( \frac{$a}{100}=\) \{ans_rule(3)\}
35 $PAR
36 \( \frac{$b}{100}= \) \{ans_rule(3)\}
37 $PAR
38 \( \frac{$c}{100}= \) \{ans_rule(2)\}
39 $PAR
40 nineteen hundredths =\{ans_rule(3)\}
41 $PAR
42 seventy-eight hundredths =\{ans_rule(3)\}
43
44 END_TEXT
45 Context("LeadingZero");
46 #note, this should be modified for .xxx
47 &ANS(Real($ans1)->cmp);
48 &ANS(Real($ans2)->cmp);
49 &ANS(Real($ans3)->cmp);
50 &ANS(Real($ans4)->cmp);
51 &ANS(Real($ans5)->cmp);
52
53 ENDDOCUMENT()
Was I supposed to do something about the flags other than what was in the
new context?

Ken,

PS I spent two days at the beach finally reading "Programming Perl" in
more detail (It is amazing how much one can get away with using ordinary
webwork problems with a limited knowledge of Perl) But this one still
eludes me.
Davide,
For some stupid reason my mouse copy would not work on this material
so, after what I thought was careful copying and then two hours of bug checking
on that "careful copying" I got things to compile into the problem. Here is
the code (note the error below the code before reading the code).

DOCUMENT();
loadMacros(
"PGstandard.pl",
"PGchoicemacros.pl",
"PGgraphmacros.pl",
"MathObjects.pl",
"compoundProblem.pl",
"unionLists.pl",
"unionMacros.pl",
"contextInequalities.pl"
);
TEXT(beginproblem());
$showPartialCorrectAnswers = 1;
# A custom checker that compares a student formula to the correct
# formula for identical structure. Both must be two numberes
# separated by an operator.
#
$LimitedOperation = sub {
my($correct,$student,$ans) = @_;
my $f = $ans->{student_formula}{tree};
return 0 if $ans->{message} || $ans->{isPreview} ||
!defined($f);
#
# Check that the form is correct
#
Value->Error("Your answer should be two numbers with
either a +, -, *, or / between them")
unless $f->class eq 'BOP' && isNumber($f->{lop}) &&
isNumber($f->{rop});
#
# Get the student's operands
#
my($a,$b)=($f->{lop}->eval, $f->{rop}->eval);
# Get the correct answer's formula and operands.
#
#my $F = Parser::Formula($ans->{correct_ans})->{tree};
my ($A,$B) =($F->{lop}->eval, $F->{rop}->eval);
#
#Check that the answers are equal, that the operators are
# are the same and that the operands are the same.
#
return $correct == $student &&
$f->{bop} eq $F->{bop} &&
(($A == $a && $B == $b) || ($A == $b && $B == $a));
};
#
# Check if a node is a Number or a negative Number
# (with no operations involved)
#
sub isNumber{
my $n = shift;
return $n->class eq 'Number' ||
($n->class eq 'UOP' && $n->{uop} eq 'u-' &&
$n->{op}->class eq 'Number');
}



Context("Numeric");
$b=random( 4,8,2);
$a=$b*random(3,7,2);
$c=random(20,50,5);
$d1= random(3,7,1);
$a1= random(2,5,1);
$c1=random(4,9,1);
$b1=$c1+$d1*random(3,6,1);
$ans1=Real($a/$b+$c);
$ans2=Compute($a1*($b1-$c1)/$d1);
@vars=('x','y','z');
@nums=('zero ','one ','two ','three ', 'four ', 'five ', 'six ',
'seven ', 'eight ', 'nine ');
@ops=('multiplied by ','divided by ', ' added to ', 'subtracted from ');

$a3=random(6,9,1);
$b3=random(2,5,1);$c3=
random(0,3,1);

if($c3==0){$ans3=Compute("$a3*$b3");}
elsif ($c3==2){$ans3=Compute("$a3+$b3");}
elsif ($c3==3){$ans3=Compute("$a3-$b3");}
else
{Context("LimitedNumeric-StrictFraction");
$ans3=Compute("$a3/$b3");Context("Numeric");}

$a4=random(6,9,1);
$b4=random(2,5,1);
$c4=random(0,3,1);


if($c4==0) {$ans4=Compute("$a4*$b4");}
elsif ($c4==2){$ans4=Compute("$a4+$b4");}
elsif ($c4==3){$ans4=Compute("$a4-$b4");}
else
{Context("LimitedNumeric-StrictFraction");
$ans4=Compute("$a4/$b4");Context("Numeric");}

$m=random(6,10,2);
$n=random(4,8,2);
$p=random(2,5,1);
$nn=random(2,5,1);
$ans5=Real($m+$nn*$n);
$q=random(2,5,1);
$ans6=Compute($m*$n/$q);
$uu=random(5,9,1);
$uuu=random(0,2,1);
$uuuu="$vars[$uuu]";
Context("Inequalities");
$ans7= Compute("$uu<$uuuu");

Context()->texStrings;
BEGIN_TEXT
$PAR
Find the value of each expression

$PAR
\($a\div $b+$c=\) \{ans_rule(4)\}.

$PAR
\($a1( $b1-$c1)\div $d1=\) \{ans_rule(4)\}.
$PAR
Write a numerical expression for each verbal phrase.
$PAR
$nums[$a3] $ops[$c3] $nums[$b3] \{ans_rule(10)\}
$PAR
$nums[$a4] $ops[$c4] $nums[$b4] \{ans_rule(10)\}
$PAR
Evaluate each expression if n=$n, m=$m, p=$p.
$PAR
m+$nn n=\{ans_rule(4)\}.

$PAR
\(\frac{mn}{$q}=\)\{ans_rule(4)\}.

$PAR
Write \( \underline{$nums[$uu]\ less\ than\ $vars[$uuu]}\)
as an algebraic expression: \{ans_rule(7)\}.




END_TEXT

ANS($ans1->cmp);
ANS($ans2->cmp);
ANS($ans3->cmp(checker=>$LimitedOperation));
ANS($ans4->cmp(checker=>$LimitedOperation));
ANS($ans5->cmp);
ANS($ans6->cmp);
ANS($ans7->cmp);


ENDDOCUMENT()

You may notice that I changed nothing but the error message - I thought
that yours was a bit sophisticated for seventh graders. Then I tried some
false and correct answers. It correctly rejected some false answers with
the proper message, but the following puzzles me.


Entered Answer Preview Correct Result Messages
53 incorrect
15 incorrect
32 8\cdot 4 8*4 incorrect An error occurred while checking your answer:
Can't call method "eval" on an undefined value at line 41 of [TMPL]/patsheets/ch1test.pg
28 7\cdot 4 7+4 incorrect An error occurred while checking your answer:
Can't call method "eval" on an undefined value at line 41 of [TMPL]/patsheets/ch1test.pg
18 incorrect
Notice that entered and preview disagree on problems 3 and 4. Also answer
3 should be incorrect and answer 4 should be incorrect (wrong operator)
Ken


Davide,
I may have read too much into your response and tried to apply it too
broadly. Here is the current complete code. As you may note, I leave
LimitedNumeric-Strict Fraction because the next line originally drew an error
concerning the + sign. But WeBWorK is unhappy with my try at remedying the
problem.

4
5 DOCUMENT();
6 loadMacros(
7 "PGstandard.pl",
8 "PGchoicemacros.pl",
9 "PGgraphmacros.pl",
10 "MathObjects.pl",
11 "compoundProblem.pl",
12 "unionLists.pl",
13 "unionMacros.pl",
14 "contextInequalities.pl"
15 );
16 TEXT(beginproblem());
17 $showPartialCorrectAnswers = 1;
18 Context("Numeric");
19 $b=random( 4,8,2);
20 $a=$b*random(3,7,2);
21 $c=random(20,50,5);
22 $d1= random(3,7,1);
23 $a1= random(2,5,1);
24 $c1=random(4,9,1);
25 $b1=$c1+$d1*random(3,6,1);
26 $ans1=$a/$b+$c;
27 $ans2=$a1*($b1-$c1)/$d1;
28 @vars=('x','y','z');
29 @nums=('zero ','one ','two ','three ', 'four ', 'five ', 'six ',
30 'seven ', 'eight ', 'nine ');
31 @ops=('multiplied by ','divided by ', ' added to ', 'subtracted from ');
32
33 $a3=random(6,9,1);
34 $b3=random(2,5,1);
35 $c3=random(1,3,1);
36 Context("LimitedNumeric-StrictFraction");
37 if($c3==1){$ans3=Compute("$a3/$b3");}
38 Context("LimitedNumeric");
39 elsif ($c3==2){$ans3=Compute("$a3+$b3");}
40 elsif ($c3==3){$ans3=Compute("$a3-$b3");}
41 else {$ans3=Compute("$a3*$b3");}
42 $a4=random(6,9,1);
43 $b4=random(2,5,1);
44 $c4=random(1,3,1);
45
46 Context("LimitedNumeric-StrictFraction");
47 if($c4==1){$ans4=Compute("$a4/$b4");}
48 Context("LimitedNumeric");
49 elsif ($c4==2){$ans4=Compute("$a4+$b4");}
50 elsif ($c4==3){$ans4=Compute("$a4-$b4");}
51 else {$ans4=Compute("$a4*$b4");}
52 $m=random(6,10,2);
53 $n=random(4,8,2);
54 $p=random(2,5,1);
55 $nn=random(2,5,1);
56 $ans5=$m+$nn*$n;
57 $q=random(2,5,1);
58 $ans6=$m*$n/$q;
59 $uu=random(5,9,1);
60 $uuu=random(0,2,1);
61 $uuuu="$vars[$uuu]";
62 Context("Inequalities");
63 $ans7= Compute("$uu<$uuuu");
64
65 Context()->texStrings;
66 BEGIN_TEXT
67 $PAR
68 Find the value of each expression
69
70 $PAR
71 \($a\div $b+$c=\) \{ans_rule(4)\}.
72
73 $PAR
74 \($a1( $b1-$c1)\div $d1=\) \{ans_rule(4)\}.
75 $PAR
76 Write a numerical expression for each verbal phrase.
77 $PAR
78 $nums[$a3] $ops[$c3] $nums[$b3] \{ans_rule(10)\}
79 $PAR
80 $nums[$a4] $ops[$c4] $nums[$b4] \{ans_rule(10)\}
81 $PAR
82 Evaluate each expression if n=$n, m=$m, p=$p.
83 $PAR
84 m+$nn n=\{ans_rule(4)\}.
85
86 $PAR
87 \(\frac{mn}{$q}=\)\{ans_rule(4)\}.
88
89 $PAR
90 Write \( \underline{$nums[$uu]\ less\ than\ $vars[$uuu]}\)
91 as an algebraic expression: \{ans_rule(7)\}.
92
93
94
95
96 END_TEXT
97
98 ANS($ans1->cmp);
99 ANS($ans2->cmp);
100 ANS($ans3->cmp);
101 ANS($ans4->cmp);
102 ANS($ans5->cmp);
103 ANS($ans6->cmp);
104 ANS($ans7->cmp);
105
106
107 ENDDOCUMENT()


Ken


Difficulty 1 is that I do not know how to reset the problem. I am getting around this temporarily by creating a student named
tester who is working the problem for the first time.

This is a known problem of the current implementation. For the professor you can fix it by changing these lines in the
question:

##############################################
$isProfessor = ($studentLogin eq 'dpvc' || $studentLogin eq 'professor');
#
# Start a compound problem. See the compoundProblem.pl
# file for more details about the parameters you
# can supply.
#
$cp = new compoundProblem(
 parts => 3, # the total number of parts in this problem
 totalAnswers => 4, # total answers in all parts combined
 parserValues => 1, # make parser objects from student answers
 allowReset => $isProfessor, # professors get Reset button for testing
);

Changing
allowReset => 1 

will give everyone a reset button -- this might be the best compromise for now. Further work needs to be done to determine exactly how one wants a sequential problem to behave.

Should the student be able to see earlier work? to change it? What is the desired behavior?

You can also change the line above:

isProfessor = ($studentLogin eq 'dpvc' || $studentLogin eq 'professor');

to contain your login instead of Davide's.

This won't be perfect, but the code below gives you a framework for
writing sequentialProblems. You will need to do to obtain file
 "compoundProblem.pl",

which Davide Cervone wrote last August. You can download this
and related files from the link on http://webwork.maa.org/wiki/SequentialProblems

Or you can type
cvs update
in the pg/macros directory


Reading the top of that file will give you instructions
on modifications that are possible with this
version of sequential problems.

One of the "features" is that once you have completed one
section of the problem you can't return to the earlier sections.
We'd like to modify that behavior but it may not happen right away.

##DESCRIPTION
## Algebra problem: true or false for inequality
##ENDDESCRIPTION

##KEYWORDS('algebra', 'inequality', 'fraction')

## DBsubject('Algebra')
## DBchapter('Fundamentals')
## DBsection('Real Numbers')
## Date('6/3/2002')
## Author('')
## Institution('')
## TitleText1('Precalculus')
## EditionText1('3')
## AuthorText1('Stewart, Redlin, Watson')
## Section1('1.1')
## Problem1('22')

########################################################################

DOCUMENT();

loadMacros(
 "PGstandard.pl", # Standard macros for PG language
 "MathObjects.pl",
 "compoundProblem.pl",
 "unionLists.pl",
 #"source.pl", # allows code to be displayed on certain sites.
 #"PGcourse.pl", # Customization file for the course
);

# Print problem number and point value (weight) for the problem
TEXT(beginproblem());

# Show which answers are correct and which ones are incorrect
$showPartialCorrectAnswers = 1;

##############################################

$isProfessor = ($studentLogin eq 'dpvc' || $studentLogin eq 'professor');

#
# Start a compound problem. See the compoundProblem.pl
# file for more details about the parameters you
# can supply.
#
$cp = new compoundProblem(
 parts => 3, # the total number of parts in this problem
 totalAnswers => 4, # total answers in all parts combined
 parserValues => 1, # make parser objects from student answers
 allowReset => $isProfessor, # professors get Reset button for testing
);
$part = $cp->part; # look up the current part

##############################################
#
# Part 1
#

if ($part == 1) {

##############################################
##############################################################
#
# Setup
#
#
Context("Numeric");
Context()->flags->set(reduceConstants=>0);

$ans[2] = Formula("2*13");
$ans[3] = Formula("3*13");
$ans[4] = Formula("4*13");
$ans[5] = Formula("5*13");
$ans[6] = Formula("6*13");
$ans[7] = Formula("7*13");
$ans[8] = Formula("8*13");
$ans[9] = Formula("9*13");
$ans[10] = Formula("52");
$ans[11] = Formula("4");

##############################################################
#
# Text
#
#

Context()->texStrings;
BEGIN_TEXT
$PAR
 Long division may look complicated because a number of ideas are combined to
make the work efficient. We will start by doing extra steps so that it will
be easier to see what is happening.
$PAR
We will divide the number 6257 by 13. Remember that our answer
will be a quotient and a remainder. The quotient will be the largest
number of 13's in 6257. The remainder will be what remains after
subtracting as many 13's as we can from 6257.
$PAR
Help List
\{ BeginList("OL")\}
END_TEXT


 foreach $j (2..11) {
 TEXT(EV3(q! $ITEM \\( $ans[$j] = \\) \\{ ans_rule(20)\\} ! ));
 }

BEGIN_TEXT

\{ EndList("OL") \}
$PAR
Now that we have our help list, we look at the number 6257.
The first two digits are 62 and it has 2 more digits.
So we find number in our help list
that is the largest number that is not more than 62.
That number is
\{ans_rule(2)\} which
is
\{ans_rule(1)\}\(\times 13\). Since there are 2 digits to t
he right of 62 in the number 6257 this means
that
\{ans_rule(2)\}\(00\) which is
\{ans_rule(2)\}\(00\times 13\) is
the largest multiple of 13 that ends with 00.




END_TEXT
Context()->normalStrings;

# $BR $BR \{NAMED_ANS_RULE('first_answer',10) \}
##############################################################
#
# Answers
#
#
Context("LimitedNumeric");
foreach $j (2..11) {
 # convert to an object that requires an integer answer
 ANS(Real($ans[$j])->cmp);
}
ANS(Real(52)->cmp,Real(4)->cmp,Real(4)->cmp,Real(52)->cmp);

} # End of Part 1

##############################################
#
# Part 2
#

if ($part == 2) {

$a = 3;
$b = 4;
BEGIN_TEXT
Part 2:
$PAR
\($a + $b\) = \{ans_rule(10)\}
END_TEXT
$c = $a+$b;
ANS(num_cmp($c,mode=>"strict"));

}

##############################################
#
# Part 3
#

if ($part == 3) {

$f = Formula("$a x + $b")->reduce;

BEGIN_TEXT
Part: 3:
$PAR
Suppose \(f(x) = \{$f->TeX\}\).$BR
Then \(f(2)\) = \{ans_rule(10)\}.
END_TEXT

ANS($f->eval(x=>2)->cmp);

}

##############################################
ENDDOCUMENT();

WeBWorK Problems -> writing sequential problems

by Michael Gage -
Hi Ken,
 I'm moving this question to the forum since there is a lot of interest
in writing sequential problems
(or compound problems or multipart problems -- we don't have a firm
naming convention yet).
It is posted at
http://wwrk.maa.org/moodle/mod/forum/discuss.php?d=349
You can set your preferences for this forum so that you are emailed whenever it is updated by going to http://wwrk.maa.org/moodle/mod/forum/view.php?f=3
and then choosing "subscribe to this forum".particular Karen Clark at TCNJ (who leads the AIM-WeBWorK work group on
sequential problems)and Davide Cervone have made contributions. I think the timing
is write and several people are interested in exploring the best way(s)
to construct these problems.
 As a starting point view the wiki document at 
 http://webwork.maa.org/wiki/SequentialProblems
--Mike
 
 On Jun 19, 2008, at 10:03 AM, Kenneth Appel wrote:
 Mike,
 I am trying to make what I used to call a sequential problem. In this
case, I want 11 answers before I check to see if the
last is correct before going on. I get a type of error that I do not
understand. There seem to be several possibility.
 perhaps A change in WeBWorK in the last few years means I should have
done something differently now than then.
-- there have been a number of changes and I expect that we can do
better than our original approaches to 
writing sequential problems.
 Here it is
Ken
 
set6: Problem 1
 This set is visible to students.
 Error messages
Not a CODE reference at line 76 of [TMPL]/msprobs6/ldintro.pg
Error details
 Problem1
ERROR caught by Translator while processing problem
file:msprobs6/ldintro.pg
****************
Not a CODE reference at line 76 of [TMPL]/msprobs6/ldintro.pg
****************
 ------Input Read
1 #DESCRIPTION
2 #ENDDESCRIPTION
3 
4 DOCUMENT();
5 loadMacros(
6 &quot;PG.pl&quot;,
7 &quot;PGbasicmacros.pl&quot;,
8 &quot;PGchoicemacros.pl&quot;,
9 &quot;PGanswermacros.pl&quot;,
10 &quot;PGgraphmacros.pl&quot;,
11 &quot;PGauxiliaryFunctions.pl&quot;,
12 );
13 TEXT(&amp;beginproblem());
14 $showPartialCorrectAnswers = 1;
15 $ans2=2*13; 
16 $ans3=3*13; 
17 $ans4=4*13; 
18 $ans5=5*13; 
19 $ans6=6*13;
20 $ans7=7*13; 
21 $ans8=8*13; 
22 $ans9=9*13;
23 $ans10=52;
24 $ans11=4;
25 BEGIN_TEXT
26 $PAR
27 Long division may look complicated because a number of ideas are
combined to
28 make the work efficient. We will start by doing extra steps so that
it will
29 be easier to see what is happening.
30 $PAR
31 We will divide the number 6257 by 13. Remember that our answer will
be a quotient and a remainder. The quotient will be the largest number
of 13's in 6257. The remainder will be what remains after subtracting as
many 13's as we can from 6257.
32 $PAR
33 What we do is to find our quotient one digit at a time. This time we
will make a
34 \(help\ list\) but after a bit of practice you will probably decide
that you don't need one. Our help list will consist of the multiples of
13 up to \(9\times 13\)
35 $PAR
36 Help List
37 $BR
38 \(2\times 13=\)\{ans_rule(2)\}
39 $BR
40 \(3\times 13=\)\{ans_rule(2)\}
41 $BR
42 \(4\times 13=\)\{ans_rule(2)\}
43 $BR
44 \(5\times 13=\)\{ans_rule(2)\}
45 $BR
46 \(6\times 13=\)\{ans_rule(2)\}
47 $BR
48 \(7\times 13=\)\{ans_rule(2)\}
49 $BR
50 \(8\times 13=\)\{ans_rule(2)\}
51 $BR
52 \(9\times 13=\)\{ans_rule(2)\}
53 $PAR
54 Now that we have our help list, we look at the number 6257. The first
two digits are 62 and it has 2 more digits. So we find number in our
help list
 55 that is the largest number that is not more than 62. That number is
\\{ans_rule(2)\} which is \{ans_rule(1)\}\(\times 13\). Since there are
2 digits to the right of 62 in the number 6257 this means that
\{ans_rule(2)\}\(00\) which is \{ans_rule(2)\}\(00\times 13\) is the
largest multiple of 13 that ends with 00. 
 56 
57 
58 
59 $BR $BR \{NAMED_ANS_RULE('first_answer',10) \} 
60 END_TEXT
61 &amp;ANS(str_cmp($ans2));
62 &amp;ANS(str_cmp($ans3));
63 &amp;ANS(str_cmp($ans4));
64 &amp;ANS(str_cmp($ans5));
 65 &amp;ANS(str_cmp($ans6));
66 &amp;ANS(str_cmp($ans7));
67 &amp;ANS(str_cmp($ans8));
68 &amp;ANS(str_cmp($ans9));
69 
70 &amp;ANS(str_cmp($ans10));
71 
72 $ans_eval1 = str_cmp($ans11);
73 NAMED_ANS(first_answer =&gt; $ans_eval1);
 74 $first_Answer = $inputs_ref-&gt;{first_answer}; 
75 
76 $rh_ans_hash1 = &amp;$ans_eval1($first_Answer);
77 #because it is text it is handled differently
78 
79 # Using named answers allows for more control. Any unique label can
be 
 80 # used for an answer. 
81 # (see
http://cartan.math.rochester.edu/WeBWorKdiscussion/discuss/msgReader$13 
82 # for more details on answer evaluator formats and on naming answers
83 # so that you can refer to them later. Look also at the pod
documentation in 
 84 # PG.pl and PGbasicmacros.pl which you can also reach at 
85 #
http://webwork.math.rochester.edu/docs/techdescription/pglanguage/index.
html)
86 
87 # Check to see that the first answer was answered correctly. If it
was then we
 88 # will ask further questions. 
89 # We need to know what the answer was named.
90 
91 #$rh_ans_hash1 = $ans_eval1-&gt;evaluate($first_Answer);
92 
93 # warn pretty_print($rh_ans_hash); # this is useful error technique
 94 
95 # The output of each answer evaluator consists of a single %ans_hash
with (at 
96 # least) these entries: 
97 # $ans_hash{score} -- a number between 0 and 1 
98 # $ans_hash{correct_ans} -- The correct answer, as supplied by the
instructor
 99 # $ans_hash{student_ans} -- This is the student's answer 
100 # $ans_hash{ans_message} -- Any error message, or hint provided by 
101 # the answer evaluator. 
102 # $ans_hash{type} -- A string indicating the type of answer
evaluator. 
 103 # -- Some examples: 
104 # 'number_with_units' 
105 # 'function' 
106 # 'frac_number' 
107 # 'arith_number' 
108 # For more details see 
 109 #
http://cartan.math.rochester.edu/WeBWorKdiscussion/discuss/msgReader$15 
110 
111 # If they get the first answer right, then we'll ask a second part
to the 
112 # question ...
113 
114 if (1 == $rh_ans_hash1-&gt;{score} ) {
 115 
116 # WATCH OUT!!: BEGIN_TEXT and END_TEXT have to be on lines by 
117 # themselves and left justified!!! This means you can't indent 
118 # this section as you might want to. The placement of BEGIN_TEXT
 119 # and END_TEXT is one of the very few formatting requirements in
120 # the PG language.
121 
122 BEGIN_TEXT 
123 $PAR 
124 We got here.
125 END_TEXT
126 }
127 END_DOCUMENT
This can be done using the compoundProblem.pl library (available from the Union problem library), though you need to change one setting in order to make the last part an extra credit one.

Here's an example of a problem that gives 10% extra credit for the second part, which is hidden until the first part is shown.

DOCUMENT();

loadMacros(
  "PGstandard.pl",
  "compoundProblem.pl",
);

TEXT(beginproblem);

$isProfessor = ($studentLogin eq 'dpvc');  # your userID here

#
#  Start a compound problem.  See the compoundProblem.pl
#  file for more details about the parameters you
#  can supply.
#
$cp = new compoundProblem(
  parts => 2,                  # the total number of parts in this problem
  weights => [1,.1],           # 10% extra credit for second part
  allowReset => $isProfessor,  # professors get Reset button for testing
);
$cp->{totalWeight} = 1;        # make part 2 extra credit

$part = $cp->part;             # look up the current part


if ($part == 1) {

#
#  Use a named answer rule here so we can include
#  the value the student typed in the second half.
#

BEGIN_TEXT
Main Answer: \{NAMED_ANS_RULE("a",25)\}
END_TEXT

NAMED_ANS(a => num_cmp(5));

}

if ($part == 2) {

BEGIN_TEXT
Main Answer: $a
$PAR

Extra Credit: \{ans_rule(25)\}
END_TEXT

ANS(num_cmp(10));

}

ENDDOCUMENT();
See if that does what you want. The going on to the next part is awkward because the grader will not have been run yet when the text of the problem is being generated, and so you don't know whether the student's answer is right at the time the problem is being displayed. You don't know that until the NEXT time through, and so you need to have the extra "go on to the next part" step. I haven't found a way around that.

The key step for making the second part extra credit rather than part of the full credit is the line

    $cp->{totalWeight} = 1;
which resets it from being 1.1 to being just 1, so when the student gets the second part, the total will be 110% rather than 100%.

It would be possible to adjust the messages at the bottom somewhat, but you really don't have enough control over those to make it perfect.

Davide

I just remembered that there is a macro file that is pretty close to what you want. It is in pg/macros/problemRandomize.pl, and it implements a re-randomize feature. The condition for re-randomizing isn't the one you are looking for, but you should be able to modify it for that. (I'm not sure I'll get to it for a while.)

This macro file was new at the end of the summer, so you might not have it in your copy of pg/macros. If so, you can get it from the CVS repository:

http://cvs.webwork.rochester.edu/viewcvs.cgi/pg/macros/problemRandomize.pl?cvsroot=UR+WeBWorK+System

This file is probably a better starting place than the compoundProblem macros.

Davide
You are right that the current macros are not sufficient for this. At our recent conference at AIM in August, we worked out a specification for compound problems that include the functionality that you request, but I haven't had the chance to implement it yet.

If by "multipart grader" you mean the compoundProblem macros at

http://cvs.webwork.rochester.edu/viewcvs.cgi/union_problib/examples/compoundProblem/?cvsroot=Union+College

then I think you are looking at the right code (though it is pretty complicated, and there are a number of subtleties relating to how it maintains the state of the problem across invocations). I want to be sure that you are not confusing this with the MultiPart answer evaluator (which has been renamed to MultiAnswer evaluator to avoid just this confusion).

You will need to change the random seed, and maintain that as part of the data that is passed from one invocation to the next as well, so that the student will have the same version of the problem the next time they view it.

A limitation of the current system is that the hardcopy will always produce the original version of the file, not the one the student is currently working on. That is something that needs to be changed before a completely satisfactory solution to the problem is possible.

Davide