Skip to content

Commit

Permalink
Functions inside functions are reevaluated (Doenet#2002)
Browse files Browse the repository at this point in the history
* evaluate_to_constant return NaN for non-numeric
* Functions default to symbolic
* Functions default to simplify
* function simplify/expand do not affect formula
  • Loading branch information
dqnykamp authored Apr 4, 2023
1 parent ed43229 commit bd04a17
Show file tree
Hide file tree
Showing 53 changed files with 3,953 additions and 749 deletions.
1,770 changes: 1,702 additions & 68 deletions cypress/e2e/DoenetML/tagSpecific/evaluate.cy.js

Large diffs are not rendered by default.

24 changes: 12 additions & 12 deletions cypress/e2e/DoenetML/tagSpecific/function.cy.js
Original file line number Diff line number Diff line change
Expand Up @@ -5007,16 +5007,16 @@ describe('Function Tag Tests', function () {
});
});

it('function of function can redefine variable', () => {
it('function of function formula can redefine variable', () => {
cy.window().then(async (win) => {
win.postMessage({
doenetML: `
<text>a</text>
<function variables="t" name="f" symbolic>st^3</function>
<function variables="t" name="f" symbolic simplify="false">st^3</function>
<function name="f2" symbolic><copy target="f"/></function>
<function name="f3" variables="s" symbolic><copy target="f"/></function>
<function name="f2" symbolic simplify="false"><copy target="f"/></function>
<function name="f3" variables="s" symbolic simplify="false"><copy target="f.formula"/></function>
<copy assignNames="f4" target="f"/>
<copy assignNames="f5" target="f2"/>
Expand Down Expand Up @@ -5981,10 +5981,10 @@ describe('Function Tag Tests', function () {
win.postMessage({
doenetML: `
<text>a</text>
<function name="f1">x^2</function>
<function name="f1" symbolic="false">x^2</function>
<copy target="f1" symbolic assignNames="f2" />
<copy target="f2" symbolic="false" assignNames="f3" />
<function name="g1" symbolic>x^2</function>
<function name="g1">x^2</function>
<copy target="g1" symbolic="false" assignNames="g2" />
<copy target="g2" symbolic assignNames="g3" />
Expand Down Expand Up @@ -6053,7 +6053,7 @@ describe('Function Tag Tests', function () {
win.postMessage({
doenetML: `
<text>a</text>
<function name="f1" symbolic>xyz</function>
<function name="f1" symbolic simplify="none">xyz</function>
<copy target="f1" variables="x y" assignNames="f2" />
<copy target="f2" variables="x y z" assignNames="f3" />
<copy target="f3" variables="z y" assignNames="f4" />
Expand Down Expand Up @@ -6361,11 +6361,11 @@ describe('Function Tag Tests', function () {
doenetML: `
<text>a</text>
<function name="f1">255.029847 sin(0.52952342x) + 3</function>
<function name="f2" displayDigits="3"> 255.029847 sin(0.52952342x) + 3</function>
<function name="f3" displayDigits="3" padZeros> 255.029847 sin(0.52952342x) + 3</function>
<function name="f4" displayDecimals="3"> 255.029847 sin(0.52952342x) + 3</function>
<function name="f5" displayDecimals="3" padZeros> 255.029847 sin(0.52952342x) + 3</function>
<function name="f1" simplify="none">255.029847 sin(0.52952342x) + 3</function>
<function name="f2" simplify="none" displayDigits="3"> 255.029847 sin(0.52952342x) + 3</function>
<function name="f3" simplify="none" displayDigits="3" padZeros> 255.029847 sin(0.52952342x) + 3</function>
<function name="f4" simplify="none" displayDecimals="3"> 255.029847 sin(0.52952342x) + 3</function>
<function name="f5" simplify="none" displayDecimals="3" padZeros> 255.029847 sin(0.52952342x) + 3</function>
<copy target="f1" assignNames="f1a" />
<copy target="f2" assignNames="f2a" />
Expand Down
4 changes: 2 additions & 2 deletions cypress/e2e/DoenetML/tagSpecific/functioniterates.cy.js
Original file line number Diff line number Diff line change
Expand Up @@ -173,7 +173,7 @@ describe('FunctionIterates Tag Tests', function () {
</map>
</ul>
<p hide><function name="f" variables="$x">$fformula</function><functioniterates function="$f" initialValue="$u" nIterates="$n" name="fis" /><copy prop="iterates" target="fis" name="iterates" /></p>
<p hide><function name="f" variables="$x" symbolic="false">$fformula</function><functioniterates function="$f" initialValue="$u" nIterates="$n" name="fis" /><copy prop="iterates" target="fis" name="iterates" /></p>
`}, "*");
Expand Down Expand Up @@ -563,7 +563,7 @@ describe('FunctionIterates Tag Tests', function () {
<p>Iterates: <aslist><copy prop="iterates" target="fis" name="iterates" /></aslist></p>
<p hide><mathlist mergeMathLists name="varList">$vars</mathlist><function name="f" variables="$varList">$fformula</function><functioniterates function="$f" initialValue="$u" nIterates="3" name="fis" /></p>
<p hide><mathlist mergeMathLists name="varList">$vars</mathlist><function name="f" variables="$varList" symbolic="false">$fformula</function><functioniterates function="$f" initialValue="$u" nIterates="3" name="fis" /></p>
<copy prop="value" target="u" assignNames="u2" />
<copy prop="value" target="fformula" assignNames="fformula2" />
<copy prop="value" target="vars" assignNames="vars2" />
Expand Down
293 changes: 284 additions & 9 deletions cypress/e2e/DoenetML/tagSpecific/functionoperators.cy.js

Large diffs are not rendered by default.

41 changes: 41 additions & 0 deletions cypress/e2e/DoenetML/tagSpecific/image.cy.js
Original file line number Diff line number Diff line change
Expand Up @@ -538,6 +538,47 @@ describe('Image Tag Tests', function () {

});

it('image in graph, handle bad anchor coordinates', () => {
cy.window().then(async (win) => {
win.postMessage({
doenetML: `
<text>a</text>
<graph >
<image source="http://mathinsight.org/media/image/image/giant_anteater.jpg" anchor="$anchorCoords1" name="image1" />
</graph>
<p name="pAnchor1">Anchor 1 coordinates: $image1.anchor</p>
<p name="pChangeAnchor1">Change anchor 1 coordinates: <mathinput name="anchorCoords1" prefill="x" /></p>
`}, "*");
});

cy.get('#\\/_text1').should('have.text', 'a') //wait for page to load

cy.get('#\\/pAnchor1 .mjx-mrow').eq(0).should('have.text', 'x')


cy.log("give good anchor coords")

cy.get('#\\/anchorCoords1 textarea').type("{home}{shift+end}{backspace}(6,7){enter}", { force: true })

cy.get('#\\/pAnchor1 .mjx-mrow').should('contain.text', '(6,7)')

cy.get('#\\/pAnchor1 .mjx-mrow').eq(0).should('have.text', '(6,7)')

cy.log("give bad anchor coords again")

cy.get('#\\/anchorCoords1 textarea').type("{home}{shift+end}{backspace}q{enter}", { force: true })

cy.get('#\\/pAnchor1 .mjx-mrow').should('contain.text', 'q')

cy.get('#\\/pAnchor1 .mjx-mrow').eq(0).should('have.text', 'q')


});
})


Expand Down
41 changes: 41 additions & 0 deletions cypress/e2e/DoenetML/tagSpecific/label.cy.js
Original file line number Diff line number Diff line change
Expand Up @@ -298,5 +298,46 @@ describe('Label Tag Tests', function () {

})

it('label in graph, handle bad anchor coordinates', () => {
cy.window().then(async (win) => {
win.postMessage({
doenetML: `
<text>a</text>
<graph >
<label anchor="$anchorCoords1" name="label1">Hello</label>
</graph>
<p name="pAnchor1">Anchor 1 coordinates: $label1.anchor</p>
<p name="pChangeAnchor1">Change anchor 1 coordinates: <mathinput name="anchorCoords1" prefill="x" /></p>
`}, "*");
});

cy.get('#\\/_text1').should('have.text', 'a') //wait for page to load

cy.get('#\\/pAnchor1 .mjx-mrow').eq(0).should('have.text', 'x')


cy.log("give good anchor coords")

cy.get('#\\/anchorCoords1 textarea').type("{home}{shift+end}{backspace}(6,7){enter}", { force: true })

cy.get('#\\/pAnchor1 .mjx-mrow').should('contain.text', '(6,7)')

cy.get('#\\/pAnchor1 .mjx-mrow').eq(0).should('have.text', '(6,7)')

cy.log("give bad anchor coords again")

cy.get('#\\/anchorCoords1 textarea').type("{home}{shift+end}{backspace}q{enter}", { force: true })

cy.get('#\\/pAnchor1 .mjx-mrow').should('contain.text', 'q')

cy.get('#\\/pAnchor1 .mjx-mrow').eq(0).should('have.text', 'q')


});

});
42 changes: 42 additions & 0 deletions cypress/e2e/DoenetML/tagSpecific/math.cy.js
Original file line number Diff line number Diff line change
Expand Up @@ -5693,6 +5693,48 @@ describe('Math Tag Tests', function () {

})

it('math in graph, handle bad anchor coordinates', () => {
cy.window().then(async (win) => {
win.postMessage({
doenetML: `
<text>a</text>
<graph >
<math anchor="$anchorCoords1" name="math1">x^2</math>
</graph>
<p name="pAnchor1">Anchor 1 coordinates: $math1.anchor</p>
<p name="pChangeAnchor1">Change anchor 1 coordinates: <mathinput name="anchorCoords1" prefill="x" /></p>
`}, "*");
});

cy.get('#\\/_text1').should('have.text', 'a') //wait for page to load

cy.get('#\\/pAnchor1 .mjx-mrow').eq(0).should('have.text', 'x')


cy.log("give good anchor coords")

cy.get('#\\/anchorCoords1 textarea').type("{home}{shift+end}{backspace}(6,7){enter}", { force: true })

cy.get('#\\/pAnchor1 .mjx-mrow').should('contain.text', '(6,7)')

cy.get('#\\/pAnchor1 .mjx-mrow').eq(0).should('have.text', '(6,7)')

cy.log("give bad anchor coords again")

cy.get('#\\/anchorCoords1 textarea').type("{home}{shift+end}{backspace}q{enter}", { force: true })

cy.get('#\\/pAnchor1 .mjx-mrow').should('contain.text', 'q')

cy.get('#\\/pAnchor1 .mjx-mrow').eq(0).should('have.text', 'q')


});

it('vec', () => {
cy.window().then(async (win) => {
win.postMessage({
Expand Down
42 changes: 42 additions & 0 deletions cypress/e2e/DoenetML/tagSpecific/mathdisplay.cy.js
Original file line number Diff line number Diff line change
Expand Up @@ -1129,6 +1129,48 @@ describe('Math Display Tag Tests', function () {

})

it('m in graph, handle bad anchor coordinates', () => {
cy.window().then(async (win) => {
win.postMessage({
doenetML: `
<text>a</text>
<graph >
<m anchor="$anchorCoords1" name="m1">x^2</m>
</graph>
<p name="pAnchor1">Anchor 1 coordinates: $m1.anchor</p>
<p name="pChangeAnchor1">Change anchor 1 coordinates: <mathinput name="anchorCoords1" prefill="x" /></p>
`}, "*");
});

cy.get('#\\/_text1').should('have.text', 'a') //wait for page to load

cy.get('#\\/pAnchor1 .mjx-mrow').eq(0).should('have.text', 'x')


cy.log("give good anchor coords")

cy.get('#\\/anchorCoords1 textarea').type("{home}{shift+end}{backspace}(6,7){enter}", { force: true })

cy.get('#\\/pAnchor1 .mjx-mrow').should('contain.text', '(6,7)')

cy.get('#\\/pAnchor1 .mjx-mrow').eq(0).should('have.text', '(6,7)')

cy.log("give bad anchor coords again")

cy.get('#\\/anchorCoords1 textarea').type("{home}{shift+end}{backspace}q{enter}", { force: true })

cy.get('#\\/pAnchor1 .mjx-mrow').should('contain.text', 'q')

cy.get('#\\/pAnchor1 .mjx-mrow').eq(0).should('have.text', 'q')


});

it('me in graph', () => {
cy.window().then(async (win) => {
win.postMessage({
Expand Down
2 changes: 1 addition & 1 deletion cypress/e2e/DoenetML/tagSpecific/mathoperators.cy.js
Original file line number Diff line number Diff line change
Expand Up @@ -6792,7 +6792,7 @@ describe('Math Operator Tag Tests', function () {
win.postMessage({
doenetML: `
<text>a</text>
<function name="f" domain="[0,2]">(x+1)(x-2)(x-4)</function>
<function name="f" domain="[0,2]" simplify>(x+1)(x-2)(x-4)</function>
<p>Min on [0,2]: <min name="min02">$$f(0) $(f.minimumValues) $$f(2)</min>.</p>
<p>Abs treats as product of three factors: <abs name="abs">$$f(0) $(f.minimumValues) $$f(2)</abs>.</p>
`}, "*");
Expand Down
4 changes: 2 additions & 2 deletions cypress/e2e/DoenetML/tagSpecific/piecewisefunction.cy.js
Original file line number Diff line number Diff line change
Expand Up @@ -740,12 +740,12 @@ describe('Piecewise Function Tag Tests', function () {

});

it.only('ignore function pieces with non-numerical domain when evaluating numerically', () => {
it('ignore function pieces with non-numerical domain when evaluating numerically', () => {
cy.window().then(async (win) => {
win.postMessage({
doenetML: `
<graph>
<piecewisefunction name="f">
<piecewisefunction name="f" symbolic="false">
<function domain="(s,t)">x</function>
<function domain="[1,q)">x^2/10</function>
<function domain="(z,5)">x^3/100</function>
Expand Down
40 changes: 20 additions & 20 deletions cypress/e2e/DoenetML/tagSpecific/selectfromsequence.cy.js
Original file line number Diff line number Diff line change
Expand Up @@ -548,11 +548,11 @@ describe('SelectFromSequence Tag Tests', function () {
cy.get('#\\/_text1').should('have.text', 'a')

let allowedCombinations = [
[1,2,2], [1,2,3], [1,3,2], [1,3,3],
[2,1,2], [2,1,3], [3,1,2], [3,1,3],
[2,2,1], [2,3,1], [3,2,1], [3,3,1],
[2,2,2], [2,2,3], [2,3,2], [3,2,2],
[3,3,2], [3,2,3], [2,3,3], [3,3,3]
[1, 2, 2], [1, 2, 3], [1, 3, 2], [1, 3, 3],
[2, 1, 2], [2, 1, 3], [3, 1, 2], [3, 1, 3],
[2, 2, 1], [2, 3, 1], [3, 2, 1], [3, 3, 1],
[2, 2, 2], [2, 2, 3], [2, 3, 2], [3, 2, 2],
[3, 3, 2], [3, 2, 3], [2, 3, 3], [3, 3, 3]
];
cy.window().then(async (win) => {
let stateVariables = await win.returnAllStateVariables1();
Expand Down Expand Up @@ -598,11 +598,11 @@ describe('SelectFromSequence Tag Tests', function () {
cy.get('#\\/_text1').should('have.text', 'a')

let allowedCombinations = [
[1,2,2], [1,2,3], [1,3,2], [1,3,3],
[2,1,2], [2,1,3], [3,1,2], [3,1,3],
[2,2,1], [2,3,1], [3,2,1], [3,3,1],
[2,2,2], [2,2,3], [2,3,2], [3,2,2],
[3,3,2], [3,2,3], [2,3,3], [3,3,3]
[1, 2, 2], [1, 2, 3], [1, 3, 2], [1, 3, 3],
[2, 1, 2], [2, 1, 3], [3, 1, 2], [3, 1, 3],
[2, 2, 1], [2, 3, 1], [3, 2, 1], [3, 3, 1],
[2, 2, 2], [2, 2, 3], [2, 3, 2], [3, 2, 2],
[3, 3, 2], [3, 2, 3], [2, 3, 3], [3, 3, 3]
];
cy.window().then(async (win) => {
let stateVariables = await win.returnAllStateVariables1();
Expand Down Expand Up @@ -656,10 +656,10 @@ describe('SelectFromSequence Tag Tests', function () {
let num3 = stateVariables[stateVariables['/sample' + ind].replacements[2].componentName].stateValues.value;
let num4 = stateVariables[stateVariables['/sample' + ind].replacements[3].componentName].stateValues.value;

expect([1,2,3].includes(num1)).eq(true);
expect([0,2,3].includes(num2)).eq(true);
expect([0,1,3].includes(num3)).eq(true);
expect([0,1,2].includes(num4)).eq(true);
expect([1, 2, 3].includes(num1)).eq(true);
expect([0, 2, 3].includes(num2)).eq(true);
expect([0, 1, 3].includes(num3)).eq(true);
expect([0, 1, 2].includes(num4)).eq(true);

}
})
Expand Down Expand Up @@ -704,9 +704,9 @@ describe('SelectFromSequence Tag Tests', function () {
let num2 = stateVariables[stateVariables['/sample' + ind].replacements[1].componentName].stateValues.value;
let num3 = stateVariables[stateVariables['/sample' + ind].replacements[2].componentName].stateValues.value;

expect([2,3].includes(num1)).eq(true);
expect([1,3].includes(num2)).eq(true);
expect([1,2].includes(num3)).eq(true);
expect([2, 3].includes(num1)).eq(true);
expect([1, 3].includes(num2)).eq(true);
expect([1, 2].includes(num3)).eq(true);

}
})
Expand All @@ -728,7 +728,7 @@ describe('SelectFromSequence Tag Tests', function () {
it('select 10 numbers from 1 to 10, without replacement, exclude positions of each number', () => {
// make sure that exclude combinations does not enumerate all combinations excluded
// to count them

cy.window().then(async (win) => {
win.postMessage({
doenetML: `
Expand All @@ -750,12 +750,12 @@ describe('SelectFromSequence Tag Tests', function () {
cy.get('#\\/_text1').should('have.text', 'a')


let allNumbers = [1,2,3,4,5,6,7,8,9,10]
let allNumbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
cy.window().then(async (win) => {
let stateVariables = await win.returnAllStateVariables1();
for (let ind = 1; ind <= 10; ind++) {

for(let j=0; j< 10; j++) {
for (let j = 0; j < 10; j++) {
let num = stateVariables[stateVariables['/sample' + ind].replacements[j].componentName].stateValues.value;

let validNums = [...allNumbers];
Expand Down
2 changes: 1 addition & 1 deletion cypress/e2e/DoenetML/tagSpecific/substitute.cy.js
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@ describe('Substitute Tag Tests', function () {
win.postMessage({
doenetML: `
<text>a</text>
<textinput name="simplify" />
<textinput name="simplify" prefill="false" />
<substitute name="s_one" match="x" replacement="y" assignNames="one" simplify="$simplify">
x+y
</substitute>
Expand Down
Loading

0 comments on commit bd04a17

Please sign in to comment.