NAME

PGbasicmacros.pl --- located in the courseScripts directory

DESCRIPTION

This includes constants and basic functions for PG.

Answer blank macros:

These produce answer blanks of various sizes or pop up lists or radio answer buttons. The names for the answer blanks are generated and implicitly associated with answer evaluators via the ANS method.

ans_rule(width)
ans_radio_buttons(value1 => name1, value2, name2 => value3, name3 => ...)
pop_up_list(@list)      # list consists of (value => label, PR => "Product rule", ...)
pop_up_list([@list])    # list consists of values

In the last case, one can use pop_up_list(['?', 'yes', 'no']) to produce a pop-up list containing the three strings listed, and then use str_cmp to check the answer.

To indicate the checked position of radio buttons put a '%' in front of the value: ans_radio_buttons(1, 'Yes', '%2', 'No') will have 'No' checked.

The following method is defined in PG.pl for entering the answer evaluators corresponding to answer rules with automatically generated names. The answer evaluators are matched with the answer rules in the order in which they appear on the page.

ANS(ans_evaluator1, ans_evaluator2, ...);

These are more primitive macros which produce answer blanks for specialized cases when complete control over the matching of answers blanks and answer evaluators is desired. The names of the answer blanks must be generated manually, and it is best if they do NOT begin with the default answer prefix (currently AnSwEr).

NAMED_ANS_RULE(name, width)
labeled_ans_rule(name, width)    # alias for NAMED_ANS_RULE
    NAMED_ANS_BOX(name, rows, cols)
NAMED_ANS_RADIO(name, value, name)
NAMED_ANS_RADIO_EXTENSION(name, value, name)
NAMED_ANS_RADIO_BUTTONS(name, value1, name1, value2, name2, ...)
NAMED_POP_UP_LIST($name, @list)     # list consists of (value => tag, PR => "Product rule", ...)
NAMED_POP_UP_LIST($name, [@list])   # list consists of a list of values
                                    # (and each tag will be set to the corresponding value)

(Name is the name of the input, value is the value given to the input when this option is selected, and label is the text printed next to the button or check box. Check box variables can have multiple values.)

NAMED_ANS_RADIO_BUTTONS creates a sequence of NAMED_ANS_RADIO and NAMED_ANS_RADIO_EXTENSION items which are output either as an array or, in scalar context, as the array glued together with spaces. It is usually easier to use this than to manually construct the radio buttons by hand. However, sometimes extra flexibility is desiredin which case:

When entering radio buttons using the "NAMED" format, you should use NAMED_ANS_RADIO button for the first button and then use NAMED_ANS_RADIO_EXTENSION for the remaining buttons. NAMED_ANS_RADIO requires a matching answer evalutor, while NAMED_ANS_RADIO_EXTENSION does not. The name used for NAMED_ANS_RADIO_EXTENSION should match the name used for NAMED_ANS_RADIO (and the associated answer evaluator).

The following method is defined for entering the answer evaluators corresponding to answer rules. The answer evaluators are matched with the answer rules in the order in which they appear on the page.

NAMED_ANS(name1 => ans_evaluator1, name2 => ans_evaluator2, ...);

Auxiliary macros defined in PG.pl:

NEW_ANS_NAME()

Produces a new anonymous answer blank name by appending a number to the prefix (AnSwEr).

ANS_NUM_TO_NAME(number)

Prepends the prefix (AnSwEr) to the number, but does nothing else.

RECORD_ANS_NAME(name)

Records the order in which the answer blank is rendered. All answer rules must be recorded by this method. All named answer rule methods in this macro do this. Most answer rules created elsewhere call a named answer rule method in this macro to handle this.

RECORD_IMPLICIT_ANS_NAME(name)

Records answer names which are to be implicitly associated with an answer This is called by the internal answer rule methods, but must be called for all answer rules constructed elsewhere as well. After this is called RECORD_ANS_NAME must be called as well. Usually the appropriate named answer rule method should be called which will do this.

Deprecated macro (still used by many problems):

ANS_RULE(number, width);    # equivalent to ans_rule(width) -- number is ignored

answer_matrix

Usage   \[ \{ answer_matrix(rows, columns, width_of_ans_rule, @options) \} \]

Creates an array of answer blanks and passes it to display_matrix which returns
text which represents the matrix in TeX format used in math display mode. Answers
are then passed back to whatever answer evaluators you write at the end of the problem.
(note, if you have an m x n matrix, you will need mn answer evaluators, and they will be
returned to the evaluaters starting in the top left hand corner and proceed to the left
and then at the end moving down one row, just as you would read them.)

The options are passed on to display_matrix.

Note (7/21/2017) The above usage does not work. Omitting the \[ \] works, but also must
load PGmatrixmacros.pl to get display_matrix used below

Hints, solutions, and statement macros

solution('text', 'text2', ...);
SOLUTION('text', 'text2', ...); # equivalent to TEXT(solution(...));

hint('text', 'text2', ...);
HINT('text', 'text2', ...);    # equivalent to TEXT("$BR$HINT" . hint(@_) . "$BR") if hint(@_);

statement('text');
STATEMENT('text');            # equivalent to TEXT(statement(...));

statement takes a string, probably from EV3P, and possibly wraps opening and closing content, paralleling one feature of solution and hint.

If $envir{showSolutions} is set to 1 then the solution is displayed.

If $envir{showHints} is set to 1 then the hint is displayed.

Comments to instructors

COMMENT('text', 'text2', ...);

Takes the text to be lines of a comment to be shown only in the Library Browser below the rendered problem.

The function COMMENT stores the needed html in the variable pgComment, which gets transfered to the flag 'comment' in PG_FLAGS.

Pseudo-random number generator

Usage:
random(0, 5, .1)          # produces a random number between 0 and 5 in increments of .1
non_zero_random(0, 5, .1) # gives a non-zero random number

list_random(2, 3, 5, 6, 7, 8, 10) # produces random value from the list
list_random(2, 3, (5..8), 10) # does the same thing

SRAND(seed)     # resets the main random generator -- use very cautiously

SRAND(time) will create a different problem everytime it is called. This makes it difficult to check the answers :-).

SRAND($envir->{'inputs_ref'}->{'key'} ) will create a different problem for each login session. This is probably what is desired.

Display Macros

These macros produce different output depending on the display mode being used to show the problem on the screen, or whether the problem is being converted to TeX to produce a hard copy output.

MODES   ( TeX        => "Output this in TeX mode",
          HTML       => "output this in HTML mode",
          HTML_tth   => "output this in HTML_tth mode",
          HTML_dpng  => "output this in HTML_dpng mode",
          Latex2HTML => "output this in Latex2HTML mode",
         )

M3      (tex_version, latex2html_version, html_version) #obsolete

Display constants

@ALPHABET           ALPHABET()           capital letter alphabet -- ALPHABET[0] = 'A'
$PAR                PAR()                paragraph character (\par or <p>)
$BR                 BR()                 line break character
$BRBR               BRBR()               line break character
$LQ                 LQ()                 left double quote
$RQ                 RQ()                 right double quote
$BM                 BM()                 begin math
$EM                 EM()                 end math
$BDM                BDM()                begin display math
$EDM                EDM()                end display math
$LTS                LTS()                strictly less than
$GTS                GTS()                strictly greater than
$LTE                LTE()                less than or equal
$GTE                GTE()                greater than or equal
$BEGIN_ONE_COLUMN   BEGIN_ONE_COLUMN()   begin one-column mode
$END_ONE_COLUMN     END_ONE_COLUMN()     end one-column mode
$SOL                SOLUTION_HEADING()   solution headline
$SOLUTION           SOLUTION_HEADING()   solution headline
$HINT               HINT_HEADING()       hint headline
$US                 US()                 underscore character
$SPACE              SPACE()              space character (tex and latex only)
$NBSP               NBSP()               non breaking space character
$NDASH              NDASH()              en dash character
$MDASH              MDASH()              em dash character
$BLABEL             BLABEL()             begin label (for input)
$ELABEL             ELABEL()             end label (for input)
$BBOLD              BBOLD()              begin bold typeface
$EBOLD              EBOLD()              end bold typeface
$BITALIC            BITALIC()            begin italic typeface
$EITALIC            EITALIC()            end italic typeface
$BUL                BUL()                begin underlined type
$EUL                EUL()                end underlined type
$BCENTER            BCENTER()            begin centered environment
$ECENTER            ECENTER()            end centered environment
$BLTR               BLTR()               begin left to right environment
$ELTR               ELTR()               end left to right environment
$BKBD               BKBD()               begin "keyboard" input text
$EKBD               EKBD()               end "keyboard" input text
$HR                 HR()                 horizontal rule
$LBRACE             LBRACE()             left brace
$LB                 LB ()                left brace
$RBRACE             RBRACE()             right brace
$RB                 RB ()                right brace
$DOLLAR             DOLLAR()             a dollar sign
$PERCENT            PERCENT()            a percent sign
$CARET              CARET()              a caret sign
$PI                 PI()                 the number pi
$E                  E()                  the number e
$LATEX              LATEX()              the LaTeX logo
$TEX                TEX()                the TeX logo
$APOS               APOS()               an apostrophe

SPAN and DIV macros These are functions primarly meant to add HTML block level DIV or inline SPAN tags and the relevant closing tags for HTML output.

At present, these macros require the user to provide TeX and
preTeXt strings which will be used in those modes instead of the
HTML block level DIV or inline SPAN tag.

If they are missing, they will default to the empty string.
If only one string is given, it will be assumed to be the TeX string.

At present only the following 4 HTML attributes can be set:
                 lang, dir, class, style.
Using the style option requires creating valid CSS text.
For safety some parsing/cleanup is done and various sorts of
(apparently) invalid values may be dropped. See the code for
details of what input sanitation is done.

Since the use of style is particularly dangerous, in order to
enable its use you must set allowStyle to 1 in the hash. It is
possible to prevent the use of some of the other options by
setting certain control like allowLang to 0.

Usage:
  openSpan( options_hash,  "tex code", "ptx code" );
  closeSpan("tex code", "ptx code");

Usage where TeX and PTX output will be empty by default.
  openSpan( options_hash );
  closeSpan();

Sample options hashes

    { "lang" => "he",
      "dir" => "rtl",
      "class" => "largeText class123" }

    { "lang" => "he",
      "allowStyle" => 1,
       "style" => "background-color: \"#afafaf; float: left;\t height: 12px;" }

TEXT macros

Usage:
    TEXT(@text);

This is the simplest way to print text from a problem. The strings in the array @text are concatenated with spaces between them and printed out in the text of the problem. The text is not processed in any other way. TEXT is defined in PG.pl.

Usage:
    BEGIN_TEXT
        text.....
    END_TEXT

This is the most common way to enter text into the problem. All of the text between BEGIN_TEXT and END_TEXT is processed by the EV3 macro described below and then printed using the TEXT command. The two key words must appear on lines by themselves. The preprocessing that makes this construction work is done in PGtranslator.pm. See EV3 below for details on the processing.

Evaluation macros

EV3

TEXT(EV3("This is a formulat \( \int_0^5 x^2 \, dx \) ");
TEXT(EV3(@text));

TEXT(EV3(<<'END_TEXT'));
    text stuff...
END_TEXT

The BEGIN_TEXT/END_TEXT construction is translated into the construction above by PGtranslator.pm. END_TEXT must appear on a line by itself and be left justified. (The << construction is known as a "here document" in UNIX and in PERL.)

The single quotes around END_TEXT mean that no automatic interpolation of variables takes place in the text. Using EV3 with strings which have been evaluated by double quotes may lead to unexpected results.

The evaluation macro E3 first evaluates perl code inside the braces: \{ code \}. Any perl statment can be put inside the braces. The result of the evaluation (i.e. the last statement evaluated) replaces the \{ code \} construction.

Next interpolation of all variables (e.g. $var or @array ) is performed.

Then mathematical formulas in TeX are evaluated within the \( tex math mode \) and \[ tex display math mode \] constructions, in that order:

refreshEquations

refreshEquations(1);

Prevents equations generated in "image mode" from being cached. This can be useful for debugging. It has no effect in the other modes.

addToTeXPreamble

addToTeXPreamble("\newcommand{\myVec}[1]{\vec{#1}} ");

Defines \myVec for all the equations in the file. You can change the vector notation for an entire PG question by changing just this line.

If you place this macro in PGcourse.pl remember to use double backslashes because it is a .pl file. In .pg files use single backslashes. This is in accordance with the usual rules for backslash in PG.

For the moment this change only works in image mode. It does not work in jsMath or MathJax mode. Stay tuned.

Adding this command

\newcommand{\myVec}[1]{\vec{#1}}

to TeX(hardcopy) portion of the setHeaderCombinedFile.pg ( or to the setHeaderHardcopyFile.pg for each homework set will take care of the TeX hardcopy version

You can also modify the TexPreamble file in webwork2/conf/snippets to set the definition of \myVec for hardcopy for the entire site.

There are ways you can use course.conf to allow course by course modification by choosing different TeXPreamble files for different courses

FEQ

FEQ($string);   # processes and outputs the string

The mathematical formulas are run through the macro FEQ (Format EQuations) which performs several substitutions (see below). In HTML_tth mode the resulting code is processed by tth to obtain an HTML version of the formula. (In the future processing by WebEQ may be added here as another option.) The Latex2HTML mode does nothing at this stage; it creates the entire problem before running it through TeX and creating the GIF images of the equations.

The resulting string is output (and usually fed into TEXT to be printed in the problem).

Usage:

    $string2 = FEQ($string1);

This is a filter which is used to format equations by EV2 and EV3, but can also be used on its own. It is best understood with an example.

$string1 = "${a}x^2 + ${b}x + {$c:%.1f}"; $a = 3;, $b = -2; $c = -7.345;

when interpolated becomes:

$string1 = '3x^2 + -2x + {-7.345:%0.1f}

FEQ first changes the number of decimal places displayed, so that the last term becomes -7.3 Then it removes the extraneous plus and minus signs, so that the final result is what you want:

$string2 = '3x^2 - 2x -7.3';

(The %0.1f construction is the same formatting convention used by Perl and nearly identical to the one used by the C printf statement. Some common usage: %0.3f 3 decimal places, fixed notation; %0.3e 3 significant figures exponential notation; %0.3g uses either fixed or exponential notation depending on the size of the number.)

Two additional legacy formatting constructions are also supported:

!{$c:%0.3f} will give a number with 3 decimal places and a negative sign if the number is negative, no sign if the number is positive. Since this is identical to the behavior of {$c:%0.3f} the use of this syntax is depricated.

?{$c:%0.3f} determines the sign and prints it whether the number is positive or negative. You can use this to force an expression such as +5.456.

EV2

TEXT(EV2(@text));

TEXT(EV2(<<END_OF_TEXT));
    text stuff...
END_OF_TEXT

This is a precursor to EV3. In this case the constants are interpolated first, before the evaluation of the \{ ...code...\} construct. This can lead to unexpected results. For example \{ join(" ", @text) \} with @text = ("Hello", "World"); becomes, after interpolation, \{ join(" ", Hello World) \} which then causes an error when evaluated because Hello is a bare word. EV2 can still be useful if you allow for this, and in particular it works on double quoted strings, which lead to unexpected results with EV3. Using single quoted strings with EV2 may lead to unexpected results.

The unexpected results have to do with the number of times backslashed constructions have to be escaped. It is quite messy. For more details get a good Perl book and then read the code. :-)

EV3P

######################################################################
#
#  New version of EV3 that allows `...` and ``...`` to insert TeX produced
#  by the new Parser (in math and display modes).
#
#  Format:  EV3P(string, ...);
#           EV3P({options}, string, ...);
#
#           `x^2/5` will become \(\frac{x^2}{5}\) and then rendered for hardcopy or screen output
#
#  where options can include:
#
#    processCommands => 0 or 1     Indicates if the student's answer will
#                                  be allowed to process \{...\}.
#                                    Default: 1
#
#    processVariables => 0 1       Indicates whether variable substitution
#                                  should be performed on the student's
#                                  answer.
#                                    Default: 1
#
#    processMath => 0 or 1         Indicates whether \(...\), \[...\],
#                                  `...` and ``...`` will be processed
#                                  in the student's answer.
#                                    Default: 1
#
#    processParser => 0 or 1       Indicates if `...` and ``...`` should
#                                  be processed when math is being
#                                  processed.
#                                    Default: 1
#
#    fixDollars => 0 or 1          Specifies whether dollar signs not followed
#                                  by a letter should be replaced by ${DOLLAR}
#                                  prior to variable substitution (to prevent
#                                  accidental substitution of strange Perl
#                                  values).
#                                    Default: 1
#

Formatting macros

beginproblem()  # Adds a custom TeX preamble.  This is deprecated and should not be used in newly written problems.
OL(@array)      # formats the array as an Ordered List ( <OL> </OL> ) enumerated by letters.
                # See BeginList()  and EndList in unionLists.pl for a more powerful version
                # of this macro.
knowlLink($display_text, url => $url, value =>'', type =>'' )
                # Places a reference to a knowl for the URL with the specified text in the problem.
                # A common usage is \{ 'for help', url =>knowlLink(alias('prob1_help.html')) \} )
                # where alias finds the full address of the prob1_help.html file in the same directory
                # as the problem file
knowlLink($display_text,  url => '', type =>'', value = <<EOF );  # this starts a here document that ends at EOF (left justified)
                help text goes here .....
EOF
                # This version of the knowl reference facilitates immediate reference to a HERE document
                # The function should be called either with value specified (immediate reference) or
                # with url specified in which case the revealed text is taken from the URL $url.
                # The $display_text is always visible and is clicked to see the contents of the knowl.
htmlLink($url, $text)
                # Places a reference to the URL with the specified text in the problem.
                # A common usage is \{ htmlLink(alias('prob1_help.html') \}, 'for help')
                # where alias finds the full address of the prob1_help.html file in the same directory
                # as the problem file
iframe($url, height=>'', width=>'', id=>'', name=>'' )
                # insert the web page referenced by $url in a space defined by height and width
                # if the webpage contains a form then this must be inserted between
                # BEGIN_POST_HEADER_TEXT/END_POST_HEADER_TEXT  to avoid having one
                # form(from the webpage) inside another (the defining form for the problem
A wide variety of google widgets, youtube videos, and other online resources can be imbedded using this macro. In HTML mode it creates an iframe, in TeX mode it prints the url.

helpLink($type)
               Allows site specific help.
               The parameter localHelpURL  must be defined in the environment
               and is set by default to pg/htdocs/helpFiles
               Standard helpFile types
                    'angle'
                    'decimal'
                    'equation'
                    'essay'
                    'exponent'
                    'formula'
                    'fraction'
                    'inequalit'
                    'limit'
                    'log'
                    'number'
                    'point'
                    'vector'
                    'interval'
                    'unit'
                    'syntax'

low level:

spf($number, $format)   # prints the number with the given format
sspf($number, $format)  # prints the number with the given format, always including a sign.
nicestring($coefficients, $terms) # print a linear combinations of terms using coefficients
nicestring($coefficients) # uses the coefficients to make a polynomial
        # For example
        # nicestring([1, -2, 0]) produces 'x^2-2x'
        # nicestring([2, 0, -1], ['', 't', 't^2']) produces '2-t^2'
protect_underbar($string) # protects the underbar (class_name) in strings which may have to pass through TeX.

Inserts a knowl link into the problem. Usually you should not call this method directly. Instead use helpLink below.

Usage: knowlLink($displayText, %options)

$display_text is the text that will be shown for the link.

The following options may be included in %options. Note that one of url or value is required.

url

A URL whose contents will be shown in a modal dialog when the knowl link is clicked. These contents will be fetched by JavaScript and injected into the knowl modal dialog.

value

The direct contents that will be shown in a modal dialog when the knowl link is clicked.

title

A string that will be used for the title of the modal dialog that opens when the knowl link is clicked. If this is not provided, then $display_text will be used for the title.

type

A string that will be set as the data-type attribute of the knowl link. This is only used by PreTeXt.

Example usage:

knowlLink('Click Me', title => 'Fascinating Contents', value => 'Here are my facinating contents.');
knowlLink('Help Me', title => 'Help Contents', url => 'https://my.domain.edu/helpfile-contents');

Usage: helpLink($type, $display_text, $helpurl)

Creates links for students to help documentation on formatting answers and allows for custom help links.

There are 16 predefined help links: angles, decimals, equations, exponents, formulas, fractions, inequalities, intervals, limits, logarithms, matrices, numbers, points, syntax, units, vectors.

Usage:

DOCUMENT();
loadMacros("PGstandard.pl");
BEGIN_TEXT
\{ ans_rule(20) \} \{ helpLink("formulas") \}
$PAR
\{ ans_rule(20) \} \{ helpLink("equations", "help entering equations") \}
$PAR
\{ ans_rule(20) \}
\{ helpLink("my custom help", undef, "custom_help.html") \}
END_TEXT
ENDDOCUMENT();

The first example uses the default link text and displays the help link next to the answer blank which is recommended.

The second example customizes the link text displayed to the student, but the actual help document is unaffected.

The third example displays a link to the contents of custom_help.html. Note that the file custom_help.html must be located in the location defined in the environment variable $envir{localHelpURL}. The value of that variable can be customized by a problem.

PGsort

Because of the way sort is optimized in Perl, the symbols $a and $b have special significance.

sort {$a<=$b} @list> sort {$a cmp $b} @list

sorts the list numerically and lexically respectively.

If my $a; is used in a problem, before the sort routine is defined in a macro, then things get badly confused. To correct this the macro PGsort is defined below. It is evaluated before the problem template is read. In PGbasicmacros.pl, the two subroutines

PGsort sub { $_[0] < $_[1] }, @list;
PGsort sub { $_[0] lt $_[1] }, @list;

(called num_sort and lex_sort) provide slightly slower, but safer, routines for the PG language. (The subroutines for ordering are required. Note the commas!)

Sorting and other list macros

Usage:
lex_sort(@list);   # outputs list in lexigraphic (alphabetical) order
num_sort(@list);   # outputs list in numerical order
uniq( @list);      # outputs a list with no duplicates.  Order is unspecified.

PGsort( \&sort_subroutine, @list);
# &sort_subroutine defines order. It's output must be 1 or 0 (true or false)

Macros for handling tables

Usage:
begintable( number_of_columns_in_table)
row(@dataelements)
endtable()

Example of useage:

BEGIN_TEXT
    This problem tests calculating new functions from old ones:$BR
    From the table below calculate the quantities asked for:$BR
    \{begintable(scalar(@firstrow)+1)\}
    \{row(" \(x\) ", @firstrow)\}
    \{row(" \(f(x)\) ", @secondrow)\}
    \{row(" \(g(x)\) ", @thirdrow)\}
    \{row(" \(f'(x)\) ", @fourthrow)\}
    \{row(" \(g'(x)\) ", @fifthrow)\}
    \{endtable()\}

 (The arrays contain numbers which are placed in the table.)

END_TEXT

Macros for displaying images

Usage:

image($image, width => 200, height => 200, tex_size => 800, valign => 'middle', alt => 'alt text', extra_html_tags => 'style="border:solid black 1pt"');

where $image can be a local file path, URL, WWPlot object, PGlateximage object, PGtikz object, or parser::GraphTool object.

width and height are positive integer pixel counts for HTML display. If both are missing, width will default to 200 and height will remain undeclared, letting the browser display the image with its natural aspect ratio. Except with a parser::GraphTool object, if both are missing then nothing will be passed along to the GraphTool method for display, and that macro's defaults will be used.

tex_size is also a positive integer, per 1000 applied to the line width in TeX. For example 800 leads to 0.8\linewidth. If over 1000, then 1000 will be used. If missing, this defaults to int(width/0.6) so the image is proportional to its HTML version with a 600 pixel wide reading area. If width is missing and height is declared, we presume this is a wide image and then tex_size defaults to 800.

valign can be 'top', 'middle', or 'bottom'. This aligns the image relative to the surrounding line of text.

image([$image1,$image2], width => 200, height => 200, tex_size => 800, alt => ['alt text 1','alt text 2'], extra_html_tags => 'style="border:solid black 1pt"');
image([$image1,$image2], width => 200, height => 200, tex_size => 800, alt => 'common alt text', extra_html_tags => 'style="border:solid black 1pt"');

this produces an array in array context and joins the elements with ' ' in scalar context

Tag helper method:

tag('input', name => 'AnSwEr0001', id => 'answer_id')
tag('div', class => 'style-class', 'This is my content')

This produces an html tag with attributes. This is designed to be similar to the Mojolicious::Plugin::TagHelpers tag method (although much simpler and not nearly as versatile). The first argument is the tag name and is required. This is followed by attribute name => value pairs. Note that all underscores in attribute names are converted into hyphens. The final argument is the content of the tag. If not given the tag will have no content. This is ignored for a self closing tag if given.

Currently this is only designed to be used for HTML output, but perhaps could be extended for XML (PTX) output.