WeBWorK Problems

Embedding a Desmos Graph in a Table

Embedding a Desmos Graph in a Table

by Eric Gilson -
Number of replies: 4
Today I was playing around with the Desmos API to embed their graphs in a problem. I can get the graph embedded and interacting with data generated by WebWork. The problem is to embed the graph I am using a <div> tag in my problem's code. This causes the columnTable() function to crash when I have the <div> tag embedded graph as one of the columns. Hence, I am a little stuck as to what else to try as I haven't been writing WebWork problems for that long. Is there another way to format text that I am missing or possibly another way to embed the Desmos graph? I know that I can use GeoGebra, but think that for simple graphs Desmos is quicker use. My code is below. It works as a .pg file, but the columnTable() function does not format at all.


DOCUMENT();

HEADER_TEXT(<<EOF);
<script src="https://www.desmos.com/api/v0.4/calculator.js?apiKey=dcb31709b452b1cf9dc26972add0fda6"></script>
EOF

loadMacros(
"PGstandard.pl",
"MathObjects.pl",
"AnswerFormatHelp.pl",
"PGgraphmacros.pl",
"unionTables.pl",
);
Context("Numeric");

TEXT(beginproblem());

$showPartialCorrectAnswers = 1;

$m=random(1,5,1);
$b=random(-5,5,1);

$f=Formula("$m*x+$b");

Context()->texStrings;

BEGIN_TEXT
\{
ColumnTable(
"What is the equation for the line in the graph above?".
$BR.
"\(y=\)".
ans_rule(7)
,
"This is a graph!".
<div id="calculator" style="width: 300px; height: 300px;"></div>
,
indent => 0, separation => 30, valign => "TOP"
)
\}
END_TEXT

ANS($f->cmp() );

TEXT( MODES(TeX=>'', HTML=><<END_SCRIPT ) );
<script>
<!-- //
var elt = document.getElementById('calculator');
var calculator = Desmos.Calculator(elt, {keypad: false, expressions: false, settingsMenu: false, expressionsTopbar: false});
calculator.setExpression({id:'graph1', latex:'y=$f'});
// -->
</script>
END_SCRIPT

ENDDOCUMENT();

In reply to Eric Gilson

Re: Embedding a Desmos Graph in a Table

by Eric Gilson -
I figured out my, embarrassing, mistake. I needed to use single quotes as escape characters to surround my div tag:
'<div id="calculator" style="width: 300px; height: 300px;"></div>'
Not fully sure why that worked, as I am still new at developing WebWork problems.

Also, I am still interested in other ways to insert a Desmos graph as my method seems a bit kludgy. It seems like there should be a way using the WebWork Applet functionality, but I don't quite have the know-how to put it together.
In reply to Eric Gilson

Re: Embedding a Desmos Graph in a Table

by Paul Pearson -
Hi Eric,

In order to get your example to work, I needed to generate a string object $fstring = $f->string; from the MathObject $f and then pass $fstring to the Desmos grapher via the API.  From the Desmos API documentation, it looks like Desmos wants things formatted like "b \\sin(x + a)", which means that in order to get things to work in webwork, the $fstring object might need to be coded manually or be generated by $f->TeX and processed further by regular expression substitution.

The webwork AppletObjects should help with the persistence of state of the Desmos graph, but for such a simple example as this I'm not sure it's worth the hassle.  (Here's an example of what I mean by persistence of state: if the student zooms in on the graph and then clicks submit answers so that webwork delivers them a new html page, the graph will still be zoomed in if there is persistence of state and it will be back to the default settings without persistence of state.)

When you write problems like this, you need to be aware that webwork delivers homework in two modes: html and pdf hardcopy.  Often, people forget to make the pdf hardcopy usable (i.e., bug free and a complete version of the problem that can be done offline).  The example below does the bare minimum to address the pdf hardcopy mode: it refers the student to the online version.  Ideally, the pdf hardcopy mode would have the same graph as the html mode does.

I used TEXT() instead of HEADER_TEXT() for loading the Desmos script so that the graph will appear when the problem is rendered in the webwork Library Browser.

Best regards,

Paul Pearson

###############################
#  Initialization

DOCUMENT();

loadMacros(
"PGstandard.pl",
"MathObjects.pl",
"AnswerFormatHelp.pl",
"unionTables.pl",
);

TEXT(beginproblem());
$showPartialCorrectAnswers = 1;


################################
#  Desmos setup
#
#  In html mode, load the Desmos api script and create the <div> to attach the Desmos graph to.
#  In tex mode, print a message to direct the student to the html version.
#  Desmos API reference: https://www.desmos.com/api/v0.6/docs/index.html

TEXT(MODES(HTML=>'<script src="https://www.desmos.com/api/v0.4/calculator.js?apiKey=dcb31709b452b1cf9dc26972add0fda6"></script>',TeX=>''));
$desmos_div = MODES(HTML=>'<div id="calculator" style="width: 400px; height: 400px;"></div>',TeX=>'Interactive graph best viewed online');


################################
#  Setup

Context("Numeric");

$m = non_zero_random(1,5,1);
$b = non_zero_random(-5,5,1);

$f=Formula("$m*x+$b");
$fstring = $f->string; # needed later by Desmos


################################
#  Main text

Context()->texStrings;
BEGIN_TEXT
\{
ColumnTable(
"What is an equation for the line in the graph?".
$PAR.
"\(y=\)". 
ans_rule(7).$SPACE.
AnswerFormatHelp("formulas")
,
$desmos_div.
$BR.
$BCENTER.
"The graph of a line".
$ECENTER
,
indent => 0, separation => 30, valign => "TOP"
)
\}
END_TEXT
Context()->normalStrings;

ANS($f->cmp);

##################################
#  Desmos graph (via the API)
#  Execute this only after the $desmos_div object has been put on the html page.

TEXT( MODES(TeX=>'', HTML=><<END_SCRIPT ) );
<script>
<!-- //
var elt = document.getElementById('calculator');
var calculator = Desmos.Calculator(elt, {keypad: false, expressions: false, settingsMenu: false, expressionsTopbar: false});
calculator.setExpression({id:'graph1', latex:"y=$fstring"});
// -->
</script>
END_SCRIPT

COMMENT('MathObject version.  Uses Desmos interactive JavaScript graphing which should work on all devices in html mode.');

ENDDOCUMENT();

In reply to Paul Pearson

Re: Embedding a Desmos Graph in a Table

by Paul Pearson -
Hi Eric,

One more thing that I noticed: you should use version v0.6 of the Desmos API (not v0.4) since there are more features.  Include

<script src="https://www.desmos.com/api/v0.6/calculator.js?apiKey=dcb31709b452b1cf9dc26972add0fda6"></script>

in your PG source code instead, and use the Desmos documentation at

https://www.desmos.com/api/v0.6/docs/index.html

Also, you should probably look into requesting an API Key (see bottom the bottom of the Desmos documentation) before putting problems into production.

Best regards,

Paul Pearson
In reply to Paul Pearson

Re: Embedding a Desmos Graph in a Table

by Eric Gilson -
Paul thank you for the detailed reply! I am a bit new to creating problems in WebWork and still fumbling my way around.

You are right that this particular example does not need any persistence. This is a first proof of concept test to see how inserting Desmos graphs into WebWork works. There are definitely more complicated examples that could use a persistent state. For example, a problem where the student is give 3 points and asked to find the equation of the quadratic that passes through those points could use Desmos as a workspace and answerbox, allowing the student to see how their proposed solution compares to the points they are given. Persistence would enable the student to come back later if they get stuck and see equations they had tried. Although I am probably going to use Desmos heavily for simple problems, like this one, that just need a graph because it is easy to setup Desmos and the zoom & tracing features are really nice for students.

It is interesting that you needed to covert to a string for Desmos to like your example. Mine works fine with the formula. Could the quotes around what is being passed make the difference? Your code looks like "y=$fstring" while mine is 'y=$f' with just single quotes.

You are right about the PDF hardcopy. I haven't looked into what I need to do for that.

Also, thanks for catching that I was using the 0.4 API. For some reason that came up first in my search and I just never switched the problem when I found the updated API.