@doenet/doenetml 0.6.0-alpha1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (549) hide show
  1. package/.prettierrc +3 -0
  2. package/LICENSE +661 -0
  3. package/README.md +146 -0
  4. package/cypress/e2e/ActivityViewer/activityVariants.cy.js +1770 -0
  5. package/cypress/e2e/ActivityViewer/compiledActivity.cy.js +83 -0
  6. package/cypress/e2e/ActivityViewer/relationshipsAmongPages.cy.js +697 -0
  7. package/cypress/e2e/answerValidation/errorinnumbers.cy.js +2125 -0
  8. package/cypress/e2e/answerValidation/factoring.cy.js +1945 -0
  9. package/cypress/e2e/answerValidation/factoringOldAlgorithm.cy.js +892 -0
  10. package/cypress/e2e/answerValidation/functionanswers.cy.js +314 -0
  11. package/cypress/e2e/answerValidation/matchingpatterns.cy.js +287 -0
  12. package/cypress/e2e/answerValidation/matchpartial.cy.js +6711 -0
  13. package/cypress/e2e/answerValidation/pointlocation.cy.js +3989 -0
  14. package/cypress/e2e/answerValidation/symbolicequality.cy.js +1893 -0
  15. package/cypress/e2e/answerValidation/videoProgress.cy.js +210 -0
  16. package/cypress/e2e/assignNames/basiccopy.cy.js +2376 -0
  17. package/cypress/e2e/assignNames/collections.cy.js +9247 -0
  18. package/cypress/e2e/assignNames/selects.cy.js +105 -0
  19. package/cypress/e2e/assignNames/sequences.cy.js +1964 -0
  20. package/cypress/e2e/baseComponent/basecomponentproperties.cy.js +999 -0
  21. package/cypress/e2e/baseComponent/doenetMLtext.cy.js +427 -0
  22. package/cypress/e2e/chemistry/atom.cy.js +201 -0
  23. package/cypress/e2e/chemistry/ion.cy.js +608 -0
  24. package/cypress/e2e/chemistry/ioniccompound.cy.js +133 -0
  25. package/cypress/e2e/dynamicalsystem/cobwebpolyline.cy.js +2653 -0
  26. package/cypress/e2e/dynamicalsystem/equilibriumcurve.cy.js +311 -0
  27. package/cypress/e2e/dynamicalsystem/equilibriumline.cy.js +279 -0
  28. package/cypress/e2e/dynamicalsystem/equilibriumpoint.cy.js +283 -0
  29. package/cypress/e2e/dynamicalsystem/odesystem.cy.js +1834 -0
  30. package/cypress/e2e/equality/mathexpressions.cy.js +948 -0
  31. package/cypress/e2e/graphing/graphreferences.cy.js +978 -0
  32. package/cypress/e2e/graphing/graphreferences2.cy.js +615 -0
  33. package/cypress/e2e/linearAlgebra/eigenDecomposition.cy.js +401 -0
  34. package/cypress/e2e/tagSpecific/angle.cy.js +3898 -0
  35. package/cypress/e2e/tagSpecific/animatefromsequence.cy.js +2306 -0
  36. package/cypress/e2e/tagSpecific/answer.cy.js +31647 -0
  37. package/cypress/e2e/tagSpecific/bestfitline.cy.js +612 -0
  38. package/cypress/e2e/tagSpecific/blockquote.cy.js +30 -0
  39. package/cypress/e2e/tagSpecific/boolean.cy.js +742 -0
  40. package/cypress/e2e/tagSpecific/booleaninput.cy.js +1283 -0
  41. package/cypress/e2e/tagSpecific/booleanlist.cy.js +588 -0
  42. package/cypress/e2e/tagSpecific/booleanoperators.cy.js +596 -0
  43. package/cypress/e2e/tagSpecific/booleanoperatorsonmath.cy.js +498 -0
  44. package/cypress/e2e/tagSpecific/callaction.cy.js +2835 -0
  45. package/cypress/e2e/tagSpecific/choiceinput.cy.js +3205 -0
  46. package/cypress/e2e/tagSpecific/circle.cy.js +22036 -0
  47. package/cypress/e2e/tagSpecific/codeeditor.cy.js +1995 -0
  48. package/cypress/e2e/tagSpecific/collect.cy.js +5035 -0
  49. package/cypress/e2e/tagSpecific/componentsize.cy.js +502 -0
  50. package/cypress/e2e/tagSpecific/conditionalcontent.cy.js +3495 -0
  51. package/cypress/e2e/tagSpecific/contentBrowser.cy.js +335 -0
  52. package/cypress/e2e/tagSpecific/contentpicker.cy.js +261 -0
  53. package/cypress/e2e/tagSpecific/copy.cy.js +12627 -0
  54. package/cypress/e2e/tagSpecific/copy2.cy.js +5698 -0
  55. package/cypress/e2e/tagSpecific/curve.bezier.cy.js +12440 -0
  56. package/cypress/e2e/tagSpecific/curve.cy.js +1716 -0
  57. package/cypress/e2e/tagSpecific/curve.function.cy.js +1471 -0
  58. package/cypress/e2e/tagSpecific/curve.parametrized.cy.js +920 -0
  59. package/cypress/e2e/tagSpecific/document.cy.js +234 -0
  60. package/cypress/e2e/tagSpecific/endpoint.cy.js +197 -0
  61. package/cypress/e2e/tagSpecific/evaluate.cy.js +8895 -0
  62. package/cypress/e2e/tagSpecific/extract.cy.js +2282 -0
  63. package/cypress/e2e/tagSpecific/feedback.cy.js +2941 -0
  64. package/cypress/e2e/tagSpecific/function.cy.js +9450 -0
  65. package/cypress/e2e/tagSpecific/functioniterates.cy.js +1178 -0
  66. package/cypress/e2e/tagSpecific/functionoperators.cy.js +4047 -0
  67. package/cypress/e2e/tagSpecific/graph.cy.js +2491 -0
  68. package/cypress/e2e/tagSpecific/group.cy.js +683 -0
  69. package/cypress/e2e/tagSpecific/hint.cy.js +204 -0
  70. package/cypress/e2e/tagSpecific/image.cy.js +770 -0
  71. package/cypress/e2e/tagSpecific/integer.cy.js +206 -0
  72. package/cypress/e2e/tagSpecific/label.cy.js +800 -0
  73. package/cypress/e2e/tagSpecific/legend.cy.js +1001 -0
  74. package/cypress/e2e/tagSpecific/line.cy.js +12167 -0
  75. package/cypress/e2e/tagSpecific/linesegment.cy.js +4749 -0
  76. package/cypress/e2e/tagSpecific/lorem.cy.js +289 -0
  77. package/cypress/e2e/tagSpecific/map.cy.js +4476 -0
  78. package/cypress/e2e/tagSpecific/matchespattern.cy.js +693 -0
  79. package/cypress/e2e/tagSpecific/math.cy.js +10990 -0
  80. package/cypress/e2e/tagSpecific/mathdisplay.cy.js +2689 -0
  81. package/cypress/e2e/tagSpecific/mathinput.cy.js +15628 -0
  82. package/cypress/e2e/tagSpecific/mathinputgraph.cy.js +566 -0
  83. package/cypress/e2e/tagSpecific/mathlist.cy.js +4073 -0
  84. package/cypress/e2e/tagSpecific/mathoperators.cy.js +13851 -0
  85. package/cypress/e2e/tagSpecific/matrix.cy.js +8825 -0
  86. package/cypress/e2e/tagSpecific/matrixinput.cy.js +16277 -0
  87. package/cypress/e2e/tagSpecific/module.cy.js +1771 -0
  88. package/cypress/e2e/tagSpecific/number.cy.js +2221 -0
  89. package/cypress/e2e/tagSpecific/numberlist.cy.js +1285 -0
  90. package/cypress/e2e/tagSpecific/p.cy.js +72 -0
  91. package/cypress/e2e/tagSpecific/paginator.cy.js +2983 -0
  92. package/cypress/e2e/tagSpecific/parabola.cy.js +14331 -0
  93. package/cypress/e2e/tagSpecific/paragraphmarkup.cy.js +104 -0
  94. package/cypress/e2e/tagSpecific/periodicset.cy.js +1439 -0
  95. package/cypress/e2e/tagSpecific/piecewisefunction.cy.js +1055 -0
  96. package/cypress/e2e/tagSpecific/pluralize.cy.js +274 -0
  97. package/cypress/e2e/tagSpecific/point.cy.js +8895 -0
  98. package/cypress/e2e/tagSpecific/point2.cy.js +10259 -0
  99. package/cypress/e2e/tagSpecific/polygon.cy.js +5039 -0
  100. package/cypress/e2e/tagSpecific/polyline.cy.js +4704 -0
  101. package/cypress/e2e/tagSpecific/problem.cy.js +2768 -0
  102. package/cypress/e2e/tagSpecific/ray.cy.js +10770 -0
  103. package/cypress/e2e/tagSpecific/rectangle.cy.js +2143 -0
  104. package/cypress/e2e/tagSpecific/ref.cy.js +420 -0
  105. package/cypress/e2e/tagSpecific/regularPolygon.cy.js +1006 -0
  106. package/cypress/e2e/tagSpecific/regularPolygon2.cy.js +100 -0
  107. package/cypress/e2e/tagSpecific/regularPolygon3.cy.js +777 -0
  108. package/cypress/e2e/tagSpecific/samplerandomnumbers.cy.js +3619 -0
  109. package/cypress/e2e/tagSpecific/sectioning.cy.js +3530 -0
  110. package/cypress/e2e/tagSpecific/select.cy.js +5376 -0
  111. package/cypress/e2e/tagSpecific/selectfromsequence.cy.js +3846 -0
  112. package/cypress/e2e/tagSpecific/selectrandomnumbers.cy.js +2914 -0
  113. package/cypress/e2e/tagSpecific/sequence.cy.js +2093 -0
  114. package/cypress/e2e/tagSpecific/shuffle.cy.js +490 -0
  115. package/cypress/e2e/tagSpecific/sidebyside.cy.js +8057 -0
  116. package/cypress/e2e/tagSpecific/singlecharactercomponents.cy.js +72 -0
  117. package/cypress/e2e/tagSpecific/slider.cy.js +914 -0
  118. package/cypress/e2e/tagSpecific/solution.cy.js +109 -0
  119. package/cypress/e2e/tagSpecific/solveequations.cy.js +1026 -0
  120. package/cypress/e2e/tagSpecific/sort.cy.js +1685 -0
  121. package/cypress/e2e/tagSpecific/spreadsheet.cy.js +5971 -0
  122. package/cypress/e2e/tagSpecific/subsetofreals.cy.js +2725 -0
  123. package/cypress/e2e/tagSpecific/substitute.cy.js +2646 -0
  124. package/cypress/e2e/tagSpecific/tabular.cy.js +36 -0
  125. package/cypress/e2e/tagSpecific/text.cy.js +975 -0
  126. package/cypress/e2e/tagSpecific/textinput.cy.js +2177 -0
  127. package/cypress/e2e/tagSpecific/textlist.cy.js +369 -0
  128. package/cypress/e2e/tagSpecific/triangle.cy.js +1936 -0
  129. package/cypress/e2e/tagSpecific/triggerset.cy.js +2023 -0
  130. package/cypress/e2e/tagSpecific/updatevalue.cy.js +3288 -0
  131. package/cypress/e2e/tagSpecific/vector.cy.js +20183 -0
  132. package/cypress/e2e/tagSpecific/video.cy.js +612 -0
  133. package/cypress/e2e/tagSpecific/when.cy.js +202 -0
  134. package/cypress/e2e/variants/specifysinglevariant.cy.js +6726 -0
  135. package/cypress/e2e/variants/uniquevariants.cy.js +4846 -0
  136. package/cypress/fixtures/example.json +5 -0
  137. package/cypress/support/commands.js +32 -0
  138. package/cypress/support/e2e.js +31 -0
  139. package/cypress.config.js +18 -0
  140. package/docs/codeSnippet.jsx +11 -0
  141. package/docs/index.html +133 -0
  142. package/docs/index.jsx +138 -0
  143. package/docs/prism.css +3 -0
  144. package/index.html +14 -0
  145. package/index.js +21 -0
  146. package/media/answer_example.png +0 -0
  147. package/media/graph_example.png +0 -0
  148. package/media/graph_markup_example.png +0 -0
  149. package/package.json +83 -0
  150. package/public/favicon.ico +0 -0
  151. package/public/fonts/files/open-sans-v18-latin-700.woff +0 -0
  152. package/public/fonts/files/open-sans-v18-latin-700.woff2 +0 -0
  153. package/public/fonts/files/open-sans-v18-latin-700italic.woff +0 -0
  154. package/public/fonts/files/open-sans-v18-latin-700italic.woff2 +0 -0
  155. package/public/fonts/files/open-sans-v18-latin-italic.woff +0 -0
  156. package/public/fonts/files/open-sans-v18-latin-italic.woff2 +0 -0
  157. package/public/fonts/files/open-sans-v18-latin-light-italic.woff +0 -0
  158. package/public/fonts/files/open-sans-v18-latin-light-italic.woff2 +0 -0
  159. package/public/fonts/files/open-sans-v18-latin-light.woff +0 -0
  160. package/public/fonts/files/open-sans-v18-latin-light.woff2 +0 -0
  161. package/public/fonts/files/open-sans-v18-latin-regular.woff +0 -0
  162. package/public/fonts/files/open-sans-v18-latin-regular.woff2 +0 -0
  163. package/src/Core/ComponentTypes.js +426 -0
  164. package/src/Core/Core.js +11852 -0
  165. package/src/Core/CoreWorker.js +127 -0
  166. package/src/Core/Dependencies.js +8226 -0
  167. package/src/Core/Numerics.js +473 -0
  168. package/src/Core/ParameterStack.js +36 -0
  169. package/src/Core/ReadOnlyProxyHandler.js +41 -0
  170. package/src/Core/StateProxyHandler.js +88 -0
  171. package/src/Core/components/Aliases.js +67 -0
  172. package/src/Core/components/Angle.js +758 -0
  173. package/src/Core/components/AnimateFromSequence.js +922 -0
  174. package/src/Core/components/Answer.js +2087 -0
  175. package/src/Core/components/AsList.js +83 -0
  176. package/src/Core/components/AttractTo.js +245 -0
  177. package/src/Core/components/AttractToAngles.js +262 -0
  178. package/src/Core/components/AttractToConstraint.js +104 -0
  179. package/src/Core/components/AttractToGrid.js +315 -0
  180. package/src/Core/components/Award.js +906 -0
  181. package/src/Core/components/BestFitLine.js +318 -0
  182. package/src/Core/components/BezierControls.js +719 -0
  183. package/src/Core/components/BlockQuote.js +35 -0
  184. package/src/Core/components/Boolean.js +500 -0
  185. package/src/Core/components/BooleanInput.js +330 -0
  186. package/src/Core/components/BooleanList.js +396 -0
  187. package/src/Core/components/BooleanOperators.js +35 -0
  188. package/src/Core/components/BooleanOperatorsOfMath.js +148 -0
  189. package/src/Core/components/CallAction.js +261 -0
  190. package/src/Core/components/Caption.js +73 -0
  191. package/src/Core/components/Case.js +56 -0
  192. package/src/Core/components/Cell.js +439 -0
  193. package/src/Core/components/CellBlock.js +64 -0
  194. package/src/Core/components/Chart.js +795 -0
  195. package/src/Core/components/Choice.js +266 -0
  196. package/src/Core/components/ChoiceInput.js +1407 -0
  197. package/src/Core/components/Circle.js +2884 -0
  198. package/src/Core/components/CodeEditor.js +647 -0
  199. package/src/Core/components/CodeViewer.js +294 -0
  200. package/src/Core/components/CollaborateGroupSetup.js +46 -0
  201. package/src/Core/components/CollaborateGroups.js +119 -0
  202. package/src/Core/components/Collect.js +850 -0
  203. package/src/Core/components/Column.js +608 -0
  204. package/src/Core/components/ConditionalContent.js +468 -0
  205. package/src/Core/components/ConsiderAsResponses.js +49 -0
  206. package/src/Core/components/ConstrainTo.js +161 -0
  207. package/src/Core/components/ConstrainToAngles.js +244 -0
  208. package/src/Core/components/ConstrainToGraph.js +142 -0
  209. package/src/Core/components/ConstrainToGrid.js +175 -0
  210. package/src/Core/components/ConstraintUnion.js +119 -0
  211. package/src/Core/components/Constraints.js +497 -0
  212. package/src/Core/components/ContentBrowser.js +441 -0
  213. package/src/Core/components/ContentPicker.js +263 -0
  214. package/src/Core/components/ControlVectors.js +25 -0
  215. package/src/Core/components/Coords.js +63 -0
  216. package/src/Core/components/Copy.js +3412 -0
  217. package/src/Core/components/Curve.js +4130 -0
  218. package/src/Core/components/CustomAttribute.js +175 -0
  219. package/src/Core/components/DataFrame.js +357 -0
  220. package/src/Core/components/DiscreteSimulationResultList.js +342 -0
  221. package/src/Core/components/DiscreteSimulationResultPolyline.js +581 -0
  222. package/src/Core/components/Divisions.js +55 -0
  223. package/src/Core/components/Document.js +888 -0
  224. package/src/Core/components/Embed.js +65 -0
  225. package/src/Core/components/Endpoint.js +62 -0
  226. package/src/Core/components/Evaluate.js +321 -0
  227. package/src/Core/components/Extract.js +656 -0
  228. package/src/Core/components/Extrema.js +556 -0
  229. package/src/Core/components/Feedback.js +200 -0
  230. package/src/Core/components/FeedbackDefinitions.js +97 -0
  231. package/src/Core/components/Figure.js +148 -0
  232. package/src/Core/components/Footnote.js +73 -0
  233. package/src/Core/components/Function.js +5344 -0
  234. package/src/Core/components/FunctionIterates.js +306 -0
  235. package/src/Core/components/FunctionOperators.js +702 -0
  236. package/src/Core/components/Graph.js +1679 -0
  237. package/src/Core/components/Group.js +7 -0
  238. package/src/Core/components/HasSameFactoring.js +407 -0
  239. package/src/Core/components/Hint.js +241 -0
  240. package/src/Core/components/Image.js +524 -0
  241. package/src/Core/components/Indexing.js +79 -0
  242. package/src/Core/components/IntComma.js +64 -0
  243. package/src/Core/components/Integer.js +81 -0
  244. package/src/Core/components/Intersection.js +328 -0
  245. package/src/Core/components/Interval.js +29 -0
  246. package/src/Core/components/Label.js +492 -0
  247. package/src/Core/components/Latex.js +104 -0
  248. package/src/Core/components/Legend.js +329 -0
  249. package/src/Core/components/Line.js +2040 -0
  250. package/src/Core/components/LineSegment.js +882 -0
  251. package/src/Core/components/Lists.js +180 -0
  252. package/src/Core/components/Lorem.js +249 -0
  253. package/src/Core/components/MMeMen.js +377 -0
  254. package/src/Core/components/Map.js +873 -0
  255. package/src/Core/components/Markers.js +101 -0
  256. package/src/Core/components/MatchesPattern.js +339 -0
  257. package/src/Core/components/Math.js +2552 -0
  258. package/src/Core/components/MathInput.js +948 -0
  259. package/src/Core/components/MathList.js +828 -0
  260. package/src/Core/components/MathOperators.js +1286 -0
  261. package/src/Core/components/Matrix.js +497 -0
  262. package/src/Core/components/MatrixInput.js +3157 -0
  263. package/src/Core/components/MdMdnMrow.js +394 -0
  264. package/src/Core/components/Module.js +16 -0
  265. package/src/Core/components/Number.js +1031 -0
  266. package/src/Core/components/NumberList.js +550 -0
  267. package/src/Core/components/Option.js +24 -0
  268. package/src/Core/components/P.js +71 -0
  269. package/src/Core/components/Paginator.js +338 -0
  270. package/src/Core/components/Panel.js +126 -0
  271. package/src/Core/components/Parabola.js +1561 -0
  272. package/src/Core/components/ParagraphMarkup.js +59 -0
  273. package/src/Core/components/Pegboard.js +43 -0
  274. package/src/Core/components/PeriodicSet.js +291 -0
  275. package/src/Core/components/PiecewiseFunction.js +832 -0
  276. package/src/Core/components/Pluralize.js +198 -0
  277. package/src/Core/components/Point.js +1295 -0
  278. package/src/Core/components/Polygon.js +408 -0
  279. package/src/Core/components/Polyline.js +841 -0
  280. package/src/Core/components/RandomizedTextList.js +225 -0
  281. package/src/Core/components/Ray.js +1737 -0
  282. package/src/Core/components/Rectangle.js +1535 -0
  283. package/src/Core/components/Ref.js +350 -0
  284. package/src/Core/components/RegionBetweenCurveXAxis.js +124 -0
  285. package/src/Core/components/RegionHalfPlane.js +107 -0
  286. package/src/Core/components/RegularPolygon.js +2118 -0
  287. package/src/Core/components/RenderDoenetML.js +181 -0
  288. package/src/Core/components/Row.js +780 -0
  289. package/src/Core/components/SampleRandomNumbers.js +653 -0
  290. package/src/Core/components/Sectioning.js +303 -0
  291. package/src/Core/components/Select.js +947 -0
  292. package/src/Core/components/SelectFromSequence.js +1242 -0
  293. package/src/Core/components/SelectRandomNumbers.js +225 -0
  294. package/src/Core/components/Sequence.js +444 -0
  295. package/src/Core/components/Setup.js +53 -0
  296. package/src/Core/components/Shuffle.js +470 -0
  297. package/src/Core/components/SideBySide.js +2130 -0
  298. package/src/Core/components/SingleCharacterComponents.js +41 -0
  299. package/src/Core/components/Slider.js +819 -0
  300. package/src/Core/components/SolutionContainer.js +67 -0
  301. package/src/Core/components/Solutions.js +334 -0
  302. package/src/Core/components/SolveEquations.js +568 -0
  303. package/src/Core/components/Sort.js +398 -0
  304. package/src/Core/components/Sources.js +108 -0
  305. package/src/Core/components/Split.js +205 -0
  306. package/src/Core/components/Spreadsheet.js +1507 -0
  307. package/src/Core/components/StyleDefinitions.js +111 -0
  308. package/src/Core/components/SubsetOfReals.js +348 -0
  309. package/src/Core/components/SubsetOfRealsInput.js +1474 -0
  310. package/src/Core/components/Substitute.js +496 -0
  311. package/src/Core/components/SummaryStatistics.js +652 -0
  312. package/src/Core/components/Table.js +145 -0
  313. package/src/Core/components/Tabular.js +384 -0
  314. package/src/Core/components/Template.js +360 -0
  315. package/src/Core/components/Text.js +341 -0
  316. package/src/Core/components/TextInput.js +566 -0
  317. package/src/Core/components/TextList.js +442 -0
  318. package/src/Core/components/TextListFromString.js +137 -0
  319. package/src/Core/components/TextOperatorsOfMath.js +21 -0
  320. package/src/Core/components/Triangle.js +280 -0
  321. package/src/Core/components/TriggerSet.js +189 -0
  322. package/src/Core/components/TupleList.js +43 -0
  323. package/src/Core/components/UpdateValue.js +435 -0
  324. package/src/Core/components/VariantControl.js +36 -0
  325. package/src/Core/components/Vector.js +2478 -0
  326. package/src/Core/components/Verbatim.js +125 -0
  327. package/src/Core/components/Video.js +673 -0
  328. package/src/Core/components/When.js +198 -0
  329. package/src/Core/components/abstract/AngleListComponent.js +140 -0
  330. package/src/Core/components/abstract/BaseComponent.js +1496 -0
  331. package/src/Core/components/abstract/BlockComponent.js +5 -0
  332. package/src/Core/components/abstract/BooleanBaseOperator.js +88 -0
  333. package/src/Core/components/abstract/BooleanBaseOperatorOfMath.js +100 -0
  334. package/src/Core/components/abstract/BooleanBaseOperatorOneInput.js +44 -0
  335. package/src/Core/components/abstract/ComponentSize.js +789 -0
  336. package/src/Core/components/abstract/ComponentWithSelectableType.js +537 -0
  337. package/src/Core/components/abstract/CompositeComponent.js +142 -0
  338. package/src/Core/components/abstract/ConstraintComponent.js +19 -0
  339. package/src/Core/components/abstract/FunctionBaseOperator.js +680 -0
  340. package/src/Core/components/abstract/GraphicalComponent.js +56 -0
  341. package/src/Core/components/abstract/InlineComponent.js +5 -0
  342. package/src/Core/components/abstract/InlineRenderInlineChildren.js +63 -0
  343. package/src/Core/components/abstract/Input.js +192 -0
  344. package/src/Core/components/abstract/IntervalListComponent.js +218 -0
  345. package/src/Core/components/abstract/LineListComponent.js +114 -0
  346. package/src/Core/components/abstract/MathBaseOperator.js +631 -0
  347. package/src/Core/components/abstract/MathBaseOperatorOneInput.js +112 -0
  348. package/src/Core/components/abstract/PointListComponent.js +238 -0
  349. package/src/Core/components/abstract/SectioningComponent.js +1262 -0
  350. package/src/Core/components/abstract/SingleCharacterInline.js +23 -0
  351. package/src/Core/components/abstract/TextBaseOperatorOfMath.js +47 -0
  352. package/src/Core/components/abstract/TextOrInline.js +66 -0
  353. package/src/Core/components/abstract/VariableName.js +31 -0
  354. package/src/Core/components/abstract/VariableNameList.js +83 -0
  355. package/src/Core/components/abstract/VectorListComponent.js +235 -0
  356. package/src/Core/components/chemistry/Atom.js +910 -0
  357. package/src/Core/components/chemistry/ElectronConfiguration.js +36 -0
  358. package/src/Core/components/chemistry/Ion.js +684 -0
  359. package/src/Core/components/chemistry/IonicCompound.js +189 -0
  360. package/src/Core/components/chemistry/OrbitalDiagram.js +175 -0
  361. package/src/Core/components/chemistry/OrbitalDiagramInput.js +753 -0
  362. package/src/Core/components/chemistry/index.js +6 -0
  363. package/src/Core/components/commonsugar/breakstrings.js +627 -0
  364. package/src/Core/components/commonsugar/lists.js +177 -0
  365. package/src/Core/components/dynamicalSystems/CobwebPolyline.js +913 -0
  366. package/src/Core/components/dynamicalSystems/EquilibriumCurve.js +95 -0
  367. package/src/Core/components/dynamicalSystems/EquilibriumLine.js +93 -0
  368. package/src/Core/components/dynamicalSystems/EquilibriumPoint.js +93 -0
  369. package/src/Core/components/dynamicalSystems/ODESystem.js +943 -0
  370. package/src/Core/components/dynamicalSystems/index.js +5 -0
  371. package/src/Core/components/linearAlgebra/EigenDecomposition.js +294 -0
  372. package/src/Core/utils/array.js +30 -0
  373. package/src/Core/utils/booleanLogic.js +965 -0
  374. package/src/Core/utils/checkEquality.js +818 -0
  375. package/src/Core/utils/cid.js +29 -0
  376. package/src/Core/utils/componentInfoObjects.js +100 -0
  377. package/src/Core/utils/constraints.js +23 -0
  378. package/src/Core/utils/copy.js +572 -0
  379. package/src/Core/utils/deepFunctions.js +173 -0
  380. package/src/Core/utils/descendants.js +252 -0
  381. package/src/Core/utils/enumeration.js +234 -0
  382. package/src/Core/utils/feedback.js +84 -0
  383. package/src/Core/utils/function.js +1343 -0
  384. package/src/Core/utils/graphical.js +196 -0
  385. package/src/Core/utils/label.js +396 -0
  386. package/src/Core/utils/math.js +1056 -0
  387. package/src/Core/utils/naming.js +45 -0
  388. package/src/Core/utils/periodicSetEquality.js +403 -0
  389. package/src/Core/utils/randomNumbers.js +70 -0
  390. package/src/Core/utils/retrieveMedia.js +98 -0
  391. package/src/Core/utils/retrieveTextFile.js +140 -0
  392. package/src/Core/utils/returnAllPossibleVariants.js +73 -0
  393. package/src/Core/utils/rounding.js +316 -0
  394. package/src/Core/utils/sequence.js +754 -0
  395. package/src/Core/utils/serializedStateProcessing.js +4049 -0
  396. package/src/Core/utils/size.js +22 -0
  397. package/src/Core/utils/stateVariables.js +138 -0
  398. package/src/Core/utils/style.js +535 -0
  399. package/src/Core/utils/subset-of-reals.js +796 -0
  400. package/src/Core/utils/table.js +41 -0
  401. package/src/Core/utils/text.js +16 -0
  402. package/src/Core/utils/triggering.js +167 -0
  403. package/src/Core/utils/variants.js +477 -0
  404. package/src/DoenetML.css +308 -0
  405. package/src/DoenetML.jsx +201 -0
  406. package/src/Parser/doenet.grammar +90 -0
  407. package/src/Parser/doenet.js +33 -0
  408. package/src/Parser/doenet.terms.js +20 -0
  409. package/src/Parser/parser.js +266 -0
  410. package/src/Parser/tokens.js +129 -0
  411. package/src/Tools/CodeMirror.jsx +440 -0
  412. package/src/Tools/DarkmodeController.jsx +21 -0
  413. package/src/Tools/Footers/MathInputSelector.jsx +34 -0
  414. package/src/Tools/Footers/VirtualKeyboard.jsx +751 -0
  415. package/src/Tools/cypressTest/CypressTest.jsx +341 -0
  416. package/src/Tools/cypressTest/index.html +102 -0
  417. package/src/Tools/cypressTest/index.jsx +40 -0
  418. package/src/Viewer/ActivityViewer.jsx +1461 -0
  419. package/src/Viewer/PageViewer.jsx +1329 -0
  420. package/src/Viewer/renderers/alert.jsx +17 -0
  421. package/src/Viewer/renderers/angle.jsx +209 -0
  422. package/src/Viewer/renderers/answer.jsx +206 -0
  423. package/src/Viewer/renderers/asList.jsx +25 -0
  424. package/src/Viewer/renderers/blockQuote.jsx +41 -0
  425. package/src/Viewer/renderers/boolean.jsx +17 -0
  426. package/src/Viewer/renderers/booleanInput.css +105 -0
  427. package/src/Viewer/renderers/booleanInput.jsx +636 -0
  428. package/src/Viewer/renderers/button.jsx +369 -0
  429. package/src/Viewer/renderers/c.jsx +17 -0
  430. package/src/Viewer/renderers/callAction.jsx +18 -0
  431. package/src/Viewer/renderers/cell.jsx +59 -0
  432. package/src/Viewer/renderers/chart.jsx +83 -0
  433. package/src/Viewer/renderers/choiceInput.css +223 -0
  434. package/src/Viewer/renderers/choiceInput.jsx +535 -0
  435. package/src/Viewer/renderers/circle.jsx +990 -0
  436. package/src/Viewer/renderers/cobwebPolyline.jsx +442 -0
  437. package/src/Viewer/renderers/codeEditor.jsx +248 -0
  438. package/src/Viewer/renderers/codeViewer.jsx +105 -0
  439. package/src/Viewer/renderers/containerBlock.jsx +41 -0
  440. package/src/Viewer/renderers/containerInline.jsx +17 -0
  441. package/src/Viewer/renderers/contentBrowser.jsx +159 -0
  442. package/src/Viewer/renderers/contentPicker.jsx +160 -0
  443. package/src/Viewer/renderers/curve.jsx +1072 -0
  444. package/src/Viewer/renderers/ellipsis.jsx +17 -0
  445. package/src/Viewer/renderers/em.jsx +17 -0
  446. package/src/Viewer/renderers/embed.jsx +110 -0
  447. package/src/Viewer/renderers/feedback.jsx +74 -0
  448. package/src/Viewer/renderers/figure.jsx +131 -0
  449. package/src/Viewer/renderers/footnote.jsx +52 -0
  450. package/src/Viewer/renderers/graph.jsx +925 -0
  451. package/src/Viewer/renderers/hint.jsx +142 -0
  452. package/src/Viewer/renderers/image.jsx +581 -0
  453. package/src/Viewer/renderers/jsxgraph-distrib/jsxgraphcore.mjs +2 -0
  454. package/src/Viewer/renderers/jsxgraph-distrib/jsxgraphcore.mjs.map +1 -0
  455. package/src/Viewer/renderers/label.jsx +470 -0
  456. package/src/Viewer/renderers/legend.jsx +306 -0
  457. package/src/Viewer/renderers/line.jsx +511 -0
  458. package/src/Viewer/renderers/lineSegment.jsx +754 -0
  459. package/src/Viewer/renderers/list.jsx +111 -0
  460. package/src/Viewer/renderers/lq.jsx +12 -0
  461. package/src/Viewer/renderers/lsq.jsx +12 -0
  462. package/src/Viewer/renderers/math.jsx +582 -0
  463. package/src/Viewer/renderers/mathInput.css +10 -0
  464. package/src/Viewer/renderers/mathInput.jsx +425 -0
  465. package/src/Viewer/renderers/mathInputog.jsx +534 -0
  466. package/src/Viewer/renderers/mathList.jsx +39 -0
  467. package/src/Viewer/renderers/matrixInput.jsx +317 -0
  468. package/src/Viewer/renderers/mdash.jsx +12 -0
  469. package/src/Viewer/renderers/nbsp.jsx +12 -0
  470. package/src/Viewer/renderers/ndash.jsx +12 -0
  471. package/src/Viewer/renderers/number.jsx +454 -0
  472. package/src/Viewer/renderers/numberList.jsx +35 -0
  473. package/src/Viewer/renderers/orbitalDiagram.jsx +247 -0
  474. package/src/Viewer/renderers/orbitalDiagramInput.jsx +450 -0
  475. package/src/Viewer/renderers/p.jsx +38 -0
  476. package/src/Viewer/renderers/paginatorControls.jsx +41 -0
  477. package/src/Viewer/renderers/pegboard.jsx +239 -0
  478. package/src/Viewer/renderers/point.jsx +649 -0
  479. package/src/Viewer/renderers/polygon.jsx +612 -0
  480. package/src/Viewer/renderers/polyline.jsx +608 -0
  481. package/src/Viewer/renderers/pre.jsx +34 -0
  482. package/src/Viewer/renderers/q.jsx +17 -0
  483. package/src/Viewer/renderers/ray.jsx +410 -0
  484. package/src/Viewer/renderers/ref.jsx +149 -0
  485. package/src/Viewer/renderers/regionBetweenCurveXAxis.jsx +182 -0
  486. package/src/Viewer/renderers/renderDoenetML.jsx +56 -0
  487. package/src/Viewer/renderers/row.jsx +31 -0
  488. package/src/Viewer/renderers/rq.jsx +12 -0
  489. package/src/Viewer/renderers/rsq.jsx +12 -0
  490. package/src/Viewer/renderers/section.jsx +427 -0
  491. package/src/Viewer/renderers/sideBySide.jsx +80 -0
  492. package/src/Viewer/renderers/slider.jsx +800 -0
  493. package/src/Viewer/renderers/solution.jsx +134 -0
  494. package/src/Viewer/renderers/spreadsheet.jsx +83 -0
  495. package/src/Viewer/renderers/sq.jsx +17 -0
  496. package/src/Viewer/renderers/styles/global.css +14 -0
  497. package/src/Viewer/renderers/subsetOfRealsInput.jsx +392 -0
  498. package/src/Viewer/renderers/summaryStatistics.jsx +83 -0
  499. package/src/Viewer/renderers/table.jsx +78 -0
  500. package/src/Viewer/renderers/tabular.jsx +58 -0
  501. package/src/Viewer/renderers/tag.jsx +26 -0
  502. package/src/Viewer/renderers/text.jsx +439 -0
  503. package/src/Viewer/renderers/textInput.jsx +774 -0
  504. package/src/Viewer/renderers/textList.jsx +30 -0
  505. package/src/Viewer/renderers/triggerSet.jsx +52 -0
  506. package/src/Viewer/renderers/updateValue.jsx +30 -0
  507. package/src/Viewer/renderers/utils/css.js +13 -0
  508. package/src/Viewer/renderers/utils/graph.js +159 -0
  509. package/src/Viewer/renderers/utils/offGraphIndicators.js +91 -0
  510. package/src/Viewer/renderers/vector.jsx +678 -0
  511. package/src/Viewer/renderers/video.jsx +494 -0
  512. package/src/Viewer/useDoenetRenderer.jsx +128 -0
  513. package/src/main.jsx +16 -0
  514. package/src/media/fonts/files/open-sans-v18-latin-700.woff +0 -0
  515. package/src/media/fonts/files/open-sans-v18-latin-700.woff2 +0 -0
  516. package/src/media/fonts/files/open-sans-v18-latin-700italic.woff +0 -0
  517. package/src/media/fonts/files/open-sans-v18-latin-700italic.woff2 +0 -0
  518. package/src/media/fonts/files/open-sans-v18-latin-italic.woff +0 -0
  519. package/src/media/fonts/files/open-sans-v18-latin-italic.woff2 +0 -0
  520. package/src/media/fonts/files/open-sans-v18-latin-light-italic.woff +0 -0
  521. package/src/media/fonts/files/open-sans-v18-latin-light-italic.woff2 +0 -0
  522. package/src/media/fonts/files/open-sans-v18-latin-light.woff +0 -0
  523. package/src/media/fonts/files/open-sans-v18-latin-light.woff2 +0 -0
  524. package/src/media/fonts/files/open-sans-v18-latin-regular.woff +0 -0
  525. package/src/media/fonts/files/open-sans-v18-latin-regular.woff2 +0 -0
  526. package/src/test/testCode.doenet +26 -0
  527. package/src/test/testViewer.jsx +158 -0
  528. package/src/uiComponents/ActionButton.jsx +157 -0
  529. package/src/uiComponents/ActionButtonGroup.jsx +93 -0
  530. package/src/uiComponents/Button.jsx +160 -0
  531. package/src/uiComponents/ButtonGroup.jsx +56 -0
  532. package/src/uiComponents/ToggleButton.jsx +194 -0
  533. package/src/uiComponents/ToggleButtonGroup.jsx +77 -0
  534. package/src/utils/activityUtils.js +713 -0
  535. package/src/utils/array.js +17 -0
  536. package/src/utils/cid.js +34 -0
  537. package/src/utils/componentInfoObjects.js +89 -0
  538. package/src/utils/deepFunctions.js +165 -0
  539. package/src/utils/enumeration.js +226 -0
  540. package/src/utils/math.js +624 -0
  541. package/src/utils/naming.js +44 -0
  542. package/src/utils/retrieveTextFile.js +156 -0
  543. package/src/utils/returnAllPossibleVariants.js +81 -0
  544. package/src/utils/sequence.js +715 -0
  545. package/src/utils/serialize.js +29 -0
  546. package/src/utils/serializedStateProcessing.js +2587 -0
  547. package/src/utils/subset-of-reals.js +783 -0
  548. package/src/utils/url.js +19 -0
  549. package/vite.config.js +14 -0
@@ -0,0 +1,2552 @@
1
+ import InlineComponent from "./abstract/InlineComponent";
2
+ import me from "math-expressions";
3
+ import {
4
+ getFromText,
5
+ getFromLatex,
6
+ convertValueToMathExpression,
7
+ normalizeMathExpression,
8
+ roundForDisplay,
9
+ mergeListsWithOtherContainers,
10
+ preprocessMathInverseDefinition,
11
+ superSubscriptsToUnicode,
12
+ unicodeToSuperSubscripts,
13
+ vectorOperators,
14
+ } from "../utils/math";
15
+ import { flattenDeep } from "../utils/array";
16
+ import {
17
+ returnSelectedStyleStateVariableDefinition,
18
+ returnTextStyleDescriptionDefinitions,
19
+ } from "../utils/style";
20
+ import {
21
+ moveGraphicalObjectWithAnchorAction,
22
+ returnAnchorAttributes,
23
+ returnAnchorStateVariableDefinition,
24
+ } from "../utils/graphical";
25
+ import {
26
+ returnRoundingAttributes,
27
+ returnRoundingStateVariableDefinitions,
28
+ returnRoundingAttributeComponentShadowing,
29
+ } from "../utils/rounding";
30
+
31
+ const vectorAndListOperators = ["list", ...vectorOperators];
32
+
33
+ export default class MathComponent extends InlineComponent {
34
+ constructor(args) {
35
+ super(args);
36
+
37
+ Object.assign(this.actions, {
38
+ moveMath: this.moveMath.bind(this),
39
+ mathClicked: this.mathClicked.bind(this),
40
+ mathFocused: this.mathFocused.bind(this),
41
+ });
42
+ }
43
+ static componentType = "math";
44
+
45
+ // used when creating new component via adapter or copy prop
46
+ static primaryStateVariableForDefinition = "unnormalizedValue";
47
+
48
+ // for copying a property with link="false"
49
+ // make sure it doesn't use the essential state variable unnormalizedValue
50
+ static primaryEssentialStateVariable = "value";
51
+
52
+ static variableForPlainMacro = "value";
53
+ static plainMacroReturnsSameType = true;
54
+
55
+ static descendantCompositesMustHaveAReplacement = true;
56
+ static descendantCompositesDefaultReplacementType = "math";
57
+
58
+ static createAttributesObject() {
59
+ let attributes = super.createAttributesObject();
60
+ attributes.format = {
61
+ createComponentOfType: "text",
62
+ createStateVariable: "format",
63
+ defaultValue: "text",
64
+ public: true,
65
+ toLowerCase: true,
66
+ validValues: ["text", "latex"],
67
+ };
68
+ // let simplify="" or simplify="true" be full simplify
69
+ attributes.simplify = {
70
+ createComponentOfType: "text",
71
+ createStateVariable: "simplify",
72
+ defaultValue: "none",
73
+ public: true,
74
+ toLowerCase: true,
75
+ valueTransformations: { "": "full", true: "full", false: "none" },
76
+ validValues: ["none", "full", "numbers", "numberspreserveorder"],
77
+ };
78
+ attributes.expand = {
79
+ createComponentOfType: "boolean",
80
+ createStateVariable: "expand",
81
+ defaultValue: false,
82
+ public: true,
83
+ };
84
+
85
+ Object.assign(attributes, returnRoundingAttributes());
86
+
87
+ attributes.renderMode = {
88
+ createComponentOfType: "text",
89
+ createStateVariable: "renderMode",
90
+ defaultValue: "inline",
91
+ public: true,
92
+ forRenderer: true,
93
+ };
94
+ attributes.unordered = {
95
+ createComponentOfType: "boolean",
96
+ };
97
+ attributes.createVectors = {
98
+ createComponentOfType: "boolean",
99
+ createStateVariable: "createVectors",
100
+ defaultValue: false,
101
+ public: true,
102
+ };
103
+ attributes.createIntervals = {
104
+ createComponentOfType: "boolean",
105
+ createStateVariable: "createIntervals",
106
+ defaultValue: false,
107
+ public: true,
108
+ };
109
+
110
+ attributes.functionSymbols = {
111
+ createComponentOfType: "textList",
112
+ createStateVariable: "functionSymbols",
113
+ defaultValue: ["f", "g"],
114
+ public: true,
115
+ };
116
+
117
+ attributes.sourcesAreFunctionSymbols = {
118
+ createComponentOfType: "textList",
119
+ createStateVariable: "sourcesAreFunctionSymbols",
120
+ defaultValue: [],
121
+ };
122
+
123
+ attributes.splitSymbols = {
124
+ createComponentOfType: "boolean",
125
+ createStateVariable: "splitSymbols",
126
+ defaultValue: true,
127
+ public: true,
128
+ fallBackToParentStateVariable: "splitSymbols",
129
+ };
130
+
131
+ attributes.parseScientificNotation = {
132
+ createComponentOfType: "boolean",
133
+ createStateVariable: "parseScientificNotation",
134
+ defaultValue: false,
135
+ public: true,
136
+ fallBackToParentStateVariable: "parseScientificNotation",
137
+ };
138
+
139
+ attributes.groupCompositeReplacements = {
140
+ createPrimitiveOfType: "boolean",
141
+ createStateVariable: "groupCompositeReplacements",
142
+ defaultValue: true,
143
+ };
144
+
145
+ attributes.displayBlanks = {
146
+ createComponentOfType: "boolean",
147
+ createStateVariable: "displayBlanks",
148
+ defaultValue: true,
149
+ public: true,
150
+ };
151
+
152
+ attributes.draggable = {
153
+ createComponentOfType: "boolean",
154
+ createStateVariable: "draggable",
155
+ defaultValue: true,
156
+ public: true,
157
+ forRenderer: true,
158
+ };
159
+
160
+ attributes.layer = {
161
+ createComponentOfType: "number",
162
+ createStateVariable: "layer",
163
+ defaultValue: 0,
164
+ public: true,
165
+ forRenderer: true,
166
+ };
167
+
168
+ Object.assign(attributes, returnAnchorAttributes());
169
+
170
+ return attributes;
171
+ }
172
+
173
+ static returnChildGroups() {
174
+ return [
175
+ {
176
+ group: "maths",
177
+ componentTypes: ["math"],
178
+ },
179
+ {
180
+ group: "strings",
181
+ componentTypes: ["string"],
182
+ },
183
+ {
184
+ group: "displayedMaths",
185
+ componentTypes: ["m", "me", "men"],
186
+ },
187
+ ];
188
+ }
189
+
190
+ static returnStateVariableDefinitions() {
191
+ let stateVariableDefinitions = super.returnStateVariableDefinitions();
192
+
193
+ let selectedStyleDefinition = returnSelectedStyleStateVariableDefinition();
194
+ Object.assign(stateVariableDefinitions, selectedStyleDefinition);
195
+
196
+ let styleDescriptionDefinitions = returnTextStyleDescriptionDefinitions();
197
+ Object.assign(stateVariableDefinitions, styleDescriptionDefinitions);
198
+
199
+ let anchorDefinition = returnAnchorStateVariableDefinition();
200
+ Object.assign(stateVariableDefinitions, anchorDefinition);
201
+
202
+ let roundingDefinitions = returnRoundingStateVariableDefinitions({
203
+ childsGroupIfSingleMatch: ["maths"],
204
+ childGroupsToStopSingleMatch: ["strings"],
205
+ includeListParents: true,
206
+ });
207
+ Object.assign(stateVariableDefinitions, roundingDefinitions);
208
+
209
+ // valueShadow will be long underscore unless math was created
210
+ // from serialized state with unnormalizedValue
211
+ stateVariableDefinitions.valueShadow = {
212
+ defaultValue: me.fromAst("\uff3f"), // long underscore
213
+ hasEssential: true,
214
+ essentialVarName: "value",
215
+ returnDependencies: () => ({}),
216
+ definition: () => ({
217
+ useEssentialOrDefaultValue: {
218
+ valueShadow: true,
219
+ },
220
+ }),
221
+ inverseDefinition: function ({ desiredStateVariableValues }) {
222
+ return {
223
+ success: true,
224
+ instructions: [
225
+ {
226
+ setEssentialValue: "valueShadow",
227
+ value: desiredStateVariableValues.valueShadow,
228
+ },
229
+ ],
230
+ };
231
+ },
232
+ };
233
+
234
+ stateVariableDefinitions.unordered = {
235
+ defaultValue: false,
236
+ public: true,
237
+ shadowingInstructions: {
238
+ createComponentOfType: "boolean",
239
+ },
240
+ hasEssential: true,
241
+ returnDependencies: () => ({
242
+ unorderedAttr: {
243
+ dependencyType: "attributeComponent",
244
+ attributeName: "unordered",
245
+ variableNames: ["value"],
246
+ },
247
+ mathChildren: {
248
+ dependencyType: "child",
249
+ childGroups: ["maths"],
250
+ variableNames: ["unordered"],
251
+ },
252
+ }),
253
+ definition({ dependencyValues }) {
254
+ if (dependencyValues.unorderedAttr === null) {
255
+ if (dependencyValues.mathChildren.length > 0) {
256
+ let unordered = dependencyValues.mathChildren.every(
257
+ (x) => x.stateValues.unordered,
258
+ );
259
+ return { setValue: { unordered } };
260
+ } else {
261
+ return {
262
+ useEssentialOrDefaultValue: {
263
+ unordered: true,
264
+ },
265
+ };
266
+ }
267
+ } else {
268
+ return {
269
+ setValue: {
270
+ unordered: dependencyValues.unorderedAttr.stateValues.value,
271
+ },
272
+ };
273
+ }
274
+ },
275
+ };
276
+
277
+ stateVariableDefinitions.codePre = {
278
+ // deferCalculation: false,
279
+ returnDependencies: () => ({
280
+ stringChildren: {
281
+ dependencyType: "child",
282
+ childGroups: ["strings"],
283
+ },
284
+ }),
285
+ definition({ dependencyValues }) {
286
+ let codePre = "math";
287
+
288
+ // make sure that codePre is not in any string piece
289
+ let foundInString = false;
290
+ do {
291
+ foundInString = false;
292
+
293
+ for (let child of dependencyValues.stringChildren) {
294
+ if (child.includes(codePre) === true) {
295
+ // found codePre in a string, so extend codePre and try again
296
+ foundInString = true;
297
+ codePre += "m";
298
+ break;
299
+ }
300
+ }
301
+ } while (foundInString);
302
+
303
+ return { setValue: { codePre } };
304
+ },
305
+ };
306
+
307
+ stateVariableDefinitions.mathChildrenFunctionSymbols = {
308
+ returnDependencies: () => ({
309
+ sourcesAreFunctionSymbols: {
310
+ dependencyType: "stateVariable",
311
+ variableName: "sourcesAreFunctionSymbols",
312
+ },
313
+ mathChildren: {
314
+ dependencyType: "child",
315
+ childGroups: ["maths"],
316
+ },
317
+ }),
318
+ definition({ dependencyValues }) {
319
+ let mathChildrenFunctionSymbols = [];
320
+ if (dependencyValues.mathChildren.compositeReplacementRange) {
321
+ for (let compositeInfo of dependencyValues.mathChildren
322
+ .compositeReplacementRange) {
323
+ if (
324
+ dependencyValues.sourcesAreFunctionSymbols.includes(
325
+ compositeInfo.target,
326
+ )
327
+ ) {
328
+ for (
329
+ let ind = compositeInfo.firstInd;
330
+ ind <= compositeInfo.lastInd;
331
+ ind++
332
+ ) {
333
+ mathChildrenFunctionSymbols.push(ind);
334
+ }
335
+ }
336
+ }
337
+ }
338
+
339
+ return { setValue: { mathChildrenFunctionSymbols } };
340
+ },
341
+ };
342
+
343
+ stateVariableDefinitions.expressionWithCodes = {
344
+ hasEssential: true,
345
+ doNotShadowEssential: true,
346
+ returnDependencies: () => ({
347
+ stringMathChildren: {
348
+ dependencyType: "child",
349
+ childGroups: ["strings", "maths"],
350
+ },
351
+ // have stringChildren and mathChildren just for inverse definition
352
+ stringChildren: {
353
+ dependencyType: "child",
354
+ childGroups: ["strings"],
355
+ },
356
+ mathChildren: {
357
+ dependencyType: "child",
358
+ childGroups: ["maths"],
359
+ },
360
+ displayedMathChildren: {
361
+ dependencyType: "child",
362
+ childGroups: ["displayedMaths"],
363
+ variableNames: ["latex"],
364
+ },
365
+ format: {
366
+ dependencyType: "stateVariable",
367
+ variableName: "format",
368
+ },
369
+ codePre: {
370
+ dependencyType: "stateVariable",
371
+ variableName: "codePre",
372
+ },
373
+ functionSymbols: {
374
+ dependencyType: "stateVariable",
375
+ variableName: "functionSymbols",
376
+ },
377
+ mathChildrenFunctionSymbols: {
378
+ dependencyType: "stateVariable",
379
+ variableName: "mathChildrenFunctionSymbols",
380
+ },
381
+ splitSymbols: {
382
+ dependencyType: "stateVariable",
383
+ variableName: "splitSymbols",
384
+ },
385
+ parseScientificNotation: {
386
+ dependencyType: "stateVariable",
387
+ variableName: "parseScientificNotation",
388
+ },
389
+ groupCompositeReplacements: {
390
+ dependencyType: "stateVariable",
391
+ variableName: "groupCompositeReplacements",
392
+ },
393
+ }),
394
+ set: (x) => (x === null ? null : convertValueToMathExpression(x)),
395
+ definition: calculateExpressionWithCodes,
396
+ async inverseDefinition({
397
+ desiredStateVariableValues,
398
+ dependencyValues,
399
+ stateValues,
400
+ }) {
401
+ let newExpressionWithCodes =
402
+ desiredStateVariableValues.expressionWithCodes;
403
+
404
+ let instructions = [
405
+ {
406
+ setEssentialValue: "expressionWithCodes",
407
+ value: newExpressionWithCodes,
408
+ },
409
+ ];
410
+
411
+ let nStringChildren = dependencyValues.stringChildren.length;
412
+
413
+ if (nStringChildren === 0) {
414
+ // don't use expressionWithCodes if no children
415
+ // and expressionWithCodes will not change if no string children
416
+ return { success: false };
417
+ }
418
+
419
+ if (dependencyValues.mathChildren.length === 0) {
420
+ // just string children. Set first to value, the rest to empty strings
421
+ let stringValue;
422
+ if ((await stateValues.format) === "latex") {
423
+ stringValue = newExpressionWithCodes.toLatex();
424
+ } else {
425
+ stringValue = newExpressionWithCodes.toString();
426
+ }
427
+
428
+ instructions.push({
429
+ setDependency: "stringChildren",
430
+ desiredValue: stringValue,
431
+ childIndex: 0,
432
+ variableIndex: 0,
433
+ ignoreChildChangeForComponent: true,
434
+ });
435
+
436
+ for (let ind = 1; ind < nStringChildren; ind++) {
437
+ instructions.push({
438
+ setDependency: "stringChildren",
439
+ desiredValue: "",
440
+ childIndex: ind,
441
+ variableIndex: 0,
442
+ ignoreChildChangeForComponent: true,
443
+ });
444
+ }
445
+ } else {
446
+ // have math children
447
+
448
+ let stringExpr;
449
+ if ((await stateValues.format) === "latex") {
450
+ stringExpr = newExpressionWithCodes.toLatex();
451
+ } else {
452
+ stringExpr = newExpressionWithCodes.toString();
453
+ }
454
+
455
+ for (let [ind, stringCodes] of (
456
+ await stateValues.codesAdjacentToStrings
457
+ ).entries()) {
458
+ let thisString = stringExpr;
459
+ if (Object.keys(stringCodes).length === 0) {
460
+ // string was skipped, so set it to an empty string
461
+ instructions.push({
462
+ setDependency: "stringChildren",
463
+ desiredValue: "",
464
+ childIndex: ind,
465
+ variableIndex: 0,
466
+ ignoreChildChangeForComponent: true,
467
+ });
468
+ } else {
469
+ if (stringCodes.prevCode) {
470
+ thisString = thisString.split(stringCodes.prevCode)[1];
471
+ }
472
+ if (stringCodes.nextCode) {
473
+ thisString = thisString.split(stringCodes.nextCode)[0];
474
+ }
475
+ instructions.push({
476
+ setDependency: "stringChildren",
477
+ desiredValue: thisString,
478
+ childIndex: ind,
479
+ variableIndex: 0,
480
+ ignoreChildChangeForComponent: true,
481
+ });
482
+ }
483
+ }
484
+ }
485
+
486
+ return {
487
+ success: true,
488
+ instructions,
489
+ };
490
+ },
491
+ };
492
+
493
+ stateVariableDefinitions.mathChildrenWithCanBeModified = {
494
+ returnDependencies: () => ({
495
+ mathChildren: {
496
+ dependencyType: "child",
497
+ childGroups: ["maths"],
498
+ variableNames: ["value", "canBeModified"],
499
+ },
500
+ }),
501
+ definition: ({ dependencyValues }) => ({
502
+ setValue: {
503
+ mathChildrenWithCanBeModified: dependencyValues.mathChildren,
504
+ },
505
+ }),
506
+ };
507
+
508
+ stateVariableDefinitions.unnormalizedValue = {
509
+ returnDependencies: () => ({
510
+ mathChildren: {
511
+ dependencyType: "child",
512
+ childGroups: ["maths"],
513
+ variableNames: ["value"],
514
+ },
515
+ // Note: need stringChildren for inverse definition
516
+ // (even though not in definition)
517
+ stringChildren: {
518
+ dependencyType: "child",
519
+ childGroups: ["strings"],
520
+ variableNames: ["value"],
521
+ },
522
+ expressionWithCodes: {
523
+ dependencyType: "stateVariable",
524
+ variableName: "expressionWithCodes",
525
+ },
526
+ codePre: {
527
+ dependencyType: "stateVariable",
528
+ variableName: "codePre",
529
+ },
530
+ valueShadow: {
531
+ dependencyType: "stateVariable",
532
+ variableName: "valueShadow",
533
+ },
534
+ }),
535
+ set: convertValueToMathExpression,
536
+ defaultValue: me.fromAst("\uff3f"), // long underscore
537
+ definition: calculateMathValue,
538
+ inverseDefinition: invertMath,
539
+ };
540
+
541
+ stateVariableDefinitions.value = {
542
+ public: true,
543
+ shadowingInstructions: {
544
+ createComponentOfType: this.componentType,
545
+ attributesToShadow: ["unordered", "simplify", "expand"],
546
+ // the reason we create a attribute component from the state variable fixed,
547
+ // rather than just shadowing the attribute,
548
+ // is that a sequence creates a math where it sets fixed directly in the state
549
+ addAttributeComponentsShadowingStateVariables: {
550
+ fixed: {
551
+ stateVariableToShadow: "fixed",
552
+ },
553
+ ...returnRoundingAttributeComponentShadowing(),
554
+ },
555
+ },
556
+ returnDependencies: () => ({
557
+ unnormalizedValue: {
558
+ dependencyType: "stateVariable",
559
+ variableName: "unnormalizedValue",
560
+ },
561
+ simplify: {
562
+ dependencyType: "stateVariable",
563
+ variableName: "simplify",
564
+ },
565
+ expand: {
566
+ dependencyType: "stateVariable",
567
+ variableName: "expand",
568
+ },
569
+ createVectors: {
570
+ dependencyType: "stateVariable",
571
+ variableName: "createVectors",
572
+ },
573
+ createIntervals: {
574
+ dependencyType: "stateVariable",
575
+ variableName: "createIntervals",
576
+ },
577
+ }),
578
+ definition: function ({ dependencyValues }) {
579
+ let value = dependencyValues.unnormalizedValue;
580
+
581
+ let { simplify, expand, createVectors, createIntervals } =
582
+ dependencyValues;
583
+
584
+ value = normalizeMathExpression({
585
+ value,
586
+ simplify,
587
+ expand,
588
+ createVectors,
589
+ createIntervals,
590
+ });
591
+
592
+ return { setValue: { value } };
593
+ },
594
+ inverseDefinition: function ({ desiredStateVariableValues }) {
595
+ return {
596
+ success: true,
597
+ instructions: [
598
+ {
599
+ setDependency: "unnormalizedValue",
600
+ desiredValue: desiredStateVariableValues.value,
601
+ },
602
+ ],
603
+ };
604
+ },
605
+ };
606
+
607
+ stateVariableDefinitions.number = {
608
+ public: true,
609
+ shadowingInstructions: {
610
+ createComponentOfType: "number",
611
+ addAttributeComponentsShadowingStateVariables:
612
+ returnRoundingAttributeComponentShadowing(),
613
+ },
614
+ returnDependencies: () => ({
615
+ value: {
616
+ dependencyType: "stateVariable",
617
+ variableName: "value",
618
+ },
619
+ }),
620
+ definition: function ({ dependencyValues }) {
621
+ let number = dependencyValues.value.evaluate_to_constant();
622
+ return { setValue: { number } };
623
+ },
624
+ inverseDefinition: function ({ desiredStateVariableValues }) {
625
+ return {
626
+ success: true,
627
+ instructions: [
628
+ {
629
+ setDependency: "value",
630
+ desiredValue: me.fromAst(desiredStateVariableValues.number),
631
+ },
632
+ ],
633
+ };
634
+ },
635
+ };
636
+
637
+ // isNumber is true if the value of the math is an actual number
638
+ stateVariableDefinitions.isNumber = {
639
+ public: true,
640
+ shadowingInstructions: {
641
+ createComponentOfType: "boolean",
642
+ },
643
+ returnDependencies: () => ({
644
+ value: {
645
+ dependencyType: "stateVariable",
646
+ variableName: "value",
647
+ },
648
+ }),
649
+ definition: function ({ dependencyValues }) {
650
+ return {
651
+ setValue: {
652
+ isNumber: Number.isFinite(dependencyValues.value.tree),
653
+ },
654
+ };
655
+ },
656
+ };
657
+
658
+ // isNumeric is weaker than isNumber
659
+ // isNumeric is true if the value can be evaluated as a number,
660
+ // i.e., if the number state variable is a number
661
+ stateVariableDefinitions.isNumeric = {
662
+ public: true,
663
+ shadowingInstructions: {
664
+ createComponentOfType: "boolean",
665
+ },
666
+ returnDependencies: () => ({
667
+ number: {
668
+ dependencyType: "stateVariable",
669
+ variableName: "number",
670
+ },
671
+ }),
672
+ definition: function ({ dependencyValues }) {
673
+ return {
674
+ setValue: {
675
+ isNumeric: Number.isFinite(dependencyValues.number),
676
+ },
677
+ };
678
+ },
679
+ };
680
+
681
+ stateVariableDefinitions.valueForDisplay = {
682
+ returnDependencies: () => ({
683
+ value: {
684
+ dependencyType: "stateVariable",
685
+ variableName: "value",
686
+ },
687
+ displayDigits: {
688
+ dependencyType: "stateVariable",
689
+ variableName: "displayDigits",
690
+ },
691
+ displayDecimals: {
692
+ dependencyType: "stateVariable",
693
+ variableName: "displayDecimals",
694
+ },
695
+ displaySmallAsZero: {
696
+ dependencyType: "stateVariable",
697
+ variableName: "displaySmallAsZero",
698
+ },
699
+ simplify: {
700
+ dependencyType: "stateVariable",
701
+ variableName: "simplify",
702
+ },
703
+ expand: {
704
+ dependencyType: "stateVariable",
705
+ variableName: "expand",
706
+ },
707
+ }),
708
+ definition: function ({ dependencyValues }) {
709
+ // for display via latex and text, round any decimal numbers to the significant digits
710
+ // determined by displaydigits, displaydecimals, and/or displaySmallAsZero
711
+ let rounded = roundForDisplay({
712
+ value: dependencyValues.value,
713
+ dependencyValues,
714
+ });
715
+
716
+ return {
717
+ setValue: {
718
+ valueForDisplay: normalizeMathExpression({
719
+ value: rounded,
720
+ simplify: dependencyValues.simplify,
721
+ expand: dependencyValues.expand,
722
+ }),
723
+ },
724
+ };
725
+ },
726
+ inverseDefinition({ desiredStateVariableValues }) {
727
+ return {
728
+ success: true,
729
+ instructions: [
730
+ {
731
+ setDependency: "value",
732
+ desiredValue: desiredStateVariableValues.valueForDisplay,
733
+ },
734
+ ],
735
+ };
736
+ },
737
+ };
738
+
739
+ stateVariableDefinitions.latex = {
740
+ public: true,
741
+ forRenderer: true,
742
+ shadowingInstructions: {
743
+ createComponentOfType: "latex",
744
+ },
745
+ returnDependencies: () => ({
746
+ valueForDisplay: {
747
+ dependencyType: "stateVariable",
748
+ variableName: "valueForDisplay",
749
+ },
750
+ padZeros: {
751
+ dependencyType: "stateVariable",
752
+ variableName: "padZeros",
753
+ },
754
+ displayDigits: {
755
+ dependencyType: "stateVariable",
756
+ variableName: "displayDigits",
757
+ },
758
+ displayDecimals: {
759
+ dependencyType: "stateVariable",
760
+ variableName: "displayDecimals",
761
+ },
762
+ displayBlanks: {
763
+ dependencyType: "stateVariable",
764
+ variableName: "displayBlanks",
765
+ },
766
+ }),
767
+ definition: function ({ dependencyValues }) {
768
+ let latex;
769
+ let params = {};
770
+ if (dependencyValues.padZeros) {
771
+ if (Number.isFinite(dependencyValues.displayDecimals)) {
772
+ params.padToDecimals = dependencyValues.displayDecimals;
773
+ }
774
+ if (dependencyValues.displayDigits >= 1) {
775
+ params.padToDigits = dependencyValues.displayDigits;
776
+ }
777
+ }
778
+ if (!dependencyValues.displayBlanks) {
779
+ params.showBlanks = false;
780
+ }
781
+ try {
782
+ latex = dependencyValues.valueForDisplay.toLatex(params);
783
+ } catch (e) {
784
+ if (dependencyValues.displayBlanks) {
785
+ latex = "\uff3f";
786
+ } else {
787
+ latex = "";
788
+ }
789
+ }
790
+ return { setValue: { latex } };
791
+ },
792
+ inverseDefinition({ desiredStateVariableValues }) {
793
+ let value;
794
+ try {
795
+ value = me.fromLatex(desiredStateVariableValues.latex);
796
+ } catch (e) {
797
+ return { success: false };
798
+ }
799
+ return {
800
+ success: true,
801
+ instructions: [
802
+ {
803
+ setDependency: "valueForDisplay",
804
+ desiredValue: value,
805
+ },
806
+ ],
807
+ };
808
+ },
809
+ };
810
+
811
+ stateVariableDefinitions.latexWithInputChildren = {
812
+ forRenderer: true,
813
+ returnDependencies: () => ({
814
+ latex: {
815
+ dependencyType: "stateVariable",
816
+ variableName: "latex",
817
+ },
818
+ }),
819
+ definition: function ({ dependencyValues }) {
820
+ return {
821
+ setValue: { latexWithInputChildren: [dependencyValues.latex] },
822
+ };
823
+ },
824
+ };
825
+
826
+ stateVariableDefinitions.text = {
827
+ public: true,
828
+ shadowingInstructions: {
829
+ createComponentOfType: "text",
830
+ },
831
+ returnDependencies: () => ({
832
+ valueForDisplay: {
833
+ dependencyType: "stateVariable",
834
+ variableName: "valueForDisplay",
835
+ },
836
+ padZeros: {
837
+ dependencyType: "stateVariable",
838
+ variableName: "padZeros",
839
+ },
840
+ displayDigits: {
841
+ dependencyType: "stateVariable",
842
+ variableName: "displayDigits",
843
+ },
844
+ displayDecimals: {
845
+ dependencyType: "stateVariable",
846
+ variableName: "displayDecimals",
847
+ },
848
+ value: {
849
+ dependencyType: "stateVariable",
850
+ variableName: "value",
851
+ onlyToSetInInverseDefinition: true,
852
+ },
853
+ displayBlanks: {
854
+ dependencyType: "stateVariable",
855
+ variableName: "displayBlanks",
856
+ },
857
+ }),
858
+ definition: function ({ dependencyValues }) {
859
+ let text;
860
+ let params = {};
861
+ if (dependencyValues.padZeros) {
862
+ if (Number.isFinite(dependencyValues.displayDecimals)) {
863
+ params.padToDecimals = dependencyValues.displayDecimals;
864
+ }
865
+ if (dependencyValues.displayDigits >= 1) {
866
+ params.padToDigits = dependencyValues.displayDigits;
867
+ }
868
+ }
869
+ if (!dependencyValues.displayBlanks) {
870
+ params.showBlanks = false;
871
+ }
872
+ try {
873
+ text = dependencyValues.valueForDisplay.toString(params);
874
+ } catch (e) {
875
+ if (dependencyValues.displayBlanks) {
876
+ text = "\uff3f";
877
+ } else {
878
+ text = "";
879
+ }
880
+ }
881
+ return {
882
+ setValue: { text: superSubscriptsToUnicode(text.toString()) },
883
+ };
884
+ },
885
+ async inverseDefinition({ desiredStateVariableValues, stateValues }) {
886
+ let fromText = getFromText({
887
+ functionSymbols: await stateValues.functionSymbols,
888
+ splitSymbols: await stateValues.splitSymbols,
889
+ parseScientificNotation: await stateValues.parseScientificNotation,
890
+ });
891
+
892
+ let expr;
893
+ try {
894
+ expr = fromText(
895
+ unicodeToSuperSubscripts(desiredStateVariableValues.text),
896
+ );
897
+ } catch (e) {
898
+ return { success: false };
899
+ }
900
+
901
+ return {
902
+ success: true,
903
+ instructions: [
904
+ {
905
+ setDependency: "value",
906
+ desiredValue: expr,
907
+ },
908
+ ],
909
+ };
910
+ },
911
+ };
912
+
913
+ stateVariableDefinitions.codesAdjacentToStrings = {
914
+ returnDependencies: () => ({
915
+ stringMathChildren: {
916
+ dependencyType: "child",
917
+ childGroups: ["strings", "maths"],
918
+ },
919
+ codePre: {
920
+ dependencyType: "stateVariable",
921
+ variableName: "codePre",
922
+ },
923
+ format: {
924
+ dependencyType: "stateVariable",
925
+ variableName: "format",
926
+ },
927
+ }),
928
+ definition: calculateCodesAdjacentToStrings,
929
+ };
930
+
931
+ stateVariableDefinitions.canBeModified = {
932
+ additionalStateVariablesDefined: [
933
+ "constantChildIndices",
934
+ "codeForExpression",
935
+ "inverseMaps",
936
+ "template",
937
+ "mathChildrenMapped",
938
+ ],
939
+ returnDependencies: () => ({
940
+ mathChildrenModifiable: {
941
+ dependencyType: "child",
942
+ childGroups: ["maths"],
943
+ variableNames: ["canBeModified"],
944
+ },
945
+ displayedMathChildren: {
946
+ dependencyType: "child",
947
+ childGroups: ["displayedMaths"],
948
+ },
949
+ expressionWithCodes: {
950
+ dependencyType: "stateVariable",
951
+ variableName: "expressionWithCodes",
952
+ },
953
+ modifyIndirectly: {
954
+ dependencyType: "stateVariable",
955
+ variableName: "modifyIndirectly",
956
+ },
957
+ fixed: {
958
+ dependencyType: "stateVariable",
959
+ variableName: "fixed",
960
+ },
961
+ codePre: {
962
+ dependencyType: "stateVariable",
963
+ variableName: "codePre",
964
+ },
965
+ }),
966
+ definition: determineCanBeModified,
967
+ };
968
+
969
+ stateVariableDefinitions.mathChildrenByVectorComponent = {
970
+ returnDependencies: () => ({
971
+ codePre: {
972
+ dependencyType: "stateVariable",
973
+ variableName: "codePre",
974
+ },
975
+ mathChildren: {
976
+ dependencyType: "child",
977
+ childGroups: ["maths"],
978
+ },
979
+ expressionWithCodes: {
980
+ dependencyType: "stateVariable",
981
+ variableName: "expressionWithCodes",
982
+ },
983
+ }),
984
+ definition: function ({ dependencyValues }) {
985
+ if (dependencyValues.expressionWithCodes === null) {
986
+ return { setValue: { mathChildrenByVectorComponent: null } };
987
+ }
988
+ let expressionWithCodesTree = dependencyValues.expressionWithCodes.tree;
989
+ let nMathChildren = dependencyValues.mathChildren.length;
990
+
991
+ if (
992
+ nMathChildren === 0 ||
993
+ !Array.isArray(expressionWithCodesTree) ||
994
+ !vectorOperators.includes(expressionWithCodesTree[0])
995
+ ) {
996
+ return { setValue: { mathChildrenByVectorComponent: null } };
997
+ }
998
+
999
+ let mathChildrenByVectorComponent = {};
1000
+
1001
+ let childInd = 0;
1002
+ let childCode = dependencyValues.codePre + childInd;
1003
+
1004
+ for (let ind = 1; ind < expressionWithCodesTree.length; ind++) {
1005
+ let exprComp = expressionWithCodesTree[ind];
1006
+ let mc = (mathChildrenByVectorComponent[ind] = []);
1007
+
1008
+ if (Array.isArray(exprComp)) {
1009
+ let flattenedComp = flattenDeep(exprComp);
1010
+ while (flattenedComp.includes(childCode)) {
1011
+ mc.push(childInd);
1012
+ childInd++;
1013
+ childCode = dependencyValues.codePre + childInd;
1014
+ }
1015
+ } else {
1016
+ if (exprComp === childCode) {
1017
+ mc.push(childInd);
1018
+ childInd++;
1019
+ childCode = dependencyValues.codePre + childInd;
1020
+ }
1021
+ }
1022
+
1023
+ if (childInd >= nMathChildren) {
1024
+ break;
1025
+ }
1026
+ }
1027
+
1028
+ return { setValue: { mathChildrenByVectorComponent } };
1029
+ },
1030
+ };
1031
+
1032
+ stateVariableDefinitions.numDimensions = {
1033
+ public: true,
1034
+ shadowingInstructions: {
1035
+ createComponentOfType: "integer",
1036
+ },
1037
+ returnDependencies: () => ({
1038
+ value: {
1039
+ dependencyType: "stateVariable",
1040
+ variableName: "value",
1041
+ },
1042
+ }),
1043
+ definition({ dependencyValues }) {
1044
+ let numDimensions = 1;
1045
+
1046
+ let tree = dependencyValues.value.tree;
1047
+
1048
+ if (Array.isArray(tree)) {
1049
+ if (vectorAndListOperators.includes(tree[0])) {
1050
+ numDimensions = tree.length - 1;
1051
+ } else if (tree[0] === "matrix") {
1052
+ let size = tree[1].slice(1);
1053
+
1054
+ if (size[0] === 1) {
1055
+ numDimensions = size[1];
1056
+ } else if (size[1] === 1) {
1057
+ numDimensions = size[0];
1058
+ }
1059
+ } else if (
1060
+ vectorOperators.includes(tree[1][0]) &&
1061
+ ((tree[0] === "^" && tree[2] === "T") || tree[0] === "prime")
1062
+ ) {
1063
+ numDimensions = tree[1].length - 1;
1064
+ }
1065
+ }
1066
+
1067
+ return { setValue: { numDimensions } };
1068
+ },
1069
+ };
1070
+
1071
+ stateVariableDefinitions.vector = {
1072
+ public: true,
1073
+ shadowingInstructions: {
1074
+ createComponentOfType: "math",
1075
+ addAttributeComponentsShadowingStateVariables:
1076
+ returnRoundingAttributeComponentShadowing(),
1077
+ returnWrappingComponents(prefix) {
1078
+ if (prefix === "x") {
1079
+ return [];
1080
+ } else {
1081
+ // entire array
1082
+ // wrap by both <vector> and <xs>
1083
+ return [
1084
+ ["vector", { componentType: "mathList", isAttribute: "xs" }],
1085
+ ];
1086
+ }
1087
+ },
1088
+ },
1089
+ isArray: true,
1090
+ entryPrefixes: ["x"],
1091
+ returnArraySizeDependencies: () => ({
1092
+ numDimensions: {
1093
+ dependencyType: "stateVariable",
1094
+ variableName: "numDimensions",
1095
+ },
1096
+ }),
1097
+ returnArraySize({ dependencyValues }) {
1098
+ return [dependencyValues.numDimensions];
1099
+ },
1100
+ returnArrayDependenciesByKey() {
1101
+ let globalDependencies = {
1102
+ value: {
1103
+ dependencyType: "stateVariable",
1104
+ variableName: "value",
1105
+ },
1106
+ };
1107
+ return { globalDependencies };
1108
+ },
1109
+ arrayDefinitionByKey({ globalDependencyValues, arraySize }) {
1110
+ let tree = globalDependencyValues.value.tree;
1111
+
1112
+ let createdVector = false;
1113
+
1114
+ let vector = {};
1115
+ if (Array.isArray(tree)) {
1116
+ if (vectorAndListOperators.includes(tree[0])) {
1117
+ for (let ind = 0; ind < arraySize[0]; ind++) {
1118
+ vector[ind] = me.fromAst(tree[ind + 1]);
1119
+ }
1120
+ createdVector = true;
1121
+ } else if (tree[0] === "matrix") {
1122
+ let size = tree[1].slice(1);
1123
+ if (size[0] === 1) {
1124
+ for (let ind = 0; ind < arraySize[0]; ind++) {
1125
+ vector[ind] = me.fromAst(tree[2][1][ind + 1]);
1126
+ }
1127
+ createdVector = true;
1128
+ } else if (size[1] === 1) {
1129
+ for (let ind = 0; ind < arraySize[0]; ind++) {
1130
+ vector[ind] = me.fromAst(tree[2][ind + 1][1]);
1131
+ }
1132
+ createdVector = true;
1133
+ }
1134
+ } else if (
1135
+ vectorOperators.includes(tree[1][0]) &&
1136
+ ((tree[0] === "^" && tree[2] === "T") || tree[0] === "prime")
1137
+ ) {
1138
+ for (let ind = 0; ind < arraySize[0]; ind++) {
1139
+ vector[ind] = me.fromAst(tree[1][ind + 1]);
1140
+ }
1141
+ createdVector = true;
1142
+ }
1143
+ }
1144
+ if (!createdVector) {
1145
+ vector[0] = globalDependencyValues.value;
1146
+ }
1147
+
1148
+ return { setValue: { vector } };
1149
+ },
1150
+ async inverseArrayDefinitionByKey({
1151
+ desiredStateVariableValues,
1152
+ globalDependencyValues,
1153
+ stateValues,
1154
+ workspace,
1155
+ arraySize,
1156
+ }) {
1157
+ // in case just one ind specified, merge with previous values
1158
+ if (!workspace.desiredVector) {
1159
+ workspace.desiredVector = [];
1160
+ }
1161
+ for (let ind = 0; ind < arraySize[0]; ind++) {
1162
+ if (desiredStateVariableValues.vector[ind] !== undefined) {
1163
+ workspace.desiredVector[ind] = convertValueToMathExpression(
1164
+ desiredStateVariableValues.vector[ind],
1165
+ );
1166
+ } else if (workspace.desiredVector[ind] === undefined) {
1167
+ workspace.desiredVector[ind] = (await stateValues.vector)[ind];
1168
+ }
1169
+ }
1170
+
1171
+ let desiredValue;
1172
+ let tree = globalDependencyValues.value.tree;
1173
+ if (Array.isArray(tree)) {
1174
+ if (vectorAndListOperators.includes(tree[0])) {
1175
+ desiredValue = me.fromAst([
1176
+ tree[0],
1177
+ ...workspace.desiredVector.map((x) => x.tree),
1178
+ ]);
1179
+ } else if (tree[0] === "matrix") {
1180
+ let size = tree[1].slice(1);
1181
+ if (size[0] === 1) {
1182
+ let desiredMatrixVals = ["tuple"];
1183
+ for (let ind = 0; ind < arraySize[0]; ind++) {
1184
+ desiredMatrixVals.push(workspace.desiredVector[ind]);
1185
+ }
1186
+ desiredMatrixVals = ["tuple", desiredMatrixVals];
1187
+ desiredValue = me.fromAst(["matrix", tree[1], desiredMatrixVals]);
1188
+ } else if (size[1] === 1) {
1189
+ let desiredMatrixVals = ["tuple"];
1190
+ for (let ind = 0; ind < arraySize[0]; ind++) {
1191
+ desiredMatrixVals.push(["tuple", workspace.desiredVector[ind]]);
1192
+ }
1193
+ desiredValue = me.fromAst(["matrix", tree[1], desiredMatrixVals]);
1194
+ }
1195
+ } else if (
1196
+ vectorOperators.includes(tree[1][0]) &&
1197
+ ((tree[0] === "^" && tree[2] === "T") || tree[0] === "prime")
1198
+ ) {
1199
+ desiredValue = [
1200
+ tree[0],
1201
+ [tree[1][0], ...workspace.desiredVector.map((x) => x.tree)],
1202
+ ];
1203
+ if (tree[2]) {
1204
+ desiredValue.push(tree[2]);
1205
+ }
1206
+ desiredValue = me.fromAst(desiredValue);
1207
+ }
1208
+ }
1209
+
1210
+ if (!desiredValue) {
1211
+ desiredValue = workspace.desiredVector[0];
1212
+ }
1213
+
1214
+ let instructions = [
1215
+ {
1216
+ setDependency: "value",
1217
+ desiredValue,
1218
+ },
1219
+ ];
1220
+
1221
+ return {
1222
+ success: true,
1223
+ instructions,
1224
+ };
1225
+ },
1226
+ };
1227
+
1228
+ stateVariableDefinitions.x = {
1229
+ isAlias: true,
1230
+ targetVariableName: "x1",
1231
+ };
1232
+
1233
+ stateVariableDefinitions.y = {
1234
+ isAlias: true,
1235
+ targetVariableName: "x2",
1236
+ };
1237
+
1238
+ stateVariableDefinitions.z = {
1239
+ isAlias: true,
1240
+ targetVariableName: "x3",
1241
+ };
1242
+
1243
+ stateVariableDefinitions.matrixSize = {
1244
+ public: true,
1245
+ shadowingInstructions: {
1246
+ createComponentOfType: "numberList",
1247
+ },
1248
+ returnDependencies: () => ({
1249
+ value: {
1250
+ dependencyType: "stateVariable",
1251
+ variableName: "value",
1252
+ },
1253
+ }),
1254
+ definition({ dependencyValues }) {
1255
+ let matrixSize = [1, 1];
1256
+
1257
+ let tree = dependencyValues.value.tree;
1258
+
1259
+ if (Array.isArray(tree)) {
1260
+ if (vectorAndListOperators.includes(tree[0])) {
1261
+ matrixSize = [tree.length - 1, 1];
1262
+ } else if (tree[0] === "matrix") {
1263
+ matrixSize = tree[1].slice(1);
1264
+ } else if (
1265
+ vectorOperators.includes(tree[1][0]) &&
1266
+ ((tree[0] === "^" && tree[2] === "T") || tree[0] === "prime")
1267
+ ) {
1268
+ matrixSize = [1, tree[1].length - 1];
1269
+ }
1270
+ }
1271
+
1272
+ return { setValue: { matrixSize } };
1273
+ },
1274
+ };
1275
+
1276
+ stateVariableDefinitions.numRows = {
1277
+ public: true,
1278
+ shadowingInstructions: {
1279
+ createComponentOfType: "integer",
1280
+ },
1281
+ returnDependencies: () => ({
1282
+ matrixSize: {
1283
+ dependencyType: "stateVariable",
1284
+ variableName: "matrixSize",
1285
+ },
1286
+ }),
1287
+ definition({ dependencyValues }) {
1288
+ return { setValue: { numRows: dependencyValues.matrixSize[0] } };
1289
+ },
1290
+ };
1291
+
1292
+ stateVariableDefinitions.numColumns = {
1293
+ public: true,
1294
+ shadowingInstructions: {
1295
+ createComponentOfType: "integer",
1296
+ },
1297
+ returnDependencies: () => ({
1298
+ matrixSize: {
1299
+ dependencyType: "stateVariable",
1300
+ variableName: "matrixSize",
1301
+ },
1302
+ }),
1303
+ definition({ dependencyValues }) {
1304
+ return { setValue: { numColumns: dependencyValues.matrixSize[1] } };
1305
+ },
1306
+ };
1307
+
1308
+ stateVariableDefinitions.matrix = {
1309
+ public: true,
1310
+ shadowingInstructions: {
1311
+ createComponentOfType: "math",
1312
+ addAttributeComponentsShadowingStateVariables:
1313
+ returnRoundingAttributeComponentShadowing(),
1314
+ returnWrappingComponents(prefix) {
1315
+ if (prefix === "matrixEntry") {
1316
+ return [];
1317
+ } else if (prefix === "row") {
1318
+ return [["matrix", "matrixRow"]];
1319
+ } else if (prefix === "column") {
1320
+ return [["matrix", "matrixColumn"]];
1321
+ } else {
1322
+ // entire matrix
1323
+ // wrap inner dimension by matrixRow and outer dimension by matrix
1324
+ // don't wrap outer dimension (for entire array)
1325
+ return [["matrixRow"], ["matrix"]];
1326
+ }
1327
+ },
1328
+ },
1329
+ isArray: true,
1330
+ numDimensions: 2,
1331
+ entryPrefixes: ["matrixEntry", "row", "column", "rows", "columns"],
1332
+ getArrayKeysFromVarName({ arrayEntryPrefix, varEnding, arraySize }) {
1333
+ if (arrayEntryPrefix === "matrixEntry") {
1334
+ // matrixEntry1_2 is the 2nd entry from the first row
1335
+ let indices = varEnding.split("_").map((x) => Number(x) - 1);
1336
+ if (
1337
+ indices.length === 2 &&
1338
+ indices.every((x) => Number.isInteger(x) && x >= 0)
1339
+ ) {
1340
+ if (arraySize) {
1341
+ if (indices.every((x, i) => x < arraySize[i])) {
1342
+ return [String(indices)];
1343
+ } else {
1344
+ return [];
1345
+ }
1346
+ } else {
1347
+ // If not given the array size,
1348
+ // then return the array keys assuming the array is large enough.
1349
+ // Must do this as it is used to determine potential array entries.
1350
+ return [String(indices)];
1351
+ }
1352
+ } else {
1353
+ return [];
1354
+ }
1355
+ } else if (arrayEntryPrefix === "row") {
1356
+ // row3 is all components of the third row
1357
+
1358
+ let rowInd = Number(varEnding) - 1;
1359
+ if (!(Number.isInteger(rowInd) && rowInd >= 0)) {
1360
+ return [];
1361
+ }
1362
+
1363
+ if (!arraySize) {
1364
+ // If don't have array size, we just need to determine if it is a potential entry.
1365
+ // Return the first entry assuming array is large enough
1366
+ return [rowInd + ",0"];
1367
+ }
1368
+ if (rowInd < arraySize[0]) {
1369
+ // array of "rowInd,i", where i=0, ..., arraySize[1]-1
1370
+ return Array.from(Array(arraySize[1]), (_, i) => rowInd + "," + i);
1371
+ } else {
1372
+ return [];
1373
+ }
1374
+ } else if (arrayEntryPrefix === "column") {
1375
+ // column3 is all components of the third column
1376
+
1377
+ let colInd = Number(varEnding) - 1;
1378
+ if (!(Number.isInteger(colInd) && colInd >= 0)) {
1379
+ return [];
1380
+ }
1381
+
1382
+ if (!arraySize) {
1383
+ // If don't have array size, we just need to determine if it is a potential entry.
1384
+ // Return the first entry assuming array is large enough
1385
+ return ["0," + colInd];
1386
+ }
1387
+ if (colInd < arraySize[1]) {
1388
+ // array of "i,colInd", where i=0, ..., arraySize[1]-1
1389
+ return Array.from(Array(arraySize[0]), (_, i) => i + "," + colInd);
1390
+ } else {
1391
+ return [];
1392
+ }
1393
+ } else if (
1394
+ arrayEntryPrefix === "rows" ||
1395
+ arrayEntryPrefix === "columns"
1396
+ ) {
1397
+ // rows or columns is the whole matrix
1398
+ // (this are designed for getting rows and columns using propIndex)
1399
+ // (rows and matrix are the same, but rows is added to be parallel to columns)
1400
+
1401
+ if (!arraySize) {
1402
+ // If don't have array size, we justr eturn the first entry
1403
+ return ["0,0"];
1404
+ }
1405
+ let keys = [];
1406
+ for (let rowInd = 0; rowInd < arraySize[0]; rowInd++) {
1407
+ keys.push(
1408
+ ...Array.from(Array(arraySize[1]), (_, i) => rowInd + "," + i),
1409
+ );
1410
+ }
1411
+ return keys;
1412
+ }
1413
+ },
1414
+ arrayVarNameFromPropIndex(propIndex, varName) {
1415
+ if (varName === "matrix" || varName === "rows") {
1416
+ if (propIndex.length === 1) {
1417
+ return "row" + propIndex[0];
1418
+ } else {
1419
+ // if propIndex has additional entries, ignore them
1420
+ return `matrixEntry${propIndex[0]}_${propIndex[1]}`;
1421
+ }
1422
+ }
1423
+ if (varName === "columns") {
1424
+ if (propIndex.length === 1) {
1425
+ return "column" + propIndex[0];
1426
+ } else {
1427
+ // if propIndex has additional entries, ignore them
1428
+ return `matrixEntry${propIndex[1]}_${propIndex[0]}`;
1429
+ }
1430
+ }
1431
+ if (varName.slice(0, 3) === "row") {
1432
+ let rowNum = Number(varName.slice(3));
1433
+ if (Number.isInteger(rowNum) && rowNum > 0) {
1434
+ // if propIndex has additional entries, ignore them
1435
+ return `matrixEntry${rowNum}_${propIndex[0]}`;
1436
+ }
1437
+ }
1438
+ if (varName.slice(0, 6) === "column") {
1439
+ let colNum = Number(varName.slice(6));
1440
+ if (Number.isInteger(colNum) && colNum > 0) {
1441
+ // if propIndex has additional entries, ignore them
1442
+ return `matrixEntry${propIndex[0]}_${colNum}`;
1443
+ }
1444
+ }
1445
+ return null;
1446
+ },
1447
+ returnArraySizeDependencies: () => ({
1448
+ matrixSize: {
1449
+ dependencyType: "stateVariable",
1450
+ variableName: "matrixSize",
1451
+ },
1452
+ }),
1453
+ returnArraySize({ dependencyValues }) {
1454
+ return dependencyValues.matrixSize;
1455
+ },
1456
+ returnArrayDependenciesByKey() {
1457
+ let globalDependencies = {
1458
+ value: {
1459
+ dependencyType: "stateVariable",
1460
+ variableName: "value",
1461
+ },
1462
+ };
1463
+ return { globalDependencies };
1464
+ },
1465
+ arrayDefinitionByKey({ globalDependencyValues, arraySize }) {
1466
+ let tree = globalDependencyValues.value.tree;
1467
+
1468
+ let createdMatrix = false;
1469
+
1470
+ let matrix = {};
1471
+ if (Array.isArray(tree)) {
1472
+ if (vectorAndListOperators.includes(tree[0])) {
1473
+ for (let ind = 0; ind < arraySize[0]; ind++) {
1474
+ matrix[ind + ",0"] = me.fromAst(tree[ind + 1]);
1475
+ }
1476
+ createdMatrix = true;
1477
+ } else if (tree[0] === "matrix") {
1478
+ let matVals = tree[2];
1479
+ for (let i = 0; i < arraySize[0]; i++) {
1480
+ for (let j = 0; j < arraySize[1]; j++) {
1481
+ matrix[`${i},${j}`] = me.fromAst(matVals[i + 1][j + 1]);
1482
+ }
1483
+ }
1484
+ createdMatrix = true;
1485
+ } else if (
1486
+ vectorOperators.includes(tree[1][0]) &&
1487
+ ((tree[0] === "^" && tree[2] === "T") || tree[0] === "prime")
1488
+ ) {
1489
+ for (let ind = 0; ind < arraySize[1]; ind++) {
1490
+ matrix["0," + ind] = me.fromAst(tree[1][ind + 1]);
1491
+ }
1492
+ createdMatrix = true;
1493
+ }
1494
+ }
1495
+ if (!createdMatrix) {
1496
+ matrix["0,0"] = globalDependencyValues.value;
1497
+ }
1498
+
1499
+ return { setValue: { matrix } };
1500
+ },
1501
+ async inverseArrayDefinitionByKey({
1502
+ desiredStateVariableValues,
1503
+ globalDependencyValues,
1504
+ stateValues,
1505
+ workspace,
1506
+ arraySize,
1507
+ }) {
1508
+ // in case just one ind specified, merge with previous values
1509
+ if (!workspace.desiredMatrix) {
1510
+ workspace.desiredMatrix = [];
1511
+ }
1512
+ for (let i = 0; i < arraySize[0]; i++) {
1513
+ for (let j = 0; j < arraySize[1]; j++) {
1514
+ let arrayKey = i + "," + j;
1515
+ if (desiredStateVariableValues.matrix[arrayKey] !== undefined) {
1516
+ workspace.desiredMatrix[arrayKey] = convertValueToMathExpression(
1517
+ desiredStateVariableValues.matrix[arrayKey],
1518
+ );
1519
+ } else if (workspace.desiredMatrix[arrayKey] === undefined) {
1520
+ workspace.desiredMatrix[arrayKey] = (await stateValues.matrix)[i][
1521
+ j
1522
+ ];
1523
+ }
1524
+ }
1525
+ }
1526
+
1527
+ let desiredValue;
1528
+ let tree = globalDependencyValues.value.tree;
1529
+ if (Array.isArray(tree)) {
1530
+ if (vectorAndListOperators.includes(tree[0])) {
1531
+ desiredValue = [tree[0]];
1532
+ for (let ind = 0; ind < arraySize[0]; ind++) {
1533
+ desiredValue.push(workspace.desiredMatrix[ind + ",0"].tree);
1534
+ }
1535
+ } else if (tree[0] === "matrix") {
1536
+ let desiredMatrixVals = ["tuple"];
1537
+
1538
+ for (let i = 0; i < arraySize[0]; i++) {
1539
+ let row = ["tuple"];
1540
+ for (let j = 0; j < arraySize[1]; j++) {
1541
+ row.push(workspace.desiredMatrix[`${i},${j}`].tree);
1542
+ }
1543
+ desiredMatrixVals.push(row);
1544
+ }
1545
+ desiredValue = me.fromAst(["matrix", tree[1], desiredMatrixVals]);
1546
+ } else if (
1547
+ vectorOperators.includes(tree[1][0]) &&
1548
+ ((tree[0] === "^" && tree[2] === "T") || tree[0] === "prime")
1549
+ ) {
1550
+ desiredValue = [tree[0]];
1551
+ let desiredVector = [tree[1][0]];
1552
+ for (let ind = 0; ind < arraySize[1]; ind++) {
1553
+ desiredVector.push(workspace.desiredMatrix["0," + ind].tree);
1554
+ }
1555
+ desiredValue = [tree[0], desiredVector];
1556
+ if (tree[2]) {
1557
+ desiredValue.push(tree[2]);
1558
+ }
1559
+ desiredValue = me.fromAst(desiredValue);
1560
+ }
1561
+ }
1562
+
1563
+ if (!desiredValue) {
1564
+ desiredValue = workspace.desiredMatrix[0];
1565
+ }
1566
+
1567
+ let instructions = [
1568
+ {
1569
+ setDependency: "value",
1570
+ desiredValue,
1571
+ },
1572
+ ];
1573
+
1574
+ return {
1575
+ success: true,
1576
+ instructions,
1577
+ };
1578
+ },
1579
+ };
1580
+
1581
+ return stateVariableDefinitions;
1582
+ }
1583
+
1584
+ static adapters = [
1585
+ {
1586
+ stateVariable: "number",
1587
+ stateVariablesToShadow: Object.keys(
1588
+ returnRoundingStateVariableDefinitions(),
1589
+ ),
1590
+ },
1591
+ "text",
1592
+ { componentType: "point", stateVariable: "value" },
1593
+ { componentType: "vector", stateVariable: "value" },
1594
+ {
1595
+ componentType: "subsetOfReals",
1596
+ stateVariable: "value",
1597
+ substituteForPrimaryStateVariable: "subsetValue",
1598
+ },
1599
+ ];
1600
+
1601
+ async moveMath({
1602
+ x,
1603
+ y,
1604
+ z,
1605
+ transient,
1606
+ actionId,
1607
+ sourceInformation = {},
1608
+ skipRendererUpdate = false,
1609
+ }) {
1610
+ return await moveGraphicalObjectWithAnchorAction({
1611
+ x,
1612
+ y,
1613
+ z,
1614
+ transient,
1615
+ actionId,
1616
+ sourceInformation,
1617
+ skipRendererUpdate,
1618
+ componentName: this.componentName,
1619
+ componentType: this.componentType,
1620
+ coreFunctions: this.coreFunctions,
1621
+ });
1622
+ }
1623
+
1624
+ async mathClicked({
1625
+ actionId,
1626
+ name,
1627
+ sourceInformation = {},
1628
+ skipRendererUpdate = false,
1629
+ }) {
1630
+ if (!(await this.stateValues.fixed)) {
1631
+ await this.coreFunctions.triggerChainedActions({
1632
+ triggeringAction: "click",
1633
+ componentName: name, // use name rather than this.componentName to get original name if adapted
1634
+ actionId,
1635
+ sourceInformation,
1636
+ skipRendererUpdate,
1637
+ });
1638
+ }
1639
+
1640
+ this.coreFunctions.resolveAction({ actionId });
1641
+ }
1642
+
1643
+ async mathFocused({
1644
+ actionId,
1645
+ name,
1646
+ sourceInformation = {},
1647
+ skipRendererUpdate = false,
1648
+ }) {
1649
+ if (!(await this.stateValues.fixed)) {
1650
+ await this.coreFunctions.triggerChainedActions({
1651
+ triggeringAction: "focus",
1652
+ componentName: name, // use name rather than this.componentName to get original name if adapted
1653
+ actionId,
1654
+ sourceInformation,
1655
+ skipRendererUpdate,
1656
+ });
1657
+ }
1658
+
1659
+ this.coreFunctions.resolveAction({ actionId });
1660
+ }
1661
+ }
1662
+
1663
+ function calculateExpressionWithCodes({ dependencyValues, changes }) {
1664
+ if (
1665
+ !(
1666
+ ("stringMathChildren" in changes &&
1667
+ changes.stringMathChildren.componentIdentitiesChanged) ||
1668
+ "displayedMathChildren" in changes ||
1669
+ "format" in changes ||
1670
+ "splitSymbols" in changes ||
1671
+ "parseScientificNotation" in changes ||
1672
+ "functionSymbols" in changes ||
1673
+ "mathChildrenFunctionSymbols" in changes
1674
+ )
1675
+ ) {
1676
+ // if component identities of stringMathChildren didn't change
1677
+ // and format didn't change
1678
+ // then expressionWithCodes remains unchanged.
1679
+ // (We assume that the value of string children cannot change on their own.)
1680
+ return { useEssentialOrDefaultValue: { expressionWithCodes: true } };
1681
+ // return { noChanges: ["expressionWithCodes"] };
1682
+ }
1683
+
1684
+ if (dependencyValues.stringMathChildren.length === 0) {
1685
+ if (dependencyValues.displayedMathChildren.length > 0) {
1686
+ let expr;
1687
+ try {
1688
+ expr = me.fromLatex(
1689
+ dependencyValues.displayedMathChildren[0].stateValues.latex,
1690
+ );
1691
+ } catch (e) {
1692
+ expr = me.fromAst("\uff3f");
1693
+ }
1694
+ return {
1695
+ setValue: { expressionWithCodes: expr },
1696
+ setEssentialValue: { expressionWithCodes: expr },
1697
+ };
1698
+ } else {
1699
+ // if don't have any string or math children,
1700
+ // set expressionWithCodes to be null,
1701
+ // which will indicate that value should use valueShadow
1702
+ return {
1703
+ setValue: { expressionWithCodes: null },
1704
+ setEssentialValue: { expressionWithCodes: null },
1705
+ };
1706
+ }
1707
+ }
1708
+
1709
+ let inputString = "";
1710
+ let mathInd = 0;
1711
+ let compositeGroupString = "";
1712
+
1713
+ let compositeReplacementRange =
1714
+ dependencyValues.stringMathChildren.compositeReplacementRange;
1715
+ let currentCompositeInd = undefined;
1716
+ let currentCompositeLastChildInd = undefined;
1717
+ let nextCompositeInd = undefined;
1718
+ let nextCompositeChildInd = undefined;
1719
+ if (
1720
+ dependencyValues.groupCompositeReplacements &&
1721
+ compositeReplacementRange.length > 0
1722
+ ) {
1723
+ nextCompositeInd = 0;
1724
+ nextCompositeChildInd =
1725
+ compositeReplacementRange[nextCompositeInd].firstInd;
1726
+ }
1727
+
1728
+ for (let [childInd, child] of dependencyValues.stringMathChildren.entries()) {
1729
+ if (
1730
+ currentCompositeInd === undefined &&
1731
+ childInd === nextCompositeChildInd
1732
+ ) {
1733
+ // we are grouping composite replacements
1734
+ // and we found the beginning of children that are composite replacements
1735
+
1736
+ currentCompositeInd = nextCompositeInd;
1737
+ currentCompositeLastChildInd =
1738
+ compositeReplacementRange[nextCompositeInd].lastInd;
1739
+ compositeGroupString = "";
1740
+
1741
+ // if composite has only one replacement or has a string replacement,
1742
+ // then we don't group
1743
+
1744
+ let dontGroup = currentCompositeLastChildInd === childInd;
1745
+ if (!dontGroup) {
1746
+ for (let ind = childInd; ind <= currentCompositeLastChildInd; ind++) {
1747
+ if (typeof dependencyValues.stringMathChildren[ind] === "string") {
1748
+ dontGroup = true;
1749
+ break;
1750
+ }
1751
+ }
1752
+ }
1753
+
1754
+ if (dontGroup) {
1755
+ if (compositeReplacementRange.length > currentCompositeInd + 1) {
1756
+ nextCompositeInd = currentCompositeInd + 1;
1757
+ nextCompositeChildInd =
1758
+ compositeReplacementRange[nextCompositeInd].firstInd;
1759
+ } else {
1760
+ nextCompositeInd = undefined;
1761
+ nextCompositeChildInd = undefined;
1762
+ }
1763
+ currentCompositeInd = undefined;
1764
+ currentCompositeLastChildInd = undefined;
1765
+ }
1766
+ }
1767
+
1768
+ if (typeof child === "string") {
1769
+ inputString += " " + child + " ";
1770
+ } else {
1771
+ // a math
1772
+ let code = dependencyValues.codePre + mathInd;
1773
+ mathInd++;
1774
+
1775
+ let nextString;
1776
+ if (dependencyValues.format === "latex") {
1777
+ // for latex, must explicitly denote that code
1778
+ // is a multicharacter variable
1779
+ nextString = "\\operatorname{" + code + "}";
1780
+ } else {
1781
+ // for text, just make sure code is surrounded by spaces
1782
+ // (the presence of numbers inside code will ensure that
1783
+ // it is parsed as a multicharcter variable)
1784
+ nextString = " " + code + " ";
1785
+ }
1786
+
1787
+ if (currentCompositeInd !== undefined) {
1788
+ if (compositeGroupString) {
1789
+ // continuing a composite group
1790
+ compositeGroupString += ",";
1791
+ }
1792
+ compositeGroupString += nextString;
1793
+ } else {
1794
+ inputString += nextString;
1795
+ }
1796
+ }
1797
+
1798
+ if (childInd === currentCompositeLastChildInd) {
1799
+ // compositeGroupString contains components separated by commas
1800
+ // will wrap in parenthesis unless already contains
1801
+ // delimeters before and after
1802
+ // TODO: \rangle and \langle?
1803
+ let iString = inputString.trimEnd();
1804
+ let wrap = false;
1805
+ if (iString.length === 0) {
1806
+ wrap = true;
1807
+ } else {
1808
+ let lastChar = iString[iString.length - 1];
1809
+ if (!["{", "[", "(", "|", ","].includes(lastChar)) {
1810
+ wrap = true;
1811
+ } else {
1812
+ let nextChild = dependencyValues.stringMathChildren[childInd + 1];
1813
+ if (typeof nextChild !== "string") {
1814
+ wrap = true;
1815
+ } else {
1816
+ let nextString = nextChild.trimStart();
1817
+ if (nextString.length === 0) {
1818
+ wrap = true;
1819
+ } else {
1820
+ let nextChar = nextString[0];
1821
+ if (
1822
+ dependencyValues.format === "latex" &&
1823
+ nextChar === "\\" &&
1824
+ nextString.length > 1
1825
+ ) {
1826
+ nextChar = nextString[1];
1827
+ }
1828
+ if (!["}", "]", ")", "|", ","].includes(nextChar)) {
1829
+ wrap = true;
1830
+ }
1831
+ }
1832
+ }
1833
+ }
1834
+ }
1835
+
1836
+ if (wrap) {
1837
+ compositeGroupString = "(" + compositeGroupString + ")";
1838
+ }
1839
+
1840
+ inputString += compositeGroupString;
1841
+ compositeGroupString = "";
1842
+
1843
+ if (compositeReplacementRange.length > currentCompositeInd + 1) {
1844
+ nextCompositeInd = currentCompositeInd + 1;
1845
+ nextCompositeChildInd =
1846
+ compositeReplacementRange[nextCompositeInd].firstInd;
1847
+ } else {
1848
+ nextCompositeInd = undefined;
1849
+ nextCompositeChildInd = undefined;
1850
+ }
1851
+ currentCompositeInd = undefined;
1852
+ currentCompositeLastChildInd = undefined;
1853
+ }
1854
+ }
1855
+
1856
+ let expressionWithCodes = null;
1857
+
1858
+ let functionSymbols = [...dependencyValues.functionSymbols];
1859
+ functionSymbols.push(
1860
+ ...dependencyValues.mathChildrenFunctionSymbols.map(
1861
+ (x) => dependencyValues.codePre + x,
1862
+ ),
1863
+ );
1864
+
1865
+ if (inputString === "") {
1866
+ expressionWithCodes = me.fromAst("\uFF3F"); // long underscore
1867
+ } else {
1868
+ if (dependencyValues.format === "text") {
1869
+ let fromText = getFromText({
1870
+ functionSymbols,
1871
+ splitSymbols: dependencyValues.splitSymbols,
1872
+ parseScientificNotation: dependencyValues.parseScientificNotation,
1873
+ });
1874
+ try {
1875
+ expressionWithCodes = fromText(inputString);
1876
+ } catch (e) {
1877
+ expressionWithCodes = me.fromAst("\uFF3F"); // long underscore
1878
+ console.log("Invalid value for a math of text format: " + inputString);
1879
+ }
1880
+ } else if (dependencyValues.format === "latex") {
1881
+ let fromLatex = getFromLatex({
1882
+ functionSymbols,
1883
+ splitSymbols: dependencyValues.splitSymbols,
1884
+ parseScientificNotation: dependencyValues.parseScientificNotation,
1885
+ });
1886
+ try {
1887
+ expressionWithCodes = fromLatex(inputString);
1888
+ } catch (e) {
1889
+ expressionWithCodes = me.fromAst("\uFF3F"); // long underscore
1890
+ console.log("Invalid value for a math of latex format: " + inputString);
1891
+ }
1892
+ }
1893
+ }
1894
+
1895
+ return {
1896
+ setValue: { expressionWithCodes },
1897
+ setEssentialValue: { expressionWithCodes },
1898
+ };
1899
+ }
1900
+
1901
+ function calculateMathValue({ dependencyValues } = {}) {
1902
+ // if expressionWithCodes is null, there were no string or math children
1903
+ if (dependencyValues.expressionWithCodes === null) {
1904
+ return {
1905
+ setValue: { unnormalizedValue: dependencyValues.valueShadow },
1906
+ };
1907
+ }
1908
+
1909
+ let subsMapping = {};
1910
+ for (let [ind, child] of dependencyValues.mathChildren.entries()) {
1911
+ subsMapping[dependencyValues.codePre + ind] = child.stateValues.value;
1912
+ }
1913
+
1914
+ let value = dependencyValues.expressionWithCodes;
1915
+ if (dependencyValues.mathChildren.length > 0) {
1916
+ value = value.substitute(subsMapping);
1917
+ }
1918
+
1919
+ value = me.fromAst(mergeListsWithOtherContainers(value.tree));
1920
+
1921
+ return {
1922
+ setValue: { unnormalizedValue: value },
1923
+ };
1924
+ }
1925
+
1926
+ function calculateCodesAdjacentToStrings({ dependencyValues }) {
1927
+ // create codesAdjacentToStrings object that gives substitution codes
1928
+ // that are just before and after each string child
1929
+ let codesAdjacentToStrings = [];
1930
+ let mathInd;
1931
+ for (let [ind, child] of dependencyValues.stringMathChildren.entries()) {
1932
+ if (typeof child === "string") {
1933
+ let nextChild = dependencyValues.stringMathChildren[ind + 1];
1934
+ if (nextChild !== undefined && typeof nextChild === "string") {
1935
+ // if following child is also a string, we'll skip the first string
1936
+ // which means, when inverting, the first string will just be set to blank
1937
+ continue;
1938
+ }
1939
+
1940
+ let subCodes = {};
1941
+ if (mathInd !== undefined) {
1942
+ if (dependencyValues.format === "latex") {
1943
+ subCodes.prevCode =
1944
+ "\\operatorname{" + dependencyValues.codePre + mathInd + "}";
1945
+ } else {
1946
+ subCodes.prevCode = dependencyValues.codePre + mathInd;
1947
+ }
1948
+ }
1949
+
1950
+ if (nextChild !== undefined) {
1951
+ // next child is a math
1952
+ let nextInd = 0;
1953
+ if (mathInd !== undefined) {
1954
+ nextInd = mathInd + 1;
1955
+ }
1956
+
1957
+ if (dependencyValues.format === "latex") {
1958
+ subCodes.nextCode =
1959
+ "\\operatorname{" + dependencyValues.codePre + nextInd + "}";
1960
+ } else {
1961
+ subCodes.nextCode = dependencyValues.codePre + nextInd;
1962
+ }
1963
+ }
1964
+
1965
+ codesAdjacentToStrings.push(subCodes);
1966
+ } else {
1967
+ // have a mathChild, so increment mathInd
1968
+ if (mathInd === undefined) {
1969
+ mathInd = 0;
1970
+ } else {
1971
+ mathInd++;
1972
+ }
1973
+ }
1974
+ }
1975
+
1976
+ return { setValue: { codesAdjacentToStrings } };
1977
+ }
1978
+
1979
+ function determineCanBeModified({ dependencyValues }) {
1980
+ if (!dependencyValues.modifyIndirectly || dependencyValues.fixed) {
1981
+ return {
1982
+ setValue: {
1983
+ canBeModified: false,
1984
+ constantChildIndices: null,
1985
+ codeForExpression: null,
1986
+ inverseMaps: null,
1987
+ template: null,
1988
+ mathChildrenMapped: null,
1989
+ },
1990
+ };
1991
+ }
1992
+
1993
+ if (dependencyValues.mathChildrenModifiable.length === 0) {
1994
+ if (dependencyValues.displayedMathChildren.length > 0) {
1995
+ // don't invert displayed math children
1996
+ return {
1997
+ setValue: {
1998
+ canBeModified: false,
1999
+ constantChildIndices: null,
2000
+ codeForExpression: null,
2001
+ inverseMaps: null,
2002
+ template: null,
2003
+ mathChildrenMapped: null,
2004
+ },
2005
+ };
2006
+ } else {
2007
+ // if have no math children, then can directly set value
2008
+ // to any specified expression
2009
+ return {
2010
+ setValue: {
2011
+ canBeModified: true,
2012
+ constantChildIndices: null,
2013
+ codeForExpression: null,
2014
+ inverseMaps: null,
2015
+ template: null,
2016
+ mathChildrenMapped: null,
2017
+ },
2018
+ };
2019
+ }
2020
+ }
2021
+
2022
+ // determine if can calculate value of activeChildren from
2023
+ // any specified value of expression
2024
+
2025
+ // categorize all math activeChildren as variables or constants
2026
+ let variableInds = [];
2027
+ let variables = [];
2028
+ // let constantInds = [];
2029
+ let constants = [];
2030
+
2031
+ let constantChildIndices = {};
2032
+
2033
+ for (let [
2034
+ ind,
2035
+ childModifiable,
2036
+ ] of dependencyValues.mathChildrenModifiable.entries()) {
2037
+ let substitutionCode = dependencyValues.codePre + ind;
2038
+
2039
+ if (childModifiable.stateValues.canBeModified === true) {
2040
+ variableInds.push(ind);
2041
+ variables.push(substitutionCode);
2042
+ } else {
2043
+ // constantInds.push(ind);
2044
+ constants.push(substitutionCode);
2045
+ constantChildIndices[substitutionCode] = ind;
2046
+ }
2047
+ }
2048
+
2049
+ // include codePre in code for whole expression, as we know codePre is not in math expression
2050
+ let codeForExpression = dependencyValues.codePre + "expr";
2051
+ let tree = me.utils.unflattenLeft(dependencyValues.expressionWithCodes.tree);
2052
+
2053
+ let result = checkForLinearExpression(
2054
+ tree,
2055
+ variables,
2056
+ codeForExpression,
2057
+ constants,
2058
+ );
2059
+
2060
+ if (result.foundLinear) {
2061
+ let inverseMaps = {};
2062
+ let template = result.template;
2063
+ let mathChildrenMapped = new Set();
2064
+
2065
+ for (let key in result.mappings) {
2066
+ inverseMaps[key] = result.mappings[key];
2067
+
2068
+ // if component was due to a math child, add Ind of the math child
2069
+ let mathChildSub = inverseMaps[key].mathChildSub;
2070
+ if (mathChildSub) {
2071
+ let mathChildInd = variableInds[variables.indexOf(mathChildSub)];
2072
+ inverseMaps[key].mathChildInd = mathChildInd;
2073
+ mathChildrenMapped.add(Number(mathChildInd));
2074
+ }
2075
+ }
2076
+
2077
+ mathChildrenMapped.has = mathChildrenMapped.has.bind(mathChildrenMapped);
2078
+
2079
+ // found an inverse
2080
+ return {
2081
+ setValue: {
2082
+ canBeModified: true,
2083
+ constantChildIndices,
2084
+ codeForExpression,
2085
+ inverseMaps,
2086
+ template,
2087
+ mathChildrenMapped,
2088
+ },
2089
+ };
2090
+ }
2091
+
2092
+ // if not linear, can't find an inverse
2093
+ return {
2094
+ setValue: {
2095
+ canBeModified: false,
2096
+ constantChildIndices: null,
2097
+ codeForExpression: null,
2098
+ inverseMaps: null,
2099
+ template: null,
2100
+ mathChildrenMapped: null,
2101
+ },
2102
+ };
2103
+ }
2104
+
2105
+ function checkForLinearExpression(
2106
+ tree,
2107
+ variables,
2108
+ inverseTree,
2109
+ constants = [],
2110
+ components = [],
2111
+ ) {
2112
+ // Check if tree is a linear expression in variables.
2113
+ // Each component of container must be a linear expression in just one variable.
2114
+ // Haven't implemented inversion of a multivariable linear map
2115
+
2116
+ let tree_variables = me.variables(tree);
2117
+ if (tree_variables.every((v) => !variables.includes(v))) {
2118
+ if (tree_variables.every((v) => !constants.includes(v))) {
2119
+ // if there are no variable or constant math activeChildren, then consider it linear
2120
+ let mappings = {};
2121
+ let key = "x" + components.join("_");
2122
+ mappings[key] = {
2123
+ result: me.fromAst(inverseTree).expand().simplify(),
2124
+ components: components,
2125
+ };
2126
+ //let modifiableStrings = {[key]: components};
2127
+ return { foundLinear: true, mappings: mappings, template: key };
2128
+ //modifiableStrings: modifiableStrings };
2129
+ }
2130
+ }
2131
+
2132
+ // if not an array, check if is a variable
2133
+ if (!Array.isArray(tree)) {
2134
+ return checkForScalarLinearExpression(
2135
+ tree,
2136
+ variables,
2137
+ inverseTree,
2138
+ components,
2139
+ );
2140
+ }
2141
+
2142
+ let operator = tree[0];
2143
+ let operands = tree.slice(1);
2144
+
2145
+ // for container, check if at least one component is a linear expression
2146
+ if (vectorAndListOperators.includes(operator)) {
2147
+ let result = { mappings: {}, template: [operator] }; //, modifiableStrings: {}};
2148
+ let numLinear = 0;
2149
+ for (let ind = 0; ind < operands.length; ind++) {
2150
+ let new_components = [...components, ind];
2151
+ let res = checkForLinearExpression(
2152
+ operands[ind],
2153
+ variables,
2154
+ inverseTree,
2155
+ constants,
2156
+ new_components,
2157
+ );
2158
+ if (res.foundLinear) {
2159
+ numLinear++;
2160
+
2161
+ // append mappings found for the component
2162
+ result.mappings = Object.assign(result.mappings, res.mappings);
2163
+
2164
+ // // append modifiableStrings found for the component
2165
+ // result.modifiableStrings = Object.assign(result.modifiableStrings, res.modifiableStrings);
2166
+
2167
+ // append template
2168
+ result.template.push(res.template);
2169
+ } else {
2170
+ result.template.push("x" + new_components.join("_"));
2171
+ }
2172
+ }
2173
+
2174
+ // if no components are linear, view whole container as nonlinear
2175
+ if (numLinear === 0) {
2176
+ return { foundLinear: false };
2177
+ }
2178
+
2179
+ // if at least one componen is a linear functions, view as linear
2180
+ result.foundLinear = true;
2181
+ return result;
2182
+ } else {
2183
+ // if not a container, check if is a scalar linear function
2184
+ return checkForScalarLinearExpression(
2185
+ tree,
2186
+ variables,
2187
+ inverseTree,
2188
+ components,
2189
+ );
2190
+ }
2191
+ }
2192
+
2193
+ // check if tree is a scalar linear function in one of the variables
2194
+ function checkForScalarLinearExpression(
2195
+ tree,
2196
+ variables,
2197
+ inverseTree,
2198
+ components = [],
2199
+ ) {
2200
+ if (typeof tree === "string" && variables.includes(tree)) {
2201
+ let mappings = {};
2202
+ let template = "x" + components.join("_");
2203
+ mappings[template] = {
2204
+ result: me.fromAst(inverseTree).expand().simplify(),
2205
+ components: components,
2206
+ mathChildSub: tree,
2207
+ };
2208
+ return { foundLinear: true, mappings: mappings, template: template };
2209
+ }
2210
+
2211
+ if (!Array.isArray(tree)) {
2212
+ return { foundLinear: false };
2213
+ }
2214
+
2215
+ let operator = tree[0];
2216
+ let operands = tree.slice(1);
2217
+
2218
+ if (operator === "-") {
2219
+ inverseTree = ["-", inverseTree];
2220
+ return checkForScalarLinearExpression(
2221
+ operands[0],
2222
+ variables,
2223
+ inverseTree,
2224
+ components,
2225
+ );
2226
+ }
2227
+ if (operator === "+") {
2228
+ if (me.variables(operands[0]).every((v) => !variables.includes(v))) {
2229
+ // if none of the variables appear in the first operand, subtract off operand from inverseTree
2230
+ inverseTree = ["+", inverseTree, ["-", operands[0]]];
2231
+ return checkForScalarLinearExpression(
2232
+ operands[1],
2233
+ variables,
2234
+ inverseTree,
2235
+ components,
2236
+ );
2237
+ } else if (me.variables(operands[1]).every((v) => !variables.includes(v))) {
2238
+ // if none of the variables appear in the second operand, subtract off operand from inverseTree
2239
+ inverseTree = ["+", inverseTree, ["-", operands[1]]];
2240
+ return checkForScalarLinearExpression(
2241
+ operands[0],
2242
+ variables,
2243
+ inverseTree,
2244
+ components,
2245
+ );
2246
+ } else {
2247
+ // neither operand was a constant
2248
+ return { foundLinear: false };
2249
+ }
2250
+ }
2251
+ if (operator === "*") {
2252
+ if (
2253
+ me.variables(operands[0]).every((v) => !variables.includes(v)) &&
2254
+ !exprContainsVector(operands[0])
2255
+ ) {
2256
+ // if none of the variables appear in the first operand and it doesn't contain a vector,
2257
+ // divide inverseTree by operand
2258
+ inverseTree = ["/", inverseTree, operands[0]];
2259
+ return checkForScalarLinearExpression(
2260
+ operands[1],
2261
+ variables,
2262
+ inverseTree,
2263
+ components,
2264
+ );
2265
+ } else if (
2266
+ me.variables(operands[1]).every((v) => !variables.includes(v)) &&
2267
+ !exprContainsVector(operands[1])
2268
+ ) {
2269
+ // if none of the variables appear in the second operand and it doesn't contain a vector,
2270
+ // divide inverseTree by operand
2271
+ inverseTree = ["/", inverseTree, operands[1]];
2272
+ return checkForScalarLinearExpression(
2273
+ operands[0],
2274
+ variables,
2275
+ inverseTree,
2276
+ components,
2277
+ );
2278
+ } else {
2279
+ // neither operand was a constant
2280
+ return { foundLinear: false };
2281
+ }
2282
+ }
2283
+ if (operator === "/") {
2284
+ if (me.variables(operands[1]).every((v) => !variables.includes(v))) {
2285
+ // if none of the variables appear in the second operand, multiply inverseTree by operand
2286
+ inverseTree = ["*", inverseTree, operands[1]];
2287
+ return checkForScalarLinearExpression(
2288
+ operands[0],
2289
+ variables,
2290
+ inverseTree,
2291
+ components,
2292
+ );
2293
+ } else {
2294
+ // second operand was not a constant
2295
+ return { foundLinear: false };
2296
+ }
2297
+ }
2298
+
2299
+ // any other operator means not linear
2300
+ return { foundLinear: false };
2301
+ }
2302
+
2303
+ async function invertMath({
2304
+ desiredStateVariableValues,
2305
+ dependencyValues,
2306
+ stateValues,
2307
+ workspace,
2308
+ overrideFixed,
2309
+ }) {
2310
+ if (!(await stateValues.canBeModified) && !overrideFixed) {
2311
+ return { success: false };
2312
+ }
2313
+
2314
+ let mathChildren = dependencyValues.mathChildren;
2315
+ let nStringChildren = dependencyValues.stringChildren.length;
2316
+
2317
+ if (mathChildren.length === 1 && nStringChildren === 0) {
2318
+ // if only child is a math, just send instructions to change it to desired value
2319
+ return {
2320
+ success: true,
2321
+ instructions: [
2322
+ {
2323
+ setDependency: "mathChildren",
2324
+ desiredValue: desiredStateVariableValues.unnormalizedValue,
2325
+ childIndex: 0,
2326
+ variableIndex: 0,
2327
+ },
2328
+ ],
2329
+ };
2330
+ }
2331
+
2332
+ let desiredExpression = convertValueToMathExpression(
2333
+ desiredStateVariableValues.unnormalizedValue,
2334
+ );
2335
+
2336
+ let result = await preprocessMathInverseDefinition({
2337
+ desiredValue: desiredExpression,
2338
+ stateValues,
2339
+ variableName: "value",
2340
+ workspace,
2341
+ });
2342
+
2343
+ let vectorComponentsNotAffected = result.vectorComponentsNotAffected;
2344
+ desiredExpression = result.desiredValue;
2345
+
2346
+ if (mathChildren.length === 0) {
2347
+ let instructions = [];
2348
+
2349
+ if (nStringChildren > 0) {
2350
+ instructions.push({
2351
+ setDependency: "expressionWithCodes",
2352
+ desiredValue: desiredExpression,
2353
+ });
2354
+ } else {
2355
+ instructions.push({
2356
+ setDependency: "valueShadow",
2357
+ desiredValue: desiredExpression,
2358
+ });
2359
+ }
2360
+
2361
+ return {
2362
+ success: true,
2363
+ instructions,
2364
+ };
2365
+ }
2366
+
2367
+ // first calculate expression pieces to make sure really can update
2368
+ let expressionPieces = await getExpressionPieces({
2369
+ expression: desiredExpression,
2370
+ stateValues,
2371
+ });
2372
+ if (!expressionPieces) {
2373
+ return { success: false };
2374
+ }
2375
+
2376
+ let instructions = [];
2377
+
2378
+ let childrenToSkip = [];
2379
+ if (
2380
+ vectorComponentsNotAffected &&
2381
+ (await stateValues.mathChildrenByVectorComponent)
2382
+ ) {
2383
+ let mathChildrenByVectorComponent =
2384
+ await stateValues.mathChildrenByVectorComponent;
2385
+ for (let ind of vectorComponentsNotAffected) {
2386
+ if (mathChildrenByVectorComponent[ind]) {
2387
+ childrenToSkip.push(...mathChildrenByVectorComponent[ind]);
2388
+ }
2389
+ }
2390
+ }
2391
+
2392
+ // update math children where have inversemap and canBeModified is true
2393
+ let mathChildrenWithCanBeModified =
2394
+ await stateValues.mathChildrenWithCanBeModified;
2395
+ for (let [childInd, mathChild] of mathChildren.entries()) {
2396
+ if (
2397
+ stateValues.mathChildrenMapped.has(childInd) &&
2398
+ mathChildrenWithCanBeModified[childInd].stateValues.canBeModified
2399
+ ) {
2400
+ if (!childrenToSkip.includes(childInd)) {
2401
+ let childValue = expressionPieces[childInd];
2402
+ let subsMap = {};
2403
+ let foundConst = false;
2404
+ let constantChildIndices = await stateValues.constantChildIndices;
2405
+ for (let code in constantChildIndices) {
2406
+ let constInd = constantChildIndices[code];
2407
+ subsMap[code] = mathChildren[constInd].stateValues.value;
2408
+ foundConst = true;
2409
+ }
2410
+ if (foundConst) {
2411
+ // substitute values of any math children that are constant
2412
+ // (i.e., that are marked as not modifiable from above)
2413
+ childValue = childValue.substitute(subsMap);
2414
+ }
2415
+
2416
+ childValue = childValue.expand().simplify();
2417
+
2418
+ instructions.push({
2419
+ setDependency: "mathChildren",
2420
+ desiredValue: childValue,
2421
+ childIndex: childInd,
2422
+ variableIndex: 0,
2423
+ });
2424
+ }
2425
+
2426
+ delete expressionPieces[childInd];
2427
+ }
2428
+ }
2429
+
2430
+ // if there are any string children,
2431
+ // need to update expressionWithCodes with new values
2432
+
2433
+ if (nStringChildren > 0) {
2434
+ let newExpressionWithCodes = dependencyValues.expressionWithCodes;
2435
+ let codePre = dependencyValues.codePre;
2436
+ let nCP = codePre.length;
2437
+
2438
+ // Given that we have both string and math children,
2439
+ // the only way that expressionWithCodes could change
2440
+ // is if expression is a vector
2441
+ // and there is a vector component that came entirely from a string child,
2442
+ // i.e., that that vector component in expressionWithCodes
2443
+ // does not have any Codes in it.
2444
+
2445
+ let mathComponentIsCode = (tree) =>
2446
+ typeof tree === "string" && tree.substring(0, nCP) === codePre;
2447
+
2448
+ let mathComponentContainsCode = (tree) => {
2449
+ if (Array.isArray(tree)) {
2450
+ return flattenDeep(tree.slice(1)).some(mathComponentIsCode);
2451
+ } else {
2452
+ return mathComponentIsCode(tree);
2453
+ }
2454
+ };
2455
+
2456
+ if (
2457
+ vectorAndListOperators.includes(newExpressionWithCodes.tree[0]) &&
2458
+ !newExpressionWithCodes.tree.slice(1).every(mathComponentContainsCode)
2459
+ ) {
2460
+ let inverseMaps = await stateValues.inverseMaps;
2461
+ for (let piece in expressionPieces) {
2462
+ let inverseMap = inverseMaps[piece];
2463
+ // skip math children
2464
+ if (inverseMap.mathChildInd !== undefined) {
2465
+ continue;
2466
+ }
2467
+ let components = inverseMap.components;
2468
+ newExpressionWithCodes = newExpressionWithCodes.substitute_component(
2469
+ components,
2470
+ expressionPieces[piece],
2471
+ );
2472
+ }
2473
+
2474
+ instructions.push({
2475
+ setDependency: "expressionWithCodes",
2476
+ desiredValue: newExpressionWithCodes,
2477
+ });
2478
+ }
2479
+ }
2480
+
2481
+ return {
2482
+ success: true,
2483
+ instructions,
2484
+ };
2485
+ }
2486
+
2487
+ async function getExpressionPieces({ expression, stateValues }) {
2488
+ let template = await stateValues.template;
2489
+
2490
+ let matching = me.utils.match(expression.tree, template);
2491
+
2492
+ // if doesn't match, trying matching, by converting vectors, intervals, or both
2493
+ if (!matching) {
2494
+ matching = me.utils.match(
2495
+ expression.tuples_to_vectors().tree,
2496
+ me.fromAst(template).tuples_to_vectors().tree,
2497
+ );
2498
+ if (!matching) {
2499
+ matching = me.utils.match(
2500
+ expression.to_intervals().tree,
2501
+ me.fromAst(template).to_intervals().tree,
2502
+ );
2503
+ if (!matching) {
2504
+ matching = me.utils.match(
2505
+ expression.tuples_to_vectors().to_intervals().tree,
2506
+ me.fromAst(template).tuples_to_vectors().to_intervals().tree,
2507
+ );
2508
+ if (!matching) {
2509
+ return false;
2510
+ }
2511
+ }
2512
+ }
2513
+ }
2514
+
2515
+ let pieces = {};
2516
+ for (let x in matching) {
2517
+ let subMap = {};
2518
+ subMap[await stateValues.codeForExpression] = matching[x];
2519
+ let inverseMap = (await stateValues.inverseMaps)[x];
2520
+ if (inverseMap !== undefined) {
2521
+ let id = x;
2522
+ if (inverseMap.mathChildInd !== undefined) {
2523
+ id = inverseMap.mathChildInd;
2524
+ }
2525
+ pieces[id] = inverseMap.result.substitute(subMap);
2526
+
2527
+ pieces[id] = normalizeMathExpression({
2528
+ value: pieces[id],
2529
+ simplify: await stateValues.simplify,
2530
+ expand: await stateValues.expand,
2531
+ createVectors: await stateValues.createVectors,
2532
+ createIntervals: await stateValues.createIntervals,
2533
+ });
2534
+ }
2535
+ }
2536
+ return pieces;
2537
+ }
2538
+
2539
+ function exprContainsVector(tree) {
2540
+ if (!Array.isArray(tree)) {
2541
+ return false;
2542
+ }
2543
+
2544
+ let operator = tree[0];
2545
+ let operands = tree.slice(1);
2546
+
2547
+ if (vectorOperators.includes(operator)) {
2548
+ return true;
2549
+ }
2550
+
2551
+ return operands.some(exprContainsVector);
2552
+ }