1       DOCUMENT();

2       loadMacros(

3               PGbasicmacros.pl,

4               PGanswermacros.pl,

5               PGchoicemacros.pl

6       );

7

8       TEXT(beginproblem());

9

10      BEGIN_TEXT

11              Complete the sentence: $PAR

12              \{ ans_rule(20) \}  world!

13      END_TEXT

14      ANS( str_cmp( "Hello" ) );

15

16      ENDDOCUMENT();


1       DOCUMENT();

The subroutine DOCUMENT() must the first line of any pg problem. It does setup procedures and initializes much of the information that will be used later on by WeBWorK to create the problem.

3       loadMacros(

4               PGbasicmacros.pl,

5               PGanswermacros.pl,

6       );

The loadMacros() call loads the specified macro files so that any macros that have been defined within them will be readily available to the professor.

Mandatory modules:

  • PGbasicmacros.pl defines many of the basic display macros used for displaying answer blanks, radio buttons, check boxes, solutions, hints, regular text, several reserved characters (ones that perl would otherwise interpret incorrectly, such as $DOLLAR returns a $) and basic html tags (such as $PAR for <P>).
  • PGanswermacros.pl defines the different methods for comparing the students answer(s) to the professors answer(s) with the ability to select many options such as case-sensitivity and tolerance.

Optional modules:

  • PGchoicemacros.pl contains methods used to create objects that allow the student to choose their answers (like Matching Lists and Multiple Choice questions).
  • PGgraphmacros.pl provides methods for creating and viewing graphs based on user-provided functions.
  • PGnumericalmacros.pl has pre-defined methods for several numerical calculus methods, such as Hermite splines and the Trapezoid Rule
  • PGauxiliaryFunctions.pl has many trigonometric and arithmetric functions that are not otherwise available in perl (arc functions, rounding functions, gcf, lcm, etc).
  • PG_CAPAmacros.pl contains macros that can help convert CAPA problems to WeBWorK problems.
  • Other Macro files can be and often are created to provide methods not otherwise found in any of the provided macro files.

8       TEXT(beginproblem());

The TEXT command is essentially the print command of the pg language. Everything that is passed to it, concatenated, evaluated, and then printed out.
The beginproblem() method prints some of the opening information that should be printed for each problem, such as how points it is worth and, if the user has permission, the filename of the problem.

10      BEGIN_TEXT

11              Complete the sentence: $PAR

12              \{ ans_rule(20) \}  world!

13      END_TEXT

The BEGIN_TEXT/END_TEXT pair is a replacement for the older EV2 and EV3 tags.

  • Both BEGIN_TEXT and END_TEXT tags must be alone on a line, but everything between them is printed exactly AS IS.
  • TeX (math mode) equations can be added by placing the TeX code between \( ... \) tags.
  • Perl variables can be added to the text directed (such as the above $PAR)
  • but calls to perl macros must be enclosed in \{ ... \} tags (such as the ans_rule(20) call which is a macro from PGbasicmacros.pl that creates an answer blank.)

14      ANS( str_cmp( "Hello" ) );

The ANS subroutine stores the answer evaluators used to evaluate the students answer by comparing the submitted answer to the one given by the instructor. How the answers are compared is determined by which answer evaluator is used (str_cmp("Hello") is one example) all of which are listed in PGanswermacros.pl.

16      ENDDOCUMENT();

The ENDDOCUMENT() finishes up the pg problem and makes sure everything closes out correctly. This must be the last line in your problem (at best anything after this will be ignored, at worst it will cause an error).

Final Notes:

Because we are writing a perl script, each statement must end in a semi-colon. Note however that many statements can be several lines long (such as loadMacros(), lines 2-5), these only require one semi-colon. All of the extra exterior links, buttons, forms, pictures, etc that are common to all problems are generated by the WeBWorK scripts and do not (and cannot) be created within the pg problem itself.

 

Top of Form

(1 pt) rochesterLibrary/setMAAtutorial/standardexample.pg


Standard Example

Complete the sentence:
world;

Enter the sum of these two numbers:
3 + 5 =

Enter the derivative of

f(x) = x^{5}


f '(x) =

Bottom of Form

you would type the following:

      

001:

002:

003: DOCUMENT();

004: loadMacros(PGbasicmacros.pl,

005: PGchoicemacros.pl,

006: PGanswermacros.pl,

007: PGauxiliaryFunctions.pl

008: );

009:

010: TEXT(beginproblem(), $BR,$BBOLD, Standard example, $EBOLD, $BR,$BR);

011:

012: # A question requiring a string answer.

013: $str = 'world';

014: #$str = "Dolly";

015: BEGIN_TEXT

016: Complete the sentence: $BR

017: \{ ans_rule(20) \} $str;

018: $PAR

019: END_TEXT

020:

021: ANS( str_cmp( "Hello") );

022:

023: # A question requiring a numerical answer.

024: #define the variables

025: $a = 3;

026: $b = 5;

027: #$a=random(1,9,1);

028: #$b=random(2,9,1);

029:

030: BEGIN_TEXT

031: Enter the sum of these two numbers: $BR

032: \($a + $b = \) {ans_rule(10) }

033: $PAR

034: END_TEXT

035:

036: $sum = $a + $b;

037: ANS( num_cmp( $sum ) );

038:

039: # A question requiring an expression as an answwer

040: BEGIN_TEXT

041: Enter the derivative of \[ f(x) = x^{$b} \] $BR

042: \(f '(x) = \) \{ ans_rule(30) \}

043: $PAR

044: END_TEXT

045: $new_exponent = $b-1;

046: $ans2 = "$b*x^($new_exponent)";

047: ANS( fun_cmp( $ans2 ) );

048: #<<<#########################################################

049: BEGIN_TEXT

050: $HR

051:

052: You can view the

053: \{ htmlLink(sourceAlias("links/set$setNumber/standardexample.html"),

054: "source", q!TARGET="source"!)\}

055: for this problem.

056: END_TEXT

057: #########################################################>>>

058: ENDDOCUMENT();

059:

060:


Comments:

Perl code:

In addition to the printed text, there are programming statements which define the coefficients used in the problem. Any statements that are not within BEGIN_TEXT / END_TEXT statements are interpreted as Perl code using additional subroutines (also called macros) written for the PG language. Even the DOCUMENT() and loadMacros(...) and ANS statements are progamming statements in Perl which call predefined subroutines.

PG macros: See Hello world example for info on the most basic PG macros. For more information on Perl see PG language basics.

Each Perl statement must end with a semi-colon.

Any line which begins with # is a comment line.

  1. The first group of statements repeats the Hello world question.
  2. The next group of statements defines a question requiring a numerical answer. In lines 25 and 26 we set $a equal to 3 and $b equal to 5.

If you want to choose random numbers instead, comment out lines 25 and 26 (insert # at the beginning of the line) and uncomment the next two lines.

The macro random(1,9,1) chooses random numbers uniformly distributed between 1 and 9 with step size 1. (To obtain fractional numbers use random(1,5,0.25) which will give you a uniformly distributed choice from the numbers 1, 1.25, 1.50,... 5. A short hand version for random(1,5,1) is random(1,5)). The variables named $a and $b now contain two integers. (In Perl all scalar variable names begin with a dollar sign. A scalar variable can hold a single number (integer or real number) or a string (of characters). A scalar variable can also hold "pointers" and "objects" as will be explained later.

  1. Variable Interpolation Inserting the phrase $a + $b in the text portion of the problem causes the quantities stored in $a and $b to be printed (interpolated). Note: In text mode these numbers are not added, the plus sign is printed just as a plus sign (line 32).
  2. Math mode The construction \( ...\) means that anything inside the parentheses will be printed or typeset in "math mode" (line32). This is the same construction used in LaTeX and it means that the formatting of formulas and numbers inside these parentheses will conform as closely as possible to the standards for typesetting equations.
  3. Display math mode This is almost the same as math mode, but it uses the construction \[...\] to display a mathematical formula in a paragraph by itself (line 41).
  4. All mathematics formulas, including numbers, should be enclosed in either the math mode or the display math mode construction or else they will not look like math formulas.
  5. In the statement

$sum = $a + $b;

the contents of the variables $a and $b are added and placed in the variable $ans (line 36).

  1. More answer evaluators:

The answer evaluator num_cmp($ans) compares the student's answer with the number stored in the variable $ans (line 37). For real numbers the answers are expected to agree to within .01%. See the documentation for answer evaluators and PGanswermacros.pl

Then answer evaluator fun_cmp($ans2) compares the student answer with the function defined by the string in the variable $ans2 (line 47).

The three answer evaluators str_cmp(..) for strings, num_cmp($ans) for numbers, and fun_cmp(...) for functions are the three most commonly used methods of checking answers. It is however possible to customize these answer_evaluators and even to create new ones.

  1. More examples:
    setAlgebra5Equations/srw1_5_22.pg -- source
    setDerivatives13Higher/s2_7_10.pg -- source

 

'Matching list' basic example

(for more advanced information on matching lists, see Match.pm) To obtain the problem:



(1 pt) rochesterLibrary/setMAAtutorial/matchinglistexample.pg


Matching list example

Place the letter of the derivative next to each function listed below:

 1. 2x^5
 2. \tan(x)
 3. \sin(2x)
 4. \sin(3x)


A. 4x^{1}
B. \sec^2(x)
C. 3\cos(3x)
D. 2\cos(2x)

Let's print the questions again, but insist that the first two questions (about sin and cos) always be included. Here is a second way to format this question, using tables:

 1. \cos(x)
 2. \sin(x)
 3. \tan(x)


A. -\sin(x)
B. \cos(x)
C. \sec^2(x)

And below is yet another way to enter a table of questions and answers:

 1. \cos(x)
 2. \sin(x)
 3. \tan(x)


A. -\sin(x)
B. \cos(x)
C. \sec^2(x)
D. The derivative is
not provided


 
DOCUMENT();        # This should be the first executable line in the problem.
 
loadMacros(
           "PGbasicmacros.pl",
           "PGchoicemacros.pl",
           "PGanswermacros.pl",
           );
 
 
TEXT(beginproblem(), $BR,$BBOLD, "Matching list example", $EBOLD, $BR,$BR);
 
 
# Since this is a matching question, we do not usually wish to tell students
# which parts of the matching question have been answered correctly and which
# areincorrect.  That is too easy.  To accomplish this we set the following
# flag to zero.
$showPartialCorrectAnswers = 0;
 
# Make a new match list
$ml = new_match_list();
# enter questions and matching answers
$ml -> qa (
"\( \sin(x) \)",        # Notice the use of the LateX construction
"\( \cos(x) \)",                # for math mode: \( ...  \) and the use of TeX
"\( \cos(x) \)",        # symbols such as \sin and \tan.
"\( -\sin(x) \)",
"\( \tan(x) \)",
"\( \sec^2(x) \)",      # Remember that in these strings we are 
                                                # only specifying typography,via TeX,
"\( x^{20} \)",         #not any calculational rules.
"\( 20x^{19} \)",
"\( \sin(2x) \)",
"\( 2\cos(2x) \)",
"\( \sin(3x) \)",
"\( 3\cos(3x) \)"
);
 
 
# Calculate coefficients for another question
$b=random(2,5);
$exp= random(2,5);
$coeff=$b*$exp;
$new_exp = $exp-1;
 
# Store the question and answers in the match list object.
$ml -> qa (
    '\( ${b}x^$exp \)',
    '\( ${coeff}x^{$new_exp} \)',
);
 
# Add another example
$b2=random(2,5);
$exp2= random(2,5);
$coeff2=$b2*$exp;
$new_exp2 = $exp-1;
$ml -> qa (
"\( ${b2}x^$exp2 \)",
"\( ${coeff2}x^{$new_exp2} \)",
);
 
# Choose four of the question and answer pairs at random.
$ml ->choose(4); 
# Using choose(8) would choose all eight questions,
# but the order of the questions and answers would be
# scrambled.
 
# The following code is needed to make the enumeration work right within tables
# when LaTeX output is being used.
# It is an example of the powerful tools of TeX and perl which are available
# for each PG problem author. 
# Once we figure out the best way to protect enumerated lists automatically
# we will include it in the tables macro.  Meantime, it is better to have
# have to do it by hand, rather than to have the wrong thing done automatically.
 
$BSPACING = MODES( TeX               => '\hbox to .5\linewidth {\hspace{0.5cm}\vbox {',
                                   HTML            =>' ',
                                   Latex2HTML => ' '
);
$ESPACING = MODES(TeX => '}}', HTML =>'', Latex2HTML => '');
sub protect_enumerated_lists {
        my @in = @_;
        my @out = ();
        foreach my $item (@in) {
                push(@out, $BSPACING . $item . $ESPACING);
        }
        @out;
}
# End of code for protecting enumerated lists in TeX.
 
# Now print the text using $ml->print_q for
# the questions and $ml->print_a to print the answers.
 
BEGIN_TEXT
$PAR
 
Place the letter of the derivative next to each function listed below: $BR
\{ $ml -> print_q \}
$PAR
\{$ml -> print_a \}
$PAR
END_TEXT
 
ANS(str_cmp( $ml->ra_correct_ans )   ) ;
# insist that the first two questions (labeled 0 and 1) are always included
$ml ->choose([0,1],1);
BEGIN_TEXT
Let's print the questions again, but insist that the
first two questions (about sin and cos) always be included.
Here is a second way to format this question, using tables:
$PAR
\{begintable(2)\}
\{row(protect_enumerated_lists( $ml->print_q, $ml -> print_a) )\}
\{endtable()\}
$PAR
And below is yet another way to enter a table of questions and answers:
$PAR
END_TEXT
ANS(str_cmp( $ml->ra_correct_ans )   ) ;
# Finally add a last answer
$ml ->makeLast("The derivative is $BR not provided");
BEGIN_TEXT
    \{ begintable(2) \}
    \{ row(   protect_enumerated_lists($ml->print_q, $ml ->print_a))\}
    \{endtable()\}
END_TEXT
# Enter the correct answers to be checked against the answers to the students.
ANS(str_cmp( $ml->ra_correct_ans )   ) ;
 
ENDDOCUMENT();      
 
 

  1. Since this is a matching questions, we do not usually wish to tell students which parts of the matching question have been answered correctly and which are incorrect. That is too easy. To accomplish this we set the following flag $showPartialCorrectAnswers to 0 (line 11).
  2. Saying that $ml$ml is a scalar variable which contains a pointer to the match list object, but you can think of the match list object as being shoe horned into the variable $ml. You need to remember that $ml Some people use the convention $o_ml to remind them that the variable contains an object, but for short problems that is probably not necessary.

An object contains both data (in this case the list of questions and answers) and subroutines (called methods) for manipulating that data.

  1. The construction $ml ->qa(..list of alternating questions and matching answers ...). Asks the object $ml to store the matching questions and answers given in the argument in its private data (lines 35 and 45). Note that that you can call qa() more than once with a match list and it will add new questions. This is not true with all objects. Some objects will overwrite previous questions if qa() is used more than once.
  2. The construction $ml->choose(3) asks the object to choose three question/answer pairs from its private data and
  3. $out = $ml->print_q() asks the object to store a string of the formatted questions in the variable $out. Calling \{ $ml->print_q() \} within BEGIN_TEXT / END_TEXT statements will just append the formatted questions to the ouput text that the student sees (line 60).
  4. $out = $ml->print_a() asks the object to store a string of the formatted answers in the variable $out. \{ $ml->print_a() \} can be used just like above to append a string of the formatted answers to the output text seen by the student (line 62).
  5. ANS is needed to compare the students answers to the correct answers (line 66).
  6. The answer evaluator str_cmp is just one of many possible answer evaluators from which to choose, each of which specifies a different method for comparing the correct answers to the students answers. str_cmp is almost always used with matching lists since the correct answers will always be a letter indicating one of the possible answers (line 66).

Top of Form

(1 pt) rochesterLibrary/setMAAtutorial/truefalseexample.pg


True False Example

Enter T or F depending on whether the statement is true or false. (You must enter T or F -- True and False will not work.)

 1. All differentiable strictly increasing functions have non-negative derivatives at every point
 2. All polynomials are differentiable.
 3. All compact sets are closed
 4. All closed sets are compact

Bottom of Form


 

DOCUMENT();     

loadMacros("PGbasicmacros.pl",

           "PGchoicemacros.pl",

           "PGanswermacros.pl",

 

);

TEXT(beginproblem(), $BR,$BBOLD, "True False Example", $EBOLD, $BR,$BR);

 

# Since this is a true questions, we do not usually wish to tell students which

# parts of the matching question have been answered correctly and which are

# incorrect.  That is too easy.  To accomplish this we set the following flag to

# zero.

$showPartialCorrectAnswers = 0;

 

# True false questions are a special case of a "select list"

# Make a new select list

$tf = new_select_list();

# $tf now "contains" the select list object.

# Insert some  questions and whether or not they are true.

 

$tf -> qa ( # each entry has to end with a comma

"All continuous functions are differentiable.",

"F",

"All differentiable functions are continuous.",

"T",

"All polynomials are differentiable.",

"T",

"All functions with positive derivatives are increasing.",

"T",

"All compact sets are closed",

"T",

"All closed sets are compact",

"F",

"All increasing functions have positive deriviatives",

"F",

"All differentiable strictly increasing functions have non-negative derivatives

                                        at every point",

"T",

);  

 

# Choose four of the question and answer pairs at random.

$tf ->choose(4);

 

# Now print the text using $ml->print_q for the questions

# and $ml->print_a to print the answers.

 

BEGIN_TEXT

$PAR

 

Enter T or F depending on whether the statement is true or false.

(You must enter T or F -- True and False will not work.)$BR

 

\{ $tf-> print_q \}