From c3b1a8cd8cd21e30a99cb947341672963a541f8d Mon Sep 17 00:00:00 2001 From: Chris Sangwin Date: Sun, 5 Nov 2023 14:45:38 +0000 Subject: [PATCH 1/3] Code tidy and update the docs. --- corsscripts/stacksortable.js | 4 ++-- doc/en/Developer/Development_track.md | 7 ++++--- doc/en/Topics/Parsons.md | 27 +-------------------------- 3 files changed, 7 insertions(+), 31 deletions(-) diff --git a/corsscripts/stacksortable.js b/corsscripts/stacksortable.js index b1788dbb6f7..eb3f5929b2c 100644 --- a/corsscripts/stacksortable.js +++ b/corsscripts/stacksortable.js @@ -24,10 +24,10 @@ export const stack_sortable = class { } else { this.userOptions = Object.assign(this.defaultOptions, options); }; - // do not allow a user to replace ghostClass or group + // Do not allow a user to replace ghostClass or group. this.options = Object.assign(this.userOptions, {ghostClass: "list-group-item-info", group: "shared"}); } - + generate_available(proofSteps) { for (const key in this.state.available) { let li = document.createElement("li"); diff --git a/doc/en/Developer/Development_track.md b/doc/en/Developer/Development_track.md index 3083a4ca518..2dc29efe565 100644 --- a/doc/en/Developer/Development_track.md +++ b/doc/en/Developer/Development_track.md @@ -41,9 +41,6 @@ Create a working Parson's block A. All functionality to be JSON strings (as in Sam's code) B. Block to accept and produce Maxima proof expressions -1. How can we embed cas content into strings? E.g. `{@plot(x^2,[x,-2,2])@}`. -2. Allow teachers to define strings in the question variables, e.g. `{# stackjson_stringify(proof_steps) #}` - Parson's options 1. use once or re-use strings @@ -52,6 +49,10 @@ Parson's options 4. create templates from the start for different proof types 5. restrict blocks to fixed number of steps +Future work. + +1. Embed plots into strings draggable blocks: e.g. `"{@plot(x^2,[x,-1,1],[size,250,250])@}"`. + Note, this doesn't work, even defining a variable such as `s1:castext("{@plot(x^2,[x,-1,1],[size,250,250])@}");` and using this. TODO: diff --git a/doc/en/Topics/Parsons.md b/doc/en/Topics/Parsons.md index 3b07e68b5d3..8a6a07fbeff 100644 --- a/doc/en/Topics/Parsons.md +++ b/doc/en/Topics/Parsons.md @@ -93,9 +93,7 @@ Then you can set up the potential response tree to be `ATAlgEquiv(sa,ta)` to con # Parson's question with block order options -TODO! To get this following example to work we need to sort out `{# stackjson_stringify(proof_steps) #}` in the Parson's block. - -The following Parson's question is an _if and only if_ proof, containing two blocks in order. +sThe following Parson's question is an _if and only if_ proof, containing two blocks in order. The input is unchanged from the above example. For the question variables use @@ -135,29 +133,6 @@ The complete question text is

[[input:ans1]] [[validation:ans1]]

```` -FOR NOW - -```` -

Let \(n\in\mathbb{N}\). Show that \(n\) is odd if and only if \(n^2\) is odd.

-[[parsons input="ans1"]] -{ - "assodd": "Assume that \\(n\\) is odd.", - "defn_odd": "Then there exists an \\(m\\in\\mathbb{Z}\\) such that \\(n=2m+1\\).", - "alg_odd": "\\[ n^2 = (2m+1)^2 = 2(2m^2+2m)+1.\\]", - "def_M_odd": "Define \\(M=2m^2+2m\\in\\mathbb{Z}\\) then \\(n^2=2M+1\\).", - "conc_odd": "Hence \\(n^2\\) is odd.", - - "contrapos": "We reformulate \"\\(n^2\\) is odd \\(\\Rightarrow \\) \\(n\\) is odd \" as the contrapositive.", - "assnotodd": "Assume that \\(n\\) is not odd.", - "even": "Then \\(n\\) is even, and so there exists an \\(m\\in\\mathbb{Z}\\) such that \\(n=2m\\).", - "alg_even": "\\[ n^2 = (2m)^2 = 2(2m^2).\\]", - "def_M_even": "Define \\(M=2m^2\\in\\mathbb{Z}\\) then \\(n^2=2M\\).", - "conc_even": "Hence \\(n^2\\) is even." -}; -[[/parsons ]] -

[[input:ans1]] [[validation:ans1]]

-```` - Notice the function `stackjson_stringify` turns the variable `proof_steps` into a JSON object. Notice in this example the teacher's proof is nested. This can be seen if we use numerical keys, not string keys and define From b9f6357924900d3bf7fe07b620531770fe335861 Mon Sep 17 00:00:00 2001 From: Chris Sangwin Date: Mon, 6 Nov 2023 04:49:23 +0000 Subject: [PATCH 2/3] Update the docs. --- doc/en/Authoring/Parsons.md | 11 +++++++++++ doc/en/Topics/Parsons.md | 29 ++++++++++++++++++----------- 2 files changed, 29 insertions(+), 11 deletions(-) diff --git a/doc/en/Authoring/Parsons.md b/doc/en/Authoring/Parsons.md index 8dea1c2b63e..38132cb7fb5 100644 --- a/doc/en/Authoring/Parsons.md +++ b/doc/en/Authoring/Parsons.md @@ -110,3 +110,14 @@ Additional display options including `height` and `width` may also be passed to }; [[/parsons]] ```` + +## Adding plots to a Parson's block + +TODO: confirm if we can embed HTML. If so, then the following should work. + +Since HTML can be embedded into strings dragged within a Parson's block, images can be included with the HTML `` tags as normal. + +STACK-generated [plots](../Plots/index.md) cannot be included just using `{@plot(x^2,[x,-1,1])@}` as might be expected. This is because of the _order_ of evaluation. The full URL of the image is only created in the (complex) chain of events after the value has been substituted into the Javascript code. Instead, to embed STACK-generated images evaluate a static string using the Maxima `castext` function, and then use the value of `s1` in the Parson's block. For example. + + s1:castext("{@plot(x^2,[x,-1,1],[size,250,250])@}"); + diff --git a/doc/en/Topics/Parsons.md b/doc/en/Topics/Parsons.md index 8a6a07fbeff..fc8024bf2b3 100644 --- a/doc/en/Topics/Parsons.md +++ b/doc/en/Topics/Parsons.md @@ -36,6 +36,17 @@ Notes The following is a minimal Parson's question where there student is expected to create a list in one and only one order. +## Question variables + +Define the following question variables: + +```` +stack_include("contribl://prooflib.mac"); +ta:proof("assume","defn_rat","defn_rat2","defn_log","defn_log2","alg","alg_int","contra","conc"); +```` + +The optional library `prooflib.mac` contain many useful functions for dealing with student's answers which represent proofs. + ## Question text The example question text below contains a Parson's block. Within the header of the Parson's block, ensure that `input="inputvar"` is included, where `inputvar` is the identifier of the input, for example `input="ans1"` as below. A minimal working example for the proof that _\(\log_2(3)\) is irrational_ is achieved by placing the following in the _Question text_ field: @@ -72,15 +83,6 @@ Notes: ## Potential response tree: prt1 -Define the following question variables: - -```` -stack_include("contribl://prooflib.mac"); -ta:proof("assume","defn_rat","defn_rat2","defn_log","defn_log2","alg","alg_int","contra","conc"); -```` - -The optional library `prooflib.mac` contain many useful functions for dealing with student's answers which represent proofs. - Define the feedback variables: ```` @@ -93,7 +95,7 @@ Then you can set up the potential response tree to be `ATAlgEquiv(sa,ta)` to con # Parson's question with block order options -sThe following Parson's question is an _if and only if_ proof, containing two blocks in order. +The following Parson's question is an _if and only if_ proof, containing two blocks in order. The input is unchanged from the above example. For the question variables use @@ -163,4 +165,9 @@ Notice this proof has two sub-proofs, which can occur in any order. Therefore w
{@ev(tad[2], map(lambda([ex], ex=dispproof_para), proof_types))@}
Can you see the differences between these proofs? -```` \ No newline at end of file +```` + +## Polish and tidy the question. + +You should hide the inputs from students with CSS after testing, e.g. `

...

`. + From 41e2e54ed6708cca94d992445d1b05f1f0324040 Mon Sep 17 00:00:00 2001 From: Chris Sangwin Date: Mon, 6 Nov 2023 04:56:29 +0000 Subject: [PATCH 3/3] Change the "teacher's answer" output of strings to remove quotes and maths environments. Needed for Parson block output, but a general improvement. --- stack/input/string/string.class.php | 4 ++-- stack/utils.class.php | 17 +++++++++++++++++ tests/input_string_test.php | 8 ++------ 3 files changed, 21 insertions(+), 8 deletions(-) diff --git a/stack/input/string/string.class.php b/stack/input/string/string.class.php index 8b6fa6d118f..bed6fc31ea1 100644 --- a/stack/input/string/string.class.php +++ b/stack/input/string/string.class.php @@ -100,8 +100,8 @@ public function get_teacher_answer_display($value, $display) { return ''; } - $value = stack_utils::maxima_string_to_php_string($value); - return stack_string('teacheranswershow', array('value' => ''.$value.'', 'display' => $display)); + $display = stack_utils::maxima_string_strip_mbox($display); + return stack_string('teacheranswershow_disp', array('display' => $display)); } /** diff --git a/stack/utils.class.php b/stack/utils.class.php index 25176af8cfb..de6ead852e7 100644 --- a/stack/utils.class.php +++ b/stack/utils.class.php @@ -781,6 +781,7 @@ public static function php_string_to_maxima_string($string) { $converted = str_replace("\"", "\\\"", $converted); return '"' . $converted . '"'; } + /** * Converts a PHP string object containing a Maxima string as presented by the grind command to a PHP string object. * @param a string that contains ""-quotes around the content. @@ -792,6 +793,22 @@ public static function maxima_string_to_php_string($string) { return substr($converted, 1, -1); } + /** + * Remove redundant "mbox" environments from Latex equations strings containing just strings. + * @param a string that contains ""-quotes around the content. + * @return a string without those quotes. + */ + public static function maxima_string_strip_mbox($string) { + $converted = trim($string); + if (substr($converted, 0, 2) == '\(' || substr($converted, 0, 2) == '\[') { + $converted = substr($converted, 2, -2); + } + if (substr(trim($converted), 0, 6) == '\mbox{') { + return substr(trim($converted), 6, -1); + } + return $string; + } + /** * Translate some strings from Maxima. * @param string $string diff --git a/tests/input_string_test.php b/tests/input_string_test.php index 8c0ce1b8562..216da9777f2 100644 --- a/tests/input_string_test.php +++ b/tests/input_string_test.php @@ -57,9 +57,7 @@ public function test_render_hello_world() { .'style="width: 13.6em" autocapitalize="none" spellcheck="false" class="maxima-string" value="0" />', $el->render(new stack_input_state(stack_input::VALID, array('0'), '', '', '', '', ''), 'stack1__ans1', false, null)); - $this->assertEquals('The answer ' . - '\( \\mbox{Hello world} \), which can be typed as Hello world, ' . - 'would be correct.', + $this->assertEquals('The answer Hello world would be correct.', $el->get_teacher_answer_display('"Hello world"', '\\mbox{Hello world}')); } @@ -72,9 +70,7 @@ public function test_validate_string_input() { $this->assertEquals(stack_input::VALID, $state->status); $this->assertEquals('"Hello world"', $state->contentsmodified); $this->assertEquals('\[ \mbox{Hello world} \]', $state->contentsdisplayed); - $this->assertEquals('The answer ' . - '\[ \[ \mbox{Hello world} \] \), ' . - 'which can be typed as Hello world, would be correct.', + $this->assertEquals('The answer Hello world would be correct.', $el->get_teacher_answer_display($state->contentsmodified, $state->contentsdisplayed)); }