Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added SageCell Macros #143

Open
wants to merge 15 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 32 additions & 1 deletion assessment/libs/sagecell.html
Original file line number Diff line number Diff line change
@@ -1,7 +1,38 @@
<html><body>
<h1>Macro Library sagecell</h1>
<p>Sagecell integration documentation, Version 1.0, Jan 2018</p>
<p>Sagecell integration documentation, Version 2.0, Mar 2019</p>
<ol>
<li><a href="#qc">Integration via Macros in Question Common Control</a></li>
<li><a href="#qt">Integration via JavaScript in Question Text</a></li>
</ol>
<h2 id="qc">Integration via Macros in Question Common Control</h2>
<p>
This library provides functions to create SageCells and transfer their output into answerboxes. To use the library in a question, make sure to call
</p>
<pre>loadlibrary("sagecell1");</pre>
<p>
before calling the functions.
</p>

<ul>
<li><a href="#sagecell">sagecell</a></li>
<li><a href="#sagecellTransfer">sagecellTransfer</a></li>
</ul>
<h3><a name="sagecell">sagecell</a></h3>
<p>
<i>sagecell(script)</i> generates a SageCell with content <i>script</i>.
<p>
Usage example: <i>$s=sagecell("1+1")</i>, place $s in question text
</p>
<h3><a name="sagecellTransfer">sagecellTransfer</a></h3>
<p>
<i>sagecellTransfer(script,questionNr,[label,partNr])</i> generates a SageCell with content <i>script</i> and a button with <i>label</i> (default: "Transfer"). Clicking the button transfers the content of the SageCell output into the answerbox. For multipart questions, <i>partNr</i> determines the index of the target answerbox.
</p>
<p>
Usage example: <i>$s = sagecellTransfer("1+1",$thisq,"Use as Answer to Part 2",1)</i>, place $s in question text.
</p>

<h2 id="qt">Integration via HTML in Question Text</h2>
<p>There is not need to actually load this macro library. This documentation
describes how to set up your HTML to enable SageCell integration.</p>

Expand Down
54 changes: 52 additions & 2 deletions assessment/libs/sagecell.php
Original file line number Diff line number Diff line change
@@ -1,3 +1,53 @@
<?php
//does nothing
?>
//SageCell extension

global $allowedmacros;
array_push($allowedmacros,"sagecell", "sagecellEssay", "sagecellTransfer", "sagecellEssayTransfer");

function sagecell($script) {
return "<pre class='converttosagecell'>".$script."</pre>";
}

function sagecellEssay($script,$essayPart=-1) {
$ansPart = $essayPart < 0 ? '$answerbox' : '$answerbox['.$essayPart.']';
return '<div class="converttosagecell">'."$ansPart".'<pre class="hidden">'.$script.'</pre></div>';
}

function sagecellTransfer($script,$q,$label="Transfer",$part=-1) {
if ($part < 0) {
$ref=$q-1;
} else {
$ref=$q*1000+$part;
}
$fns="<script>function getSageOutput_$ref (el) {
var iframe=$(el).closest('.sagetransfer').find('.sagecellframe')[0];
var output=iframe.contentWindow.document.getElementsByClassName('sagecell_sessionOutput');
if (output.length) {
$('input[id=\'tc$ref\'],input[id=\'qn$ref\'').val(output[0].textContent);
} else {
alert('Please evaluate cell first');
}
}
</script>";
$btn="<input type='button' value='$label' onClick='getSageOutput_$ref(this)'>";

return "<div class='sagetransfer'>".sagecell($script).$fns.$btn."</div>";
}

function sagecellEssayTransfer($script,$q,$essayPart,$part,$label="Transfer") {
$ref=$q*1000+$part;
$fns="<script>function getSageOutput_$ref (el) {
var iframe=$(el).closest('.sagetransfer').find('.sagecellframe')[0];
var output=iframe.contentWindow.document.getElementsByClassName('sagecell_sessionOutput');
if (output.length) {
$('input[id=\'tc$ref\'],input[id=\'qn$ref\'').val(output[0].textContent);
} else {
alert('Please evaluate cell first');
}
}
</script>";
$btn="<input type='button' value='$label' onClick='getSageOutput_$ref(this)'>";

return "<div class='sagetransfer'>".sagecellEssay($script,$essayPart).$fns.$btn."</div>";
}
?>
172 changes: 172 additions & 0 deletions assessment/libs/sagecell_vcrp.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,172 @@
<html>
<body>
<h1>Macro Library sagecell_vcrp</h1>
<p>Sagecell integration documentation, Version 3.0, June 2019</p>

<p>
This library provides functions to create SageCells and transfer their
output into answerboxes. To use the library in a question, make sure to
call
</p>
<pre>loadlibrary("sagecell_vcrp");</pre>
<p>
before calling the functions.
</p>

<ul>
<li><a href="#sagecell">sagecell</a></li>
<li><a href="#sagecellButton">sagecellButton</a></li>
<br />
<li><a href="#UseCases">Use Cases</a></li>
</ul>

<h3 id="sagecell">sagecell</h3>
<p>
<code>sagecell([script,thisq,essayPart,sageName])</code> generates code
for a SageCell with content <code>script</code> which can be used in
<code>Question Text</code>.
</p>
<p>
If the output produced by sage is to be reused as an answer,
<code>thisq</code> must be instantiated with <code>$thisq</code>.
</p>
<p>
If the SageCell script edited by the student is to be inspected, it can be
saved as an answer to a question (part) of type <code>essay</code>. If the
script is the only expected answer, the question must be of type
<code>essay</code> and the parameter <code>essayPart</code> must be
instantiated with <code>"essay"</code>. If the question is of type
<code>multipart</code> or <code>conditional</code>,
<code>essayPart</code> must be instantiated with the number <i>n</i> of
the <code>essay</code> part to be used for saving the script. Do not put
<code>$answerbox[n]</code> into the question text.
</p>
<p>
If the script is not to be saved, <code>essayPart</code> should be
instantiated with <code>"none"</code>, which is also it's default value.
</p>
<p>
If the question uses more than one SageCells the output of which needs to
be accessed, they may be distinguished by the value of the parameter
<code>sageName</code>.
</p>

<h3 id="sagecellButton">sagecellButton</h3>
<p>
<code>sagecellButton([label, part, format, sageName])</code>
generates code for a button to transfer SageCell output into an answerbox.
This code can be used in <code>Question Text</code>.
</p>
<p>
The parameter <code>label</code> can be used to specify the text to be
shown on the button. In questions of type <code>multipart</code> or
<code>conditional</code>, the argument <code>part</code> must specify the
number <i>n</i> if a click on the button is to transfer the output of the
SageCell into <code>$answerbox[n]</code>. If the question doesn't have
parts, use <code>"none"</code> as value for <code>part</code>, which is
also the default.
</p>
<p>
If the output is to be interpreted as a list or matrix, set
<code>format</code> to <code>'list'</code> or
<code>'matrix'</code> respectively. For matrix questions
<code>$answersize</code> must not be set in the question control code.
<b>Note:</b> Applying the <code>matrix</code> format to non-nmeric
matrices may yield weird results. In case of doubt use format
<code>'any'</code> instead to let the student adapt the matrix syntax.
</p>
<p>
If the question uses more than one SageCells the output of which needs to
be accessed, they may be distinguished by the value of the parameter
<code>sageName</code>.
</p>

<h3 id="UseCases">Use Cases</h3>
<h4>Just adding a SageCell</h4>

<dl>
<dt>In Question Control:</dt>
<dd><code>$cell=sagecell()</code></dd>
<dt>In Question Text:</dt>
<dd><code>$cell</code></dd>
</dl>

<h4>Adding a SageCell with Script</h4>
<dl>
<dt>In Question Control:</dt>
<dd>
<code>
$script="x=var(x)<br />
integral(sin(x),x)<br />
"<br />
$cell = sagecell($script)
</code>
</dd>
<dt>In Question Text:</dt>
<dd><code>$cell</code></dd>
</dl>

<h4>
Adding a SageCell and Button to Transfer SageCell Output (single part
question)
</h4>
<dl>
<dt>In Question Control:</dt>
<dd>
<code>
$cell = sagecell("",$thisq)<br />
$button=sagecellButton()
</code>
</dd>
<dt>In Question Text:</dt>
<dd>
<code>
$cell<br />
$button $answerbox
</code>
</dd>
</dl>

<h4>
Adding a SageCell and Button to Transfer SageCell Output (multipart
question)
</h4>
<dl>
<dt>In Question Control:</dt>
<dd>
<code>
$cell = sagecell("",$thisq)<br />
$button=sagecellButton("Get Answer to Part 3",2)
</code>
</dd>
<dt>In Question Text:</dt>
<dd>
<code>
$cell<br />
$button $answerbox[2]
</code>
</dd>
</dl>

<h4>
Getting a Numerical Matrix as Answer from Sage and Saving the Sage Script
in Part 0
</h4>
<dl>
<dt>In Question Control:</dt>
<dd>
<code>
$cell = sagecell("",$thisq,0)<br />
$button=sagecellButton("Get Answer to Part 2",2,"matrix")
</code>
</dd>
<dt>In Question Text:</dt>
<dd>
<code>
$cell<br />
$button $answerbox[2]
</code>
</dd>
</dl>
</body>
</html>
60 changes: 60 additions & 0 deletions assessment/libs/sagecell_vcrp.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
<?php
//SageCell extension

global $allowedmacros;
array_push($allowedmacros,"sagecell", "sagecellButton" );

function sagecell($script="",$q=0,$essayPart="none",$id="sagecell") {
$cid='sagecell_vcrp_'.$id;
$fns="<script>function getSageOutput_$id (part=-1,format='any') {
var ref=$q-1;
if (part >= 0)
ref=$q*1000+part;
var iframe=$(\"#\"+'$cid').find('.sagecellframe')[0];
var output=iframe.contentWindow.document.getElementsByClassName('sagecell_sessionOutput');
if (output.length) {
var sageOutput=output[0].textContent;
if (format == 'list') {
var start=sageOutput.indexOf('[');
var end=sageOutput.lastIndexOf(']');
if (start > -1 && end > -1)
sageOutput=sageOutput.substring(start+1,end);
}
if (format == 'matrix') {
sageOutput=sageOutput.replace(/ /g,',');
sageOutput=sageOutput.replace(/\[/g,'(');
sageOutput=sageOutput.replace(/\]/g,')');
sageOutput=sageOutput.replace(/\)\s*\(/g,'),(');
sageOutput='['+sageOutput+']';
}
$('input[id=\'tc'+ref+'\'],input[id=\'qn'+ref+'\']').val(sageOutput);
} else {
alert('Please evaluate cell');
}
}
</script>";
if ($essayPart === 'none') {
return "<div id='$cid' class='sagetransfer'><pre class='converttosagecell'>".$script."</pre>".$fns."</div>";
} else {
$ansPart = ($essayPart === "essay" ? '[AB]' : '[AB'.strval($essayPart).']');

return "<div id='$cid' class='sagetransfer'><div class='converttosagecell'>$ansPart<pre class='hidden'>$script</pre></div>$fns</div>";
}

}

function sagecellButton($label="Transfer",$part="none",$format='any',$id="sagecell") {
switch (strval($part)) {
case "none":
$parts=-1;
break;
case "essay":
$parts=-2;
break;
default:
$parts=$part;
}
return "<input type='button' value='$label' onClick='getSageOutput_$id($parts,\"$format\")'>";
}

?>
Loading