Answer Checking Wheel of Death in Cascades

I am working on this Polynomial Activity (with Cascades). I have a lot of variants and to check if the student’s work (both symbolically and graphically) is correct. Excuse the mess with my logic because I’m still learning how to use all of the features and tags.

There is one part of the activity that is hanging up in the answer checking phase, but only if I have cascades.

It’s in the section called “Multiplicity and Behavior at Zeros”. The table in that section is generated by a module, and each row is generated using a repeatForSequence. The answer checking for that row is built into the module.

The Multiplicity Column checks accurately and quickly. However, the “Behavior at the Zero” column just hangs on “Checking” when you hit “Check Work”. If you choose the correct answers, it is recognized by my award tag and you can move onto the next section. But the spinning wheel of death is still there.

Can someone help me figure out how to make this module better and get past the spinning wheel of death? Pedagogically, I like that each answer is checked individually, but that can also be annoying. I was pretty proud of getting the module to work on my own.

Here is the same activity, but with the Cascade removed from that section. The answer checking works quickly in this version. The only difference is the cascade.

Polynomial Graphing Activity (No Cascade)

I have some other issues, but I’ll put those in a new thread once I have this problem solved.

This doesn’t resolve the issue but line 44 might be missing a $.

Nice catch. I missed that one because I didn’t notice any variants whose right root was 0.

This one made my head hurt. I got rid of modules and just hard coded things and that seemed to work.

Modules scare me. I’m not sure I’ve ever felt safe using them. It’s like leaving the popcorn bag in the microwave for 15 seconds too long.

<title>Polynomial Equation and Graph Connections</title>
<variantControl numVariants="10" />
<setup>
  <boolean name="showdebug">false</boolean>
  <!-- Select the three roots but make them well spaced -->
  <select name="s">5 6 7 </select>
  <selectFromSequence name="rL" from="-7" to="3" exclude="0" />
  
  <number name="rR">
    <conditionalContent>
      <case condition="$rL+$s=0">
        5
      </case>
      <else>
        $rL+$s
      </else>
    </conditionalContent>
  </number>
  
  <number name="rM">
    <math simplify>
      <floor><mean>$rL $rR</mean></floor>
    </math>
    </number>

  
  <mathList name="rootslist" unordered="true">
    <sort>$rL $rM $rR</sort>
  </mathList>
  
<!-- Select multiplicities -->
<select name="mu" numToSelect="3">1 1 2 3</select>

<selectFromSequence name="a"from="-8" to="8" exclude="-1 0 1"/>
<!-- Scaling factor to make things not get too crazy. Also ensure not dividing by zero -->
  
  <number name="scl">
    <conditionalContent>
      <case condition="$rM=0">
        <abs>
          20*$rootslist[1]^$mu[1]*$rootslist[3]^$mu[3]
        </abs> 
      </case>
      <case condition="$rR=0">
        20*$rootslist[1]^$mu[1]*$rootslist[2]^$mu[2]
      </case>
      <else>
        $rootslist[1]^$mu[1]*$rootslist[2]^$mu[2]*$rootslist[3]^$mu[3]
      </else>
    </conditionalContent>

  </number>

  
<math name="lt" simplify>$a/$scl*x^($mu[1]+$mu[2]+$mu[3])</math>
<math name="lc" simplify>$a/$scl</math>
<math name="deg"><sum>$mu</sum></math>
  <function name="p">  <math simplify>$a/$scl*(x-$rootslist[1])^($mu[1])(x-$rootslist[2])^($mu[2])(x-$rootslist[3])^($mu[3])</math></function>


</setup>


<section hide="!$showdebug">
  <title>Debugging Info</title>
  <p>Roots List: $rootslist</p>

  <floor><mean>$rL $rR</mean></floor>
    <math simplify><floor><mean>$rL $rR</mean></floor>+1</math>
  <p>Multiplicities: $mu </p>
  <p>Leading Term: $lt</p>
  <p>Leading Coefficient: $lc</p>
  <p>Degree: $deg</p>
  <p>y-intercept: <m>(0,$$p(0))</m></p>
  <p><min>$p.minimumValues</min></p>
</section>

<section noAutoTitle>
<cascade boxAll>
<subsection>

  <title>Zeros</title>
  <p>
  Consider the polynomial function given by: <m>f(x)=$p</m>


</p>
  

  
  
  
  
  
  
  <!-- MODIFIED: Moved <setup> block out of the <p> below. -->

  
  
  
  
  
  
  
  
  
  <!--Storing their answers as a math list. Is there a better way to do this?  -->
<setup>
  <mathList name="ans1">$zeros</mathList>
</setup>
<p>
<answer name="zeros">
<label>List the unique zeros of this function in any order:</label>
<award>
$rootslist
</award>
</answer>
<!--Add feedback based on length of list? How do I get the length of the list that they entered-->
  


</p> 
</subsection>
<subsection >
  <title>Multiplicity and Behavior at Zeros</title>
The zeros that you listed above have been sorted in ascending order: $rootslist and listed in the table below. For each zero, fill in its multiplicity in the second column and select the behavior at the zero using the options in the third column.
<me>f(x)=$p</me>
<!-- Need to adjust the view of the table, but the content is fine -->










  
      <!-- MODIFIED: The table rows below were previously generated using <module copy="$BehavRows"/>. Since this activity always generates 3 roots, hard-coding the rows seems to fix `something.` -->

  
  
  
  
  
  
  
  
  
  <tabular>
        <row header>
          <cell>Zero</cell>
          <cell>Multiplicity</cell>
          <cell>Behavior at the Zero</cell>
        </row>

      <row>
        <cell>$rootslist[1]</cell>
        <cell>
          <answer>
            <mathInput name="mult1">
              <shortDescription>Multiplicity Answer Box</shortDescription>
            </mathInput>
            <award>
              <when>
                $mult1=$mu[1]
              </when>  
            </award>
          </answer>
        </cell>
        <cell>
          <choiceInput name="b1" inline>
            <shortDescription>Behavior Drop Down</shortDescription>
              <choice>
              Crosses the <m>x</m>-axis almost linearly
              </choice>
              <choice>
              Turns at the <m>x</m>-axis 
              </choice>
              <choice>
              Saddles through the <m>x</m>-axis 
              </choice>
         </choiceInput>
          <answer>
            <award>
              <when>
                $b1.selectedIndex=$mu[1]
              </when>
            </award>
          </answer>
        </cell>
      </row>

      <row>
        <cell>$rootslist[2]</cell>
        <cell>
          <answer>
            <mathInput name="mult2">
              <shortDescription>Multiplicity Answer Box</shortDescription>
            </mathInput>
            <award>
              <when>
                $mult2=$mu[2]
              </when>  
            </award>
          </answer>
        </cell>
        <cell>
          <choiceInput name="b2" inline>
            <shortDescription>Behavior Drop Down</shortDescription>
              <choice>
              Crosses the <m>x</m>-axis almost linearly
              </choice>
              <choice>
              Turns at the <m>x</m>-axis 
              </choice>
              <choice>
              Saddles through the <m>x</m>-axis 
              </choice>
         </choiceInput>
          <answer>
            <award>
              <when>
                $b2.selectedIndex=$mu[2]
              </when>
            </award>
          </answer>
        </cell>
      </row>

      <row>
        <cell>$rootslist[3]</cell>
        <cell>
          <answer>
            <mathInput name="mult3">
              <shortDescription>Multiplicity Answer Box</shortDescription>
            </mathInput>
            <award>
              <when>
                $mult3=$mu[3]
              </when>  
            </award>
          </answer>
        </cell>
        <cell>
          <choiceInput name="b3" inline>
            <shortDescription>Behavior Drop Down</shortDescription>
              <choice>
              Crosses the <m>x</m>-axis almost linearly
              </choice>
              <choice>
              Turns at the <m>x</m>-axis 
              </choice>
              <choice>
              Saddles through the <m>x</m>-axis 
              </choice>
         </choiceInput>
          <answer>
            <award>
              <when>
                $b3.selectedIndex=$mu[3]
              </when>
            </award>
          </answer>
        </cell>
      </row>
      </tabular>

  </subsection>

  <subsection>
    <title>The y-intercept</title>
   
    <answer>
      <mathInput name="yint">
      <label> The <m>y</m>-intercept of the function <m>f(x)=$p</m> as an <em> ordered pair </em> is:</label>
        </mathInput>
      (0,$$p(0))
    </answer>
  </subsection>


  <subsection>
    <title>End Behavior</title>
    <p>Now let's focus on the end behavior of this function.</p>
    <p>
    <answer name="ltin">
      <mathInput>
        <label>
          The leading term of $p is
        </label>
      </mathInput>
          $lt
    </answer>
    </p>
    <p>
      <choiceInput name="coef_in" inline>
        <label>The leading coefficient is </label>
        <choice name="pos">positive</choice>
        <choice name="neg">negative</choice>
    </choiceInput>
    which means that as <m>x\to \infty, y\to </m>
    <choiceInput inline name="reb">
      <shortDescription>Choices for left side end behavior</shortDescription>
      <choice>
        <m>\infty</m>
      </choice>
      <choice>
         <m>-\infty</m>
      </choice>
    </choiceInput>. 
    Since the degree is 
    <choiceInput inline name="deg_in">
      <shortDescription>Choices for degree</shortDescription>
      <choice>even</choice>
      <choice>odd</choice>
    </choiceInput>
      , this means that as <m>x\to -\infty, y\to </m>
      <choiceInput inline name="leb">
        <shortDescription>Choices for right side end behavior</shortDescription>
        <choice><m>\infty</m></choice>
        <choice><m>-\infty</m></choice>
      </choiceInput>
    </p>
    <answer>
      <shortDescription>
        Check answer for leading coefficient, degree, and endbehavior
      </shortDescription>
       <award>
        <when>
          ($coef_in.selectedIndex=1 and $lc > 0
          or $coef_in.selectedIndex=2 and $lc < 0)
          and
          ($reb.selectedIndex=1 and $lc >0 
          or $reb.selectedIndex=2 and $lc < 0)
          and
          ($deg_in.selectedIndex=1 and <mod>$deg 2</mod>=0
          or $deg_in.selectedIndex=2 and <mod>$deg 2</mod>=1)
          and
          ($reb.selectedIndex=$leb.selectedIndex and <mod>$deg 2</mod>=0
          or $reb.selectedIndex+$leb.selectedIndex=3 and <mod>$deg 2</mod>=1)
        </when>
      </award>
    </answer>
  </subsection>
</cascade>

</section>


<section hide="!$zeros.creditAchieved">
  <title>Graph</title>
  <me>f(x)=$p</me>

<setup>
<!-- Lowest and highest turn y-value -->
  <number name="min_turn"><min>$p.minimumValues -5</min></number>
  <number name="max_turn"><max>$p.maximumValues 5 </max></number>

  
<!--Left End Bevahior Set Up  -->
  <circle name="Lcirc"
    center="(-8,0)"
    radius="($graph1.yMax-$graph1.yMin)/8"/>  
  <point name="Lhead" styleNumber="4"markerSize="3">
    <label><m>Q_1</m></label>
    (-10,0)
    <constrainTo>$Lcirc</constrainTo>
  </point>
  <point name="Lcent" styleNumber="4" markerSize="3">
    <label><m>P_1</m></label>
    $Lcirc.center
  </point>

<!--Right End Behavior Set Up -->
  <circle name="Rcirc"
    center="(8,0)"
    radius="($graph1.yMax-$graph1.yMin)/8"/>  
  
  <point name="Rhead" styleNumber="4" markerSize="3">
    <label><m>Q_2</m></label>
    (10,0)
    <constrainTo>$Rcirc</constrainTo>
  </point>
  <point name="Rcent" styleNumber="4" markerSize="3">
    <label><m>P_2</m></label>
    $Rcirc.center
  </point>
  <number name="h">0.9</number>
 
<boolean name="pos_lc">
 $lc > 0 
</boolean>
<boolean name="neg_lc">
 $lc < 0 
</boolean>

<boolean name="ev_deg">
 <mod>$deg 2</mod>=0 
</boolean>

<boolean name="od_deg">
 <mod>$deg 2</mod>=1 
</boolean>

<!--Check the right end behavior  -->
<boolean name="rightcheck">
  ($pos_lc and $vR.y/$vR.x > 0 and $Rcent.x > $rR and $Rcent.y > 0) 
  or
  ($neg_lc and $vR.y/$vR.x < 0 and $Rcent.x > $rR and $Rcent.y < 0)
</boolean>
    
<!-- Check the left end behavior -->
<boolean name="leftcheck">
  <conditionalContent>
    <case condition="$neg_lc">
      <conditionalContent>
        <case condition="$ev_deg">
          $vL.y/$vL.x > 0 and $Lcent.x < $rL and $Lcent.y < 0
        </case>
        <case condition="$od_deg">
          $vL.y/$vL.x < 0 and $Lcent.x < $rL and $Lcent.y > 0
        </case>
      </conditionalContent>
    </case>
    <case condition="$pos_lc">
      <conditionalContent>
        <case condition="$ev_deg">
          $vL.y/$vL.x < 0 and $Lcent.x < $rL and $Lcent.y > 0
        </case>
        <case condition="$od_deg">
        $vL.y/$vL.x > 0 and $Lcent.x < $rL and $Lcent.y < 0
        </case>
      </conditionalContent>
    </case>
  </conditionalContent>
</boolean>
  
</setup>
<cascade boxAll>
<subsection>
<title>Putting it all together graphically </title>

<p>The graph below contains much of the work you've previosly submitted, but you'll have to do a bit more to finish the graph. To start, fix the arrows for the end behavior of <m>f(x)</m>.

<br/>When you are finished, check your work for the end behavior by clicking the "Check Work" button.
</p>
<p>Recall, you said 
  <ul>
    <li>as <m>x\to -\infty, y\to $leb.selectedValue</m></li>
    <li>as <m>x\to \infty, y\to $reb.selectedValue</m></li>
  </ul>
</p>
<hint>
  For the left end behavior, move $Lcent.label so its to the left of <m>$rL.</m> Then move $Lhead.label so that the arrow is pointing the correct way (up vs down). Finally, move $Lcent.label again so that it is above or below the x-axis as appropriate. Use a similar strategy with $Rcent.label and $Rhead.label.
</hint>
  <answer name="endbeh">
    <shortDescription>Check End Behavior</shortDescription>
    <award>
      <when>
     $rightcheck and $leftcheck
      </when>
    </award>
  </answer>
  <feedback condition="!$endbeh.creditAchieved and $endbeh.justSubmitted">
    Make sure that $Lcent.label and $Rcent.label are on the outside of the outermost roots. 
  </feedback>
</subsection>
  
<subsection hide="!$endbeh.creditAchieved">
<title>Behavior at Roots</title>
The possible behaviors at each root are shown below. For each root, choose Option 1 or Option 2 to match the behavior you'd expect based on the end behavior you've previously checked. 
<setup>
<!-- These should probably be modules that take in the function and root -->
  <boolean name="Lrootbcheck">
    ($left_c.selectedIndex=1 
      and <sign>$$Lrb_p($rL-0.1)</sign>=<sign>$$p($rL-0.1)</sign>)
      or
      ($left_c.selectedIndex=2 
      and <sign>$$Lrb_n($rL-0.1)</sign>=<sign>$$p($rL-0.1)</sign>)
  </boolean>

  <boolean name="Mrootbcheck">
    ($middle_c.selectedIndex=1 
      and <sign>$$Mrb_p($rM-0.1)</sign>=<sign>$$p($rM-0.1)</sign>)
      or
      ($middle_c.selectedIndex=2 
      and <sign>$$Mrb_n($rM-0.1)</sign>=<sign>$$p($rM-0.1)</sign>)
  </boolean>

  <boolean name="Rrootbcheck">
    ($right_c.selectedIndex=1 
      and <sign>$$Rrb_p($rR-0.1)</sign>=<sign>$$p($rR-0.1)</sign>)
      or
      ($right_c.selectedIndex=2 
      and <sign>$$Rrb_n($rR-0.1)</sign>=<sign>$$p($rR-0.1)</sign>)
  </boolean>
</setup>
  <tabular>
    <row header>
      <cell>$rootslist[1]</cell>
      <cell>$rootslist[2]</cell>
      <cell>$rootslist[3]</cell>
    </row>
    <row>
      <cell>
        <choiceInput name="left_c">
          <shortDescription>Choosing left root behavior</shortDescription>
          <choice>
            Option 1 (Red)
          </choice>
          <choice>
            Option 2 (Orange)
          </choice>
        </choiceInput>
      </cell>
      <cell>
        <choiceInput name="middle_c">
          <shortDescription>Choosing middle root behavior</shortDescription>
          <choice>
            Option 1 (Red)
          </choice>
          <choice>
            Option 2 (Orange)
          </choice>
        </choiceInput>
      </cell>
      <cell>
        <choiceInput name="right_c">
          <shortDescription>Choosing right root behavior</shortDescription>
          <choice>
            Option 1 (Red)
          </choice>
          <choice>
            Option 2 (Orange)
          </choice>
        </choiceInput>
      </cell>
    </row>
  </tabular>
<answer name="lastcheck">
  <award>
    <when>
    $Lrootbcheck and $Mrootbcheck and $Rrootbcheck
    </when>
  </award>
</answer>

</subsection>
  
<subsection hide="!$lastcheck.creditAchieved">
<title>Finally done!</title>
You are finally ready to sketch your graph. Any remaining turning points have also been added since you need calculus to find those. Press the button below to connect all of the features.
<p>










  
  <!-- MODIFIED to below: <function>$p</function> since you are already inside a graph -->
  
  
  
  
  
  
  
  
  <callAction actionName="addChildren" target="$graph1">
  $p
  <label>Graph Function</label>
</callAction>
</p>


</subsection>
</cascade>

  
<setup>
  <function name="Lrb_p" hide="$left_c.selectedIndex=2 or !$endbeh.creditAchieved"  domain="($rL-$h, $rL+$h)" styleNumber="2">
    <abs>$a/$scl*($rL-$rM)^$mu[2]*($rL-$rR)^$mu[3]</abs>*(x-$rL)^$mu[1]
  </function>
  
  <function name="Lrb_n" hide="$left_c.selectedIndex=1 or !$endbeh.creditAchieved" domain="($rL-$h, $rL+$h)"styleNumber="3">
    -$Lrb_p
  </function>

  <function name="Mrb_p" hide="$middle_c.selectedIndex=2 or !$endbeh.creditAchieved" domain="($rM-$h, $rM+$h)" styleNumber="2">
    <abs>$a/$scl*($rM-$rL)^$mu[1]*($rM-$rR)^$mu[3]</abs>*(x-$rM)^$mu[2]
  </function>
  
  <function name="Mrb_n" hide="$middle_c.selectedIndex=1 or !$endbeh.creditAchieved" domain="($rM-$h, $rM+$h)" styleNumber="3">
    -$Mrb_p
  </function>
  
  <function name="Rrb_p" hide="$right_c.selectedIndex=2 or !$endbeh.creditAchieved" domain="($rR-$h, $rR+$h)" styleNumber="2">
    <abs>$a/$scl*($rR-$rL)^$mu[1]*($rR-$rM)^$mu[2]</abs>*(x-$rR)^$mu[3]
  </function>

  <function name="Rrb_n" hide="$right_c.selectedIndex=1 or !$endbeh.creditAchieved" domain="($rR-$h, $rR+$h)" styleNumber="3">
    -$Rrb_p
  </function>
  

</setup>
<me>f(x)=$p</me>
  <!-- Start of the graph elements -->
<graph name="graph1"
  ymin="1.2*$min_turn" 
  ymax="1.2*$max_turn">
  
<shortDescription>A graph that contains zeros at the previously indicated user value, movable vectors to adjust endbehavior, and the behavior at the roots previously indicated by the user.
</shortDescription>
  
  <pointList name="xints" fixed>
    ($rootslist[1],0) ($rootslist[2],0) ($rootslist[3],0)
  </pointList>
  <lineSegment name="segment1" endpoints="$Lcent $Lhead"/>
   <vector styleNumber="4" name="vL" head="$Lhead" tail="$Lcent"/>
    <vector styleNumber="4" name="vR" head="$Rhead" tail="$Rcent"/>
    $Lhead
    $Lcent
    $Rhead
    $Rcent
    <!-- $p -->
  <point>$yint</point>
  $Lrb_p
  $Lrb_n
  $Mrb_p
  $Mrb_n
  $Rrb_p
  $Rrb_n
  <pointList hide="!$lastcheck.creditAchieved">$p.extrema</pointList>

  
</graph>

<!-- End Behavior Check -->




</section>

I can confirm this bug. Thanks for stress-testing Doenet and finding a bug! I’ll look into and see what is causing this problem.

I originally had it hard coded like you’ve shown. But I remember someone saying that if you are repeatedly copying and pasting, you should use modules instead. I wanted to be able to modify this for 2-4 roots more easily, which is why I took the effort to make the module. I also like the ability to change the language of the drop downs in one place (some people prefer “bounce” or “touch” for even multiplicity).

I’ll look at some of your other modifications the next time I’m working on this.

I think there’s a bit more logic that can be tightened up so it looks less daunting.

Wow, Carly, your creativity found quite a subtle bug. It is triggered only if you have an <m> inside a <choice> inside a <choiceInput> that used in an <answer> inside a <repeatForSequence> inside a <cascade>. Even just removing the <m> to change “Crosses the <m>x</m>-axis almost linearly” to “Crosses the x-axis almost linearly” removes the wheel of death.

I have fixed the bug. Hope to have a new dev version with the fix released within an hour or so.

Fix for this bug is in, and I have released a new dev version of DoenetML with the fix.

Carly, if you want to test this out, you can click on the Settings button when in this activity, scroll to the bottom, and change the version to 0.7dev. Assuming you haven’t used 0.7dev in awhile, the activity should start working immediately. (If you have used 0.7.dev recently, you may have to clear your browser’s cache or wait a day or so for the new version to kick in.)

Duane,

Yay, it works! By the way, this was the same bug that I found at the conference but couldn’t replicate because I had changed my activity design.

Thank you!