WeBWorK Problems

Dynamic PGML solution with images

Dynamic PGML solution with images

by Carl Yao -
Number of replies: 6
Hello:

I'm trying to dynamically generate PGML solution in a problem. The following trick has been working well for numbers:

$a = 1;
$test = "[`$a`]";

PGML_SOLUTION
[$test]**
END_PGML_SOLUTION

However, I don't know how to include an image between the quotation marks. The following program doesn't work. Please help if you can. Thank you!

Carl Yao
Portland Community College



##############################################
DOCUMENT();

loadMacros(
"PGstandard.pl",
"MathObjects.pl",
"PGML.pl",
"PGgraphmacros.pl",
"PGcourse.pl",
);

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

Context("Numeric");

$gr = init_graph(-1,-1,4,4,
axes=>[0,0],
grid=>[5,5],
size=>[400,400]
);

add_functions($gr, "x^2/4 for x in <-1,4>" .
" using color:blue and weight:2");

$alt1 = "text for accessibility";

$output = "

>>[@ image(insertGraph( $gr ), tex_size=>400, height=>400, width=>400,
extra_html_tags=>~~"alt= ~~'$alt1~~' title= ~~'$alt1~~'~~") @]*<<

";


##############################################
TEXT(beginproblem());

BEGIN_PGML

Testing Graph

END_PGML

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

BEGIN_PGML_SOLUTION

Normal graph:

>>[@ image(insertGraph( $gr ), tex_size=>400, height=>400, width=>400,
extra_html_tags=>"alt= '$alt1' title= '$alt1'") @]*<<

Testing:

[$output]*

END_PGML_SOLUTION

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

ENDDOCUMENT();

In reply to Carl Yao

Re: Dynamic PGML solution with images

by Michael Gage -
This seems to work -- you do the process the image subroutine outside of PGML. 

I found that I needed spaces after >>  and before   << in order to 
get the centering to work.


$output = qq{

>>[@ image(insertGraph( $gr ), tex_size=>400, height=>400, width=>400,
extra_html_tags=>"alt='$alt1' title= '$alt1'") @]*<<

};
$output2 = image(insertGraph( $gr ), tex_size=>400, height=>400, width=>400,
extra_html_tags=>"alt='$alt1' title= '$alt1'");

then

Testing: 

[$output]*

Test again

>>  [$output2]* <<


In reply to Michael Gage

Re: Dynamic PGML solution with images

by Carl Yao -
Hi Michael:

I must be missing something here. It's still not working on my end:


##############################################
DOCUMENT();

loadMacros(
"PGstandard.pl",
"MathObjects.pl",
"PGML.pl",
"PGgraphmacros.pl",
"PGcourse.pl",
);

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

Context("Numeric");

$gr = init_graph(-1,-1,4,4,
axes=>[0,0],
grid=>[5,5],
size=>[400,400]
);

add_functions($gr, "x^2/4 for x in <-1,4>" .
" using color:blue and weight:2");

$alt1 = "text for accessibility";

$output = qq{

>>[@ image(insertGraph( $gr ), tex_size=>400, height=>400, width=>400,
extra_html_tags=>"alt='$alt1' title= '$alt1'") @]*<<

};


##############################################
TEXT(beginproblem());

BEGIN_PGML

Testing Graph

END_PGML

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

BEGIN_PGML_SOLUTION

Normal graph:

Testing:

[$output]*

END_PGML_SOLUTION



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

ENDDOCUMENT();

In reply to Carl Yao

Re: Dynamic PGML solution with images

by Michael Gage -
$output will continue to fail,  but  $output2 should work.  It does for me.

I cleaned up $output a little bit by using qq{  } for quotes (which avoids 
having to escape the interior quotes).  How ever $output will still fail.

The problem, I think,  is that [$output] is evaluated while parsing the PGML 
section.  That reveals the code  [@  .... @]   but that code is NOT evaluated as PGML code, you would have to run the PGML parser over that text that has been revealed with a second pass.  

Is there are reason why evaluated the image subroutine outside the PGML 
block as with $output2 won't suit your needs?  It is more straightforward and you were already evaluating $output outside the PGML block.  You seem to know all the inputs for the image subroutine as well. 

(I'm writing this during flight stop overs so you may not get a reply to your comments until tomorrow. :-) )
In reply to Michael Gage

Re: Dynamic PGML solution with images

by Carl Yao -
Thank you for your help, Michael!

I'm trying to write a subroutine which produces images based on different math problems' numbers. I want to wrap this subroutine in a macro file, so all related math problems will simply use [$output]** in PGML_SOLUTION block.

Now, in each problem, I have to do something like:

[$output1]**
>> [@ image1 @] <<
[$output2]**
>>[@ image2 @] <<
[$output3]**
...

Thank you, anyway, Michael. Have a nice trip!

Carl Yao
In reply to Carl Yao

Re: Dynamic PGML solution with images

by Davide Cervone -
The problem, here, is that the string you are trying to pass in $output needs to be exactly a string the you would normally enclose with BEGIN_PGML/END_PGML, but you are getting caught by how Perl handles variable substitution within string literals.

In your example

$a = 1;
$test = "[`$a`]";
the $test string will be [`1`] because the value of $a will be inserted into it before it is assigned to $test. So when you then use [$test]** in the PGML block, this will produce a typeset 1, as you desire. Note, however, that it is Perl doing the substitution of $a, not PGML. If you wanted PGML to insert the value of $a, you would need to use
$a = 1;
$test = '[`[$a]`]';
Note the use of ' rather than " as the string literal quotation mark, which prevents variable substitution. Then the value of $test would be [`[$a]`], and when this is inserted into PGML by [$test]**, PGML will first insert the value of $a and then typeset that value.

The output will be the same, but you should note the difference in the timing of when the value of $a is inserted. This difference is important in your second example:

$output = "

>>[@ image(insertGraph( $gr ), tex_size=>400, height=>400, width=>400,
extra_html_tags=>~~"alt= ~~'$alt1~~' title= ~~'$alt1~~'~~") @]*<<

";
Here, the values of all the variables are inserted into the string before it is assigned to $output. That includes the variable $gr. Since $gr is a perl object, inserting it into a string literal causes it to be stringified, and in this case, you get something like WWPlot=HASH(0x7fc5a6b05f60) as the result. So $output becomes
$output = "

>>[@ image(insertGraph( WWPlot=HASH(0x7fc5a6b05f60) ), tex_size=>400, height=>400, width=>400,
extra_html_tags=>"alt= 'text for accessibility' title= 'text for accessibility'") @]*<<

";
When this string is processed by PGML, the command image(insertGraph( WWPlot=HASH(0x7fc5a6b05f60) ),... is executed, but because $gr as been replaced by a string that is nor part of a valid perl command, the command fails, and no output is produced.

One way around this is to use single quotes as above:

$output = '

>>[@ image(insertGraph( $gr ), tex_size=>400, height=>400, width=>400,
extra_html_tags=>"alt= ~~'$alt1~~' title= ~~'$alt1~~'") @]*<<

';
This will mean that $gr is left verbatim in the string, and so when that is eventually used for a command when processed by PGML, it will properly insert the graphic. On the other hand, it also means that the newlines at the beginning and end of the string are removed by Perl, and since these are critical for PGML, that will prevent the centering from being performed properly (the final << will not be processed without the trailing newlines.

In order to retain newlines, you could use a "here document", as in the following:

$output = >[@ image(insertGraph( $gr ), tex_size=>400, height=>400, width=>400,
extra_html_tags=>"alt= '$alt1' title= '$alt1'") @]*<<

END_OUTPUT
This preserves the line breaks (and also prevents variable substitution), so the centering will work properly. On the other hand, it also means that $alt isn't inserted until the command is executed, and if you are constructing $output using local variables within a function, then that could be a problem (since $alt might no longer be available at that point).

So perhaps you want to use a "here document" that allows substitution, but prevent the substitution for $gr:

$output = >[@ image(insertGraph( ~~$gr ), tex_size=>400, height=>400, width=>400,
extra_html_tags=>"alt= '$alt1' title= '$alt1'") @]*<<
~~n~~n
END_OUTPUT
We need to include the newlines explicitly, since otherwise they are removed again with this type of here document.

Finally, if you are constructing the output string programmatically, you might want to build it up piece by piece. For example

$output = "~~n~~n";
$output .= >[@ image(insertGraph( ~~$gr ), tex_size=>400, height=>400, width=>400,
extra_html_tags=>"alt= '$alt1' title= '$alt1'") @]*<<
END_OUTPUT
$output .= "~~n~~n";
and so on as you add the additional lines of text needed.
In reply to Davide Cervone

Re: Dynamic PGML solution with images

by Carl Yao -
Thank you, Davide!

For that problem, we ended up using BEGIN_TEXT and ENG_TEXT, instead of PGML. We will refer to this valuable post next time we handle images.

Carl Yao
Portland Community College