@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,2118 @@
1
+ import { returnRoundingAttributeComponentShadowing } from "../utils/rounding";
2
+ import Polygon from "./Polygon";
3
+ import me from "math-expressions";
4
+
5
+ export default class RegularPolygon extends Polygon {
6
+ static componentType = "regularPolygon";
7
+ static rendererType = "polygon";
8
+
9
+ static createAttributesObject() {
10
+ let attributes = super.createAttributesObject();
11
+
12
+ attributes.numVertices = {
13
+ createComponentOfType: "integer",
14
+ };
15
+
16
+ attributes.numSides = {
17
+ createComponentOfType: "integer",
18
+ };
19
+
20
+ // Note: vertices is already an attribute from polygon
21
+
22
+ attributes.center = {
23
+ createComponentOfType: "point",
24
+ };
25
+
26
+ // if center and vertex or two vertices are specified
27
+ // then the following size attributes are ignored
28
+
29
+ // circumradius and radrius are the same thing and either attribute can be used
30
+ // If both specified, circumradius is used
31
+ attributes.circumradius = {
32
+ createComponentOfType: "number",
33
+ };
34
+ attributes.radius = {
35
+ createComponentOfType: "number",
36
+ };
37
+
38
+ // inradius and apothem are the same thing and either attribute can be used
39
+ // If both specified, inradius is used.
40
+ // If circumradius is specified, inradius is ignored
41
+ attributes.inradius = {
42
+ createComponentOfType: "number",
43
+ };
44
+ attributes.apothem = {
45
+ createComponentOfType: "number",
46
+ };
47
+
48
+ // if circumradius or inradius is specified, sideLength is ignored
49
+ attributes.sideLength = {
50
+ createComponentOfType: "number",
51
+ };
52
+
53
+ // if circumradius, inradius, or sideLength is specified, perimeter is ignored
54
+ attributes.perimeter = {
55
+ createComponentOfType: "number",
56
+ };
57
+
58
+ // if circumradius, inradius, sideLength, or perimeter is specified, area is ignored
59
+ attributes.area = {
60
+ createComponentOfType: "number",
61
+ };
62
+
63
+ return attributes;
64
+ }
65
+
66
+ static returnStateVariableDefinitions() {
67
+ let stateVariableDefinitions = super.returnStateVariableDefinitions();
68
+
69
+ let styleDescriptionWithNounDeps =
70
+ stateVariableDefinitions.styleDescriptionWithNoun.returnDependencies();
71
+ styleDescriptionWithNounDeps.numSides = {
72
+ dependencyType: "stateVariable",
73
+ variableName: "numSides",
74
+ };
75
+
76
+ stateVariableDefinitions.styleDescriptionWithNoun.returnDependencies = () =>
77
+ styleDescriptionWithNounDeps;
78
+
79
+ let styleDescriptionWithNounDef =
80
+ stateVariableDefinitions.styleDescriptionWithNoun.definition;
81
+
82
+ stateVariableDefinitions.styleDescriptionWithNoun.definition = function ({
83
+ dependencyValues,
84
+ }) {
85
+ let styleDescriptionWithNoun = styleDescriptionWithNounDef({
86
+ dependencyValues,
87
+ }).setValue.styleDescriptionWithNoun;
88
+
89
+ styleDescriptionWithNoun = styleDescriptionWithNoun.replaceAll(
90
+ "polygon",
91
+ `${dependencyValues.numSides}-sided regular polygon`,
92
+ );
93
+
94
+ return { setValue: { styleDescriptionWithNoun } };
95
+ };
96
+
97
+ stateVariableDefinitions.numVertices = {
98
+ isLocation: true,
99
+ hasEssential: true,
100
+ defaultValue: 3,
101
+ public: true,
102
+ forRenderer: true,
103
+ shadowingInstructions: {
104
+ createComponentOfType: "integer",
105
+ },
106
+ returnDependencies: () => ({
107
+ numVerticesAttr: {
108
+ dependencyType: "attributeComponent",
109
+ attributeName: "numVertices",
110
+ variableNames: ["value"],
111
+ },
112
+ numSidesAttr: {
113
+ dependencyType: "attributeComponent",
114
+ attributeName: "numSides",
115
+ variableNames: ["value"],
116
+ },
117
+ }),
118
+ definition({ dependencyValues }) {
119
+ if (dependencyValues.numVerticesAttr) {
120
+ return {
121
+ setValue: {
122
+ numVertices: dependencyValues.numVerticesAttr.stateValues.value,
123
+ },
124
+ };
125
+ } else if (dependencyValues.numSidesAttr) {
126
+ return {
127
+ setValue: {
128
+ numVertices: dependencyValues.numSidesAttr.stateValues.value,
129
+ },
130
+ };
131
+ } else {
132
+ return {
133
+ useEssentialOrDefaultValue: { numVertices: true },
134
+ };
135
+ }
136
+ },
137
+ inverseDefinition({ desiredStateVariableValues, dependencyValues }) {
138
+ if (dependencyValues.numVerticesAttr) {
139
+ return {
140
+ success: true,
141
+ instructions: [
142
+ {
143
+ setDependency: "numVerticesAttr",
144
+ desiredValue: desiredStateVariableValues.numVertices,
145
+ variableIndex: 0,
146
+ },
147
+ ],
148
+ };
149
+ } else if (dependencyValues.numSidesAttr) {
150
+ return {
151
+ success: true,
152
+ instructions: [
153
+ {
154
+ setDependency: "numSidesAttr",
155
+ desiredValue: desiredStateVariableValues.numVertices,
156
+ variableIndex: 0,
157
+ },
158
+ ],
159
+ };
160
+ } else {
161
+ return {
162
+ success: true,
163
+ instructions: [
164
+ {
165
+ setEssentialValue: "numVertices",
166
+ value: desiredStateVariableValues.numVertices,
167
+ },
168
+ ],
169
+ };
170
+ }
171
+ },
172
+ };
173
+
174
+ stateVariableDefinitions.numSides = {
175
+ isAlias: true,
176
+ targetVariableName: "numVertices",
177
+ };
178
+
179
+ stateVariableDefinitions.numVerticesSpecified = {
180
+ returnDependencies: () => ({
181
+ verticesAttr: {
182
+ dependencyType: "attributeComponent",
183
+ attributeName: "vertices",
184
+ variableNames: ["numPoints"],
185
+ },
186
+ }),
187
+ definition: function ({ dependencyValues }) {
188
+ if (dependencyValues.verticesAttr !== null) {
189
+ return {
190
+ setValue: {
191
+ numVerticesSpecified:
192
+ dependencyValues.verticesAttr.stateValues.numPoints,
193
+ },
194
+ };
195
+ } else {
196
+ return { setValue: { numVerticesSpecified: 0 } };
197
+ }
198
+ },
199
+ };
200
+
201
+ stateVariableDefinitions.essentialDirection = {
202
+ isArray: true,
203
+ isLocation: true,
204
+ entryPrefixes: ["essentialVertexX"],
205
+ defaultValueByArrayKey: () => 0,
206
+ hasEssential: true,
207
+ returnArraySizeDependencies: () => ({
208
+ numVerticesSpecified: {
209
+ dependencyType: "stateVariable",
210
+ variableName: "numVerticesSpecified",
211
+ },
212
+ haveSpecifiedCenter: {
213
+ dependencyType: "stateVariable",
214
+ variableName: "haveSpecifiedCenter",
215
+ },
216
+ }),
217
+ returnArraySize({ dependencyValues }) {
218
+ let needDir =
219
+ (dependencyValues.haveSpecifiedCenter ? 1 : 0) +
220
+ dependencyValues.numVerticesSpecified <=
221
+ 1;
222
+ return [needDir ? 2 : 0];
223
+ },
224
+
225
+ returnArrayDependenciesByKey() {
226
+ return {};
227
+ },
228
+
229
+ arrayDefinitionByKey: function ({ arrayKeys }) {
230
+ let essentialDirection = {};
231
+
232
+ for (let arrayKey of arrayKeys) {
233
+ if (arrayKey === "0") {
234
+ essentialDirection[arrayKey] = { defaultValue: 1 };
235
+ } else {
236
+ // uses defaultValueByArrayKey
237
+ essentialDirection[arrayKey] = true;
238
+ }
239
+ }
240
+ return { useEssentialOrDefaultValue: { essentialDirection } };
241
+ },
242
+
243
+ inverseArrayDefinitionByKey({ desiredStateVariableValues }) {
244
+ let instructions = [];
245
+
246
+ for (let arrayKey in desiredStateVariableValues.essentialDirection) {
247
+ instructions.push({
248
+ setEssentialValue: "essentialDirection",
249
+ value: {
250
+ [arrayKey]:
251
+ desiredStateVariableValues.essentialDirection[arrayKey],
252
+ },
253
+ });
254
+ }
255
+
256
+ return {
257
+ success: true,
258
+ instructions,
259
+ };
260
+ },
261
+ };
262
+
263
+ stateVariableDefinitions.haveSpecifiedCenter = {
264
+ returnDependencies: () => ({
265
+ centerAttr: {
266
+ dependencyType: "attributeComponent",
267
+ attributeName: "center",
268
+ },
269
+ }),
270
+ definition: ({ dependencyValues }) => ({
271
+ setValue: {
272
+ haveSpecifiedCenter: dependencyValues.centerAttr !== null,
273
+ },
274
+ }),
275
+ };
276
+
277
+ stateVariableDefinitions.specifiedCenter = {
278
+ isArray: true,
279
+ isLocation: true,
280
+ entryPrefixes: ["specifiedCenterX"],
281
+ returnArraySizeDependencies: () => ({
282
+ haveSpecifiedCenter: {
283
+ dependencyType: "stateVariable",
284
+ variableName: "haveSpecifiedCenter",
285
+ },
286
+ }),
287
+ returnArraySize({ dependencyValues }) {
288
+ return [dependencyValues.haveSpecifiedCenter ? 2 : 0];
289
+ },
290
+
291
+ returnArrayDependenciesByKey({ arrayKeys }) {
292
+ let dependenciesByKey = {};
293
+
294
+ for (let arrayKey of arrayKeys) {
295
+ let varEnding = Number(arrayKey) + 1;
296
+ dependenciesByKey[arrayKey] = {
297
+ centerAttr: {
298
+ dependencyType: "attributeComponent",
299
+ attributeName: "center",
300
+ variableNames: ["x" + varEnding],
301
+ },
302
+ };
303
+ }
304
+
305
+ return { dependenciesByKey };
306
+ },
307
+
308
+ arrayDefinitionByKey: function ({ dependencyValuesByKey, arrayKeys }) {
309
+ let specifiedCenter = {};
310
+
311
+ for (let arrayKey of arrayKeys) {
312
+ let varEnding = Number(arrayKey) + 1;
313
+
314
+ if (dependencyValuesByKey[arrayKey].centerAttr !== null) {
315
+ specifiedCenter[arrayKey] =
316
+ dependencyValuesByKey[arrayKey].centerAttr.stateValues[
317
+ "x" + varEnding
318
+ ].evaluate_to_constant();
319
+ }
320
+ }
321
+
322
+ return { setValue: { specifiedCenter } };
323
+ },
324
+
325
+ inverseArrayDefinitionByKey({
326
+ desiredStateVariableValues,
327
+ dependencyValuesByKey,
328
+ dependencyNamesByKey,
329
+ }) {
330
+ let instructions = [];
331
+
332
+ for (let arrayKey in desiredStateVariableValues.specifiedCenter) {
333
+ if (
334
+ dependencyValuesByKey[arrayKey].centerAttr &&
335
+ dependencyValuesByKey[arrayKey].centerAttr !== null
336
+ ) {
337
+ instructions.push({
338
+ setDependency: dependencyNamesByKey[arrayKey].centerAttr,
339
+ desiredValue: me.fromAst(
340
+ desiredStateVariableValues.specifiedCenter[arrayKey],
341
+ ),
342
+ variableIndex: 0,
343
+ });
344
+ }
345
+ }
346
+
347
+ return {
348
+ success: true,
349
+ instructions,
350
+ };
351
+ },
352
+ };
353
+
354
+ stateVariableDefinitions.essentialCenter = {
355
+ isArray: true,
356
+ isLocation: true,
357
+ entryPrefixes: ["essentialCenterX"],
358
+ defaultValueByArrayKey: () => 0,
359
+ hasEssential: true,
360
+ returnArraySizeDependencies: () => ({
361
+ haveSpecifiedCenter: {
362
+ dependencyType: "stateVariable",
363
+ variableName: "haveSpecifiedCenter",
364
+ },
365
+ }),
366
+ returnArraySize({ dependencyValues }) {
367
+ return [dependencyValues.haveSpecifiedCenter ? 0 : 2];
368
+ },
369
+
370
+ returnArrayDependenciesByKey() {
371
+ return {};
372
+ },
373
+
374
+ arrayDefinitionByKey: function ({ arrayKeys }) {
375
+ let essentialCenter = {};
376
+
377
+ for (let arrayKey of arrayKeys) {
378
+ essentialCenter[arrayKey] = true;
379
+ }
380
+ return { useEssentialOrDefaultValue: { essentialCenter } };
381
+ },
382
+
383
+ inverseArrayDefinitionByKey({ desiredStateVariableValues }) {
384
+ let instructions = [];
385
+
386
+ for (let arrayKey in desiredStateVariableValues.essentialCenter) {
387
+ instructions.push({
388
+ setEssentialValue: "essentialCenter",
389
+ value: {
390
+ [arrayKey]: desiredStateVariableValues.essentialCenter[arrayKey],
391
+ },
392
+ });
393
+ }
394
+
395
+ return {
396
+ success: true,
397
+ instructions,
398
+ };
399
+ },
400
+ };
401
+
402
+ stateVariableDefinitions.specifiedCircumradius = {
403
+ isLocation: true,
404
+ returnDependencies() {
405
+ return {
406
+ circumradiusAttr: {
407
+ dependencyType: "attributeComponent",
408
+ attributeName: "circumradius",
409
+ variableNames: ["value"],
410
+ },
411
+ radiusAttr: {
412
+ dependencyType: "attributeComponent",
413
+ attributeName: "radius",
414
+ variableNames: ["value"],
415
+ },
416
+ numVerticesSpecified: {
417
+ dependencyType: "stateVariable",
418
+ variableName: "numVerticesSpecified",
419
+ },
420
+ haveSpecifiedCenter: {
421
+ dependencyType: "stateVariable",
422
+ variableName: "haveSpecifiedCenter",
423
+ },
424
+ };
425
+ },
426
+
427
+ definition({ dependencyValues }) {
428
+ if (dependencyValues.circumradiusAttr !== null) {
429
+ return {
430
+ setValue: {
431
+ specifiedCircumradius:
432
+ dependencyValues.circumradiusAttr.stateValues.value,
433
+ },
434
+ };
435
+ } else if (dependencyValues.radiusAttr !== null) {
436
+ return {
437
+ setValue: {
438
+ specifiedCircumradius:
439
+ dependencyValues.radiusAttr.stateValues.value,
440
+ },
441
+ };
442
+ } else {
443
+ return { setValue: { specifiedCircumradius: null } };
444
+ }
445
+ },
446
+
447
+ inverseDefinition({ desiredStateVariableValues, dependencyValues }) {
448
+ if (dependencyValues.circumradiusAttr !== null) {
449
+ return {
450
+ success: true,
451
+ instructions: [
452
+ {
453
+ setDependency: "circumradiusAttr",
454
+ desiredValue: desiredStateVariableValues.specifiedCircumradius,
455
+ childIndex: 0,
456
+ variableIndex: 0,
457
+ },
458
+ ],
459
+ };
460
+ } else if (dependencyValues.radiusAttr !== null) {
461
+ return {
462
+ success: true,
463
+ instructions: [
464
+ {
465
+ setDependency: "radiusAttr",
466
+ desiredValue: desiredStateVariableValues.specifiedCircumradius,
467
+ childIndex: 0,
468
+ variableIndex: 0,
469
+ },
470
+ ],
471
+ };
472
+ } else {
473
+ return { success: false };
474
+ }
475
+ },
476
+ };
477
+
478
+ stateVariableDefinitions.specifiedInradius = {
479
+ isLocation: true,
480
+ returnDependencies() {
481
+ return {
482
+ inradiusAttr: {
483
+ dependencyType: "attributeComponent",
484
+ attributeName: "inradius",
485
+ variableNames: ["value"],
486
+ },
487
+ apothemAttr: {
488
+ dependencyType: "attributeComponent",
489
+ attributeName: "apothem",
490
+ variableNames: ["value"],
491
+ },
492
+ };
493
+ },
494
+
495
+ definition({ dependencyValues }) {
496
+ if (dependencyValues.inradiusAttr !== null) {
497
+ return {
498
+ setValue: {
499
+ specifiedInradius:
500
+ dependencyValues.inradiusAttr.stateValues.value,
501
+ },
502
+ };
503
+ } else if (dependencyValues.apothemAttr !== null) {
504
+ return {
505
+ setValue: {
506
+ specifiedInradius: dependencyValues.apothemAttr.stateValues.value,
507
+ },
508
+ };
509
+ } else {
510
+ return { setValue: { specifiedInradius: null } };
511
+ }
512
+ },
513
+
514
+ inverseDefinition({ desiredStateVariableValues, dependencyValues }) {
515
+ if (dependencyValues.inradiusAttr !== null) {
516
+ return {
517
+ success: true,
518
+ instructions: [
519
+ {
520
+ setDependency: "inradiusAttr",
521
+ desiredValue: desiredStateVariableValues.specifiedInradius,
522
+ childIndex: 0,
523
+ variableIndex: 0,
524
+ },
525
+ ],
526
+ };
527
+ } else if (dependencyValues.apothemAttr !== null) {
528
+ return {
529
+ success: true,
530
+ instructions: [
531
+ {
532
+ setDependency: "apothemAttr",
533
+ desiredValue: desiredStateVariableValues.specifiedInradius,
534
+ childIndex: 0,
535
+ variableIndex: 0,
536
+ },
537
+ ],
538
+ };
539
+ } else {
540
+ return { sucess: false };
541
+ }
542
+ },
543
+ };
544
+
545
+ stateVariableDefinitions.specifiedSideLength = {
546
+ isLocation: true,
547
+ returnDependencies() {
548
+ return {
549
+ sideLengthAttr: {
550
+ dependencyType: "attributeComponent",
551
+ attributeName: "sideLength",
552
+ variableNames: ["value"],
553
+ },
554
+ };
555
+ },
556
+
557
+ definition({ dependencyValues }) {
558
+ if (dependencyValues.sideLengthAttr !== null) {
559
+ return {
560
+ setValue: {
561
+ specifiedSideLength:
562
+ dependencyValues.sideLengthAttr.stateValues.value,
563
+ },
564
+ };
565
+ } else {
566
+ return { setValue: { specifiedSideLength: null } };
567
+ }
568
+ },
569
+
570
+ inverseDefinition({ desiredStateVariableValues, dependencyValues }) {
571
+ if (dependencyValues.sideLengthAttr !== null) {
572
+ return {
573
+ success: true,
574
+ instructions: [
575
+ {
576
+ setDependency: "sideLengthAttr",
577
+ desiredValue: desiredStateVariableValues.specifiedSideLength,
578
+ childIndex: 0,
579
+ variableIndex: 0,
580
+ },
581
+ ],
582
+ };
583
+ } else {
584
+ return { sucess: false };
585
+ }
586
+ },
587
+ };
588
+
589
+ stateVariableDefinitions.specifiedPerimeter = {
590
+ isLocation: true,
591
+ returnDependencies() {
592
+ return {
593
+ perimeterAttr: {
594
+ dependencyType: "attributeComponent",
595
+ attributeName: "perimeter",
596
+ variableNames: ["value"],
597
+ },
598
+ };
599
+ },
600
+
601
+ definition({ dependencyValues }) {
602
+ if (dependencyValues.perimeterAttr !== null) {
603
+ return {
604
+ setValue: {
605
+ specifiedPerimeter:
606
+ dependencyValues.perimeterAttr.stateValues.value,
607
+ },
608
+ };
609
+ } else {
610
+ return { setValue: { specifiedPerimeter: null } };
611
+ }
612
+ },
613
+
614
+ inverseDefinition({ desiredStateVariableValues, dependencyValues }) {
615
+ if (dependencyValues.perimeterAttr !== null) {
616
+ return {
617
+ success: true,
618
+ instructions: [
619
+ {
620
+ setDependency: "perimeterAttr",
621
+ desiredValue: desiredStateVariableValues.specifiedPerimeter,
622
+ childIndex: 0,
623
+ variableIndex: 0,
624
+ },
625
+ ],
626
+ };
627
+ } else {
628
+ return { sucess: false };
629
+ }
630
+ },
631
+ };
632
+
633
+ stateVariableDefinitions.specifiedArea = {
634
+ isLocation: true,
635
+ returnDependencies() {
636
+ return {
637
+ areaAttr: {
638
+ dependencyType: "attributeComponent",
639
+ attributeName: "area",
640
+ variableNames: ["value"],
641
+ },
642
+ };
643
+ },
644
+
645
+ definition({ dependencyValues }) {
646
+ if (dependencyValues.areaAttr !== null) {
647
+ return {
648
+ setValue: {
649
+ specifiedArea: dependencyValues.areaAttr.stateValues.value,
650
+ },
651
+ };
652
+ } else {
653
+ return { setValue: { specifiedArea: null } };
654
+ }
655
+ },
656
+
657
+ inverseDefinition({ desiredStateVariableValues, dependencyValues }) {
658
+ if (dependencyValues.areaAttr !== null) {
659
+ return {
660
+ success: true,
661
+ instructions: [
662
+ {
663
+ setDependency: "areaAttr",
664
+ desiredValue: desiredStateVariableValues.specifiedArea,
665
+ childIndex: 0,
666
+ variableIndex: 0,
667
+ },
668
+ ],
669
+ };
670
+ } else {
671
+ return { sucess: false };
672
+ }
673
+ },
674
+ };
675
+
676
+ stateVariableDefinitions.essentialCircumradius = {
677
+ isLocation: true,
678
+ hasEssential: true,
679
+ defaultValue: 1,
680
+ returnDependencies: () => ({}),
681
+ definition: () => ({
682
+ useEssentialOrDefaultValue: { essentialCircumradius: true },
683
+ }),
684
+ inverseDefinition({ desiredStateVariableValues }) {
685
+ return {
686
+ success: true,
687
+ instructions: [
688
+ {
689
+ setEssentialValue: "essentialCircumradius",
690
+ value: desiredStateVariableValues.essentialCircumradius,
691
+ },
692
+ ],
693
+ };
694
+ },
695
+ };
696
+
697
+ // Note: we create the non-array centerComponents
698
+ // because we currently can't use additionalStateVariablesDefined with arrays
699
+ // unless all state variables are arrays of the same size
700
+ stateVariableDefinitions.centerComponents = {
701
+ isLocation: true,
702
+ additionalStateVariablesDefined: ["directionWithRadius"],
703
+ returnDependencies: () => ({
704
+ numVertices: {
705
+ dependencyType: "stateVariable",
706
+ variableName: "numVertices",
707
+ },
708
+ numVerticesSpecified: {
709
+ dependencyType: "stateVariable",
710
+ variableName: "numVerticesSpecified",
711
+ },
712
+ haveSpecifiedCenter: {
713
+ dependencyType: "stateVariable",
714
+ variableName: "haveSpecifiedCenter",
715
+ },
716
+
717
+ specifiedCircumradius: {
718
+ dependencyType: "stateVariable",
719
+ variableName: "specifiedCircumradius",
720
+ },
721
+ specifiedInradius: {
722
+ dependencyType: "stateVariable",
723
+ variableName: "specifiedInradius",
724
+ },
725
+ specifiedSideLength: {
726
+ dependencyType: "stateVariable",
727
+ variableName: "specifiedSideLength",
728
+ },
729
+ specifiedPerimeter: {
730
+ dependencyType: "stateVariable",
731
+ variableName: "specifiedPerimeter",
732
+ },
733
+ specifiedArea: {
734
+ dependencyType: "stateVariable",
735
+ variableName: "specifiedArea",
736
+ },
737
+
738
+ essentialCircumradius: {
739
+ dependencyType: "stateVariable",
740
+ variableName: "essentialCircumradius",
741
+ },
742
+ essentialDirection: {
743
+ dependencyType: "stateVariable",
744
+ variableName: "essentialDirection",
745
+ },
746
+
747
+ verticesAttr: {
748
+ dependencyType: "attributeComponent",
749
+ attributeName: "vertices",
750
+ variableNames: ["points"],
751
+ },
752
+
753
+ specifiedCenter: {
754
+ dependencyType: "stateVariable",
755
+ variableName: "specifiedCenter",
756
+ },
757
+
758
+ essentialCenter: {
759
+ dependencyType: "stateVariable",
760
+ variableName: "essentialCenter",
761
+ },
762
+ }),
763
+ definition({ dependencyValues }) {
764
+ let numVertices = dependencyValues.numVertices;
765
+
766
+ let center;
767
+ let directionWithRadius;
768
+
769
+ if (dependencyValues.numVerticesSpecified === 0) {
770
+ // with no vertices, use center (specified or essential), direction, and a measure of size
771
+
772
+ if (dependencyValues.haveSpecifiedCenter) {
773
+ center = dependencyValues.specifiedCenter;
774
+ } else {
775
+ center = dependencyValues.essentialCenter;
776
+ }
777
+
778
+ let circumradius;
779
+
780
+ if (dependencyValues.specifiedCircumradius !== null) {
781
+ circumradius = dependencyValues.specifiedCircumradius;
782
+ } else if (dependencyValues.specifiedInradius !== null) {
783
+ circumradius =
784
+ dependencyValues.specifiedInradius /
785
+ Math.cos(Math.PI / numVertices);
786
+ } else if (dependencyValues.specifiedSideLength !== null) {
787
+ circumradius =
788
+ dependencyValues.specifiedSideLength /
789
+ (2 * Math.sin(Math.PI / numVertices));
790
+ } else if (dependencyValues.specifiedPerimeter !== null) {
791
+ circumradius =
792
+ dependencyValues.specifiedPerimeter /
793
+ (2 * numVertices * Math.sin(Math.PI / numVertices));
794
+ } else if (dependencyValues.specifiedArea !== null) {
795
+ circumradius = Math.sqrt(
796
+ dependencyValues.specifiedArea /
797
+ ((numVertices / 2) * Math.sin((2 * Math.PI) / numVertices)),
798
+ );
799
+ } else {
800
+ circumradius = dependencyValues.essentialCircumradius;
801
+ }
802
+
803
+ directionWithRadius = dependencyValues.essentialDirection.map(
804
+ (x) => x * circumradius,
805
+ );
806
+ } else if (dependencyValues.haveSpecifiedCenter) {
807
+ // base polygon on center and first vertex
808
+
809
+ center = dependencyValues.specifiedCenter;
810
+
811
+ let vertex = dependencyValues.verticesAttr.stateValues.points[0].map(
812
+ (x) => x.evaluate_to_constant(),
813
+ );
814
+
815
+ directionWithRadius = [vertex[0] - center[0], vertex[1] - center[1]];
816
+ } else if (dependencyValues.numVerticesSpecified === 1) {
817
+ // one vertex, no center
818
+ // use vertex, direction, and a measure of size
819
+
820
+ let circumradius;
821
+
822
+ if (dependencyValues.specifiedCircumradius !== null) {
823
+ circumradius = dependencyValues.specifiedCircumradius;
824
+ } else if (dependencyValues.specifiedInradius !== null) {
825
+ circumradius =
826
+ dependencyValues.specifiedInradius /
827
+ Math.cos(Math.PI / numVertices);
828
+ } else if (dependencyValues.specifiedSideLength !== null) {
829
+ circumradius =
830
+ dependencyValues.specifiedSideLength /
831
+ (2 * Math.sin(Math.PI / numVertices));
832
+ } else if (dependencyValues.specifiedPerimeter !== null) {
833
+ circumradius =
834
+ dependencyValues.specifiedPerimeter /
835
+ (2 * numVertices * Math.sin(Math.PI / numVertices));
836
+ } else if (dependencyValues.specifiedArea !== null) {
837
+ circumradius = Math.sqrt(
838
+ dependencyValues.specifiedArea /
839
+ ((numVertices / 2) * Math.sin((2 * Math.PI) / numVertices)),
840
+ );
841
+ } else {
842
+ circumradius = dependencyValues.essentialCircumradius;
843
+ }
844
+
845
+ directionWithRadius = dependencyValues.essentialDirection.map(
846
+ (x) => x * circumradius,
847
+ );
848
+
849
+ let vertex = dependencyValues.verticesAttr.stateValues.points[0].map(
850
+ (x) => x.evaluate_to_constant(),
851
+ );
852
+
853
+ center = [
854
+ vertex[0] - directionWithRadius[0],
855
+ vertex[1] - directionWithRadius[1],
856
+ ];
857
+ } else {
858
+ // have at least two vertices specified, use the first 2
859
+ // these vertices are adjacent vertices of the polygon, in counterclockwise order
860
+
861
+ let vertex1 = dependencyValues.verticesAttr.stateValues.points[0].map(
862
+ (x) => x.evaluate_to_constant(),
863
+ );
864
+ let vertex2 = dependencyValues.verticesAttr.stateValues.points[1].map(
865
+ (x) => x.evaluate_to_constant(),
866
+ );
867
+
868
+ let sideVector = [vertex2[0] - vertex1[0], vertex2[1] - vertex1[1]];
869
+ let midpoint = [
870
+ (vertex1[0] + vertex2[0]) / 2,
871
+ (vertex1[1] + vertex2[1]) / 2,
872
+ ];
873
+ let sideLength = Math.sqrt(sideVector[0] ** 2 + sideVector[1] ** 2);
874
+ let inradius = sideLength / (2 * Math.tan(Math.PI / numVertices));
875
+
876
+ let inradiusDirection = [
877
+ -sideVector[1] / sideLength,
878
+ sideVector[0] / sideLength,
879
+ ];
880
+
881
+ center = [
882
+ midpoint[0] + inradiusDirection[0] * inradius,
883
+ midpoint[1] + inradiusDirection[1] * inradius,
884
+ ];
885
+
886
+ directionWithRadius = [
887
+ vertex1[0] - center[0],
888
+ vertex1[1] - center[1],
889
+ ];
890
+ }
891
+
892
+ return { setValue: { centerComponents: center, directionWithRadius } };
893
+ },
894
+ async inverseDefinition({
895
+ desiredStateVariableValues,
896
+ dependencyValues,
897
+ workspace,
898
+ stateValues,
899
+ }) {
900
+ let numVertices = dependencyValues.numVertices;
901
+
902
+ let instructions = [];
903
+
904
+ let desiredCenter = desiredStateVariableValues.centerComponents;
905
+ if (!desiredCenter) {
906
+ desiredCenter = workspace.desiredCenter;
907
+ }
908
+ if (!desiredCenter) {
909
+ desiredCenter = (await stateValues.center).map((x) =>
910
+ x.evaluate_to_constant(),
911
+ );
912
+ }
913
+
914
+ let desiredDirectionWithRadius =
915
+ desiredStateVariableValues.directionWithRadius;
916
+ if (!desiredDirectionWithRadius) {
917
+ desiredDirectionWithRadius = workspace.desiredDirectionWithRadius;
918
+ }
919
+ if (!desiredDirectionWithRadius) {
920
+ let center = (await stateValues.center).map((x) =>
921
+ x.evaluate_to_constant(),
922
+ );
923
+ let vertex1 = (await stateValues.vertices)[0].map((x) =>
924
+ x.evaluate_to_constant(),
925
+ );
926
+ desiredDirectionWithRadius = [
927
+ vertex1[0] - center[0],
928
+ vertex1[1] - center[1],
929
+ ];
930
+ }
931
+
932
+ workspace.desiredCenter = desiredCenter;
933
+ workspace.desiredDirectionWithRadius = desiredDirectionWithRadius;
934
+
935
+ if (dependencyValues.numVerticesSpecified === 0) {
936
+ // with no vertices, use center (specified or essential), direction, and a measure of size
937
+
938
+ if (dependencyValues.haveSpecifiedCenter) {
939
+ instructions.push({
940
+ setDependency: "specifiedCenter",
941
+ desiredValue: desiredCenter,
942
+ });
943
+ } else {
944
+ instructions.push({
945
+ setDependency: "essentialCenter",
946
+ desiredValue: desiredCenter,
947
+ });
948
+ }
949
+
950
+ let desiredCircumradius = Math.sqrt(
951
+ desiredDirectionWithRadius[0] ** 2 +
952
+ desiredDirectionWithRadius[1] ** 2,
953
+ );
954
+ let desiredDirection = desiredDirectionWithRadius.map(
955
+ (x) => x / desiredCircumradius,
956
+ );
957
+
958
+ if (dependencyValues.specifiedCircumradius !== null) {
959
+ instructions.push({
960
+ setDependency: "specifiedCircumradius",
961
+ desiredValue: desiredCircumradius,
962
+ });
963
+ } else if (dependencyValues.specifiedInradius !== null) {
964
+ instructions.push({
965
+ setDependency: "specifiedInradius",
966
+ desiredValue:
967
+ desiredCircumradius * Math.cos(Math.PI / numVertices),
968
+ });
969
+ } else if (dependencyValues.specifiedSideLength !== null) {
970
+ instructions.push({
971
+ setDependency: "specifiedSideLength",
972
+ desiredValue:
973
+ desiredCircumradius * (2 * Math.sin(Math.PI / numVertices)),
974
+ });
975
+ } else if (dependencyValues.specifiedPerimeter !== null) {
976
+ instructions.push({
977
+ setDependency: "specifiedPerimeter",
978
+ desiredValue:
979
+ desiredCircumradius *
980
+ (2 * numVertices * Math.sin(Math.PI / numVertices)),
981
+ });
982
+ } else if (dependencyValues.specifiedArea !== null) {
983
+ instructions.push({
984
+ setDependency: "specifiedArea",
985
+ desiredValue:
986
+ desiredCircumradius ** 2 *
987
+ ((numVertices / 2) * Math.sin((2 * Math.PI) / numVertices)),
988
+ });
989
+ } else {
990
+ instructions.push({
991
+ setDependency: "essentialCircumradius",
992
+ desiredValue: desiredCircumradius,
993
+ });
994
+ }
995
+
996
+ instructions.push({
997
+ setDependency: "essentialDirection",
998
+ desiredValue: desiredDirection,
999
+ });
1000
+ } else if (dependencyValues.haveSpecifiedCenter) {
1001
+ // base polygon on center and first vertex
1002
+
1003
+ instructions.push({
1004
+ setDependency: "specifiedCenter",
1005
+ desiredValue: desiredCenter,
1006
+ });
1007
+
1008
+ let desiredVertices = {
1009
+ "0,0": me.fromAst(desiredDirectionWithRadius[0] + desiredCenter[0]),
1010
+ "0,1": me.fromAst(desiredDirectionWithRadius[1] + desiredCenter[1]),
1011
+ };
1012
+
1013
+ instructions.push({
1014
+ setDependency: "verticesAttr",
1015
+ desiredValue: desiredVertices,
1016
+ variableIndex: 0,
1017
+ });
1018
+ } else if (dependencyValues.numVerticesSpecified === 1) {
1019
+ // one vertex, no center
1020
+ // use vertex, direction, and a measure of size
1021
+
1022
+ let desiredCircumradius = Math.sqrt(
1023
+ desiredDirectionWithRadius[0] ** 2 +
1024
+ desiredDirectionWithRadius[1] ** 2,
1025
+ );
1026
+ let desiredDirection = desiredDirectionWithRadius.map(
1027
+ (x) => x / desiredCircumradius,
1028
+ );
1029
+
1030
+ if (dependencyValues.specifiedCircumradius !== null) {
1031
+ instructions.push({
1032
+ setDependency: "specifiedCircumradius",
1033
+ desiredValue: desiredCircumradius,
1034
+ });
1035
+ } else if (dependencyValues.specifiedInradius !== null) {
1036
+ instructions.push({
1037
+ setDependency: "specifiedInradius",
1038
+ desiredValue:
1039
+ desiredCircumradius * Math.cos(Math.PI / numVertices),
1040
+ });
1041
+ } else if (dependencyValues.specifiedSideLength !== null) {
1042
+ instructions.push({
1043
+ setDependency: "specifiedSideLength",
1044
+ desiredValue:
1045
+ desiredCircumradius * (2 * Math.sin(Math.PI / numVertices)),
1046
+ });
1047
+ } else if (dependencyValues.specifiedPerimeter !== null) {
1048
+ instructions.push({
1049
+ setDependency: "specifiedPerimeter",
1050
+ desiredValue:
1051
+ desiredCircumradius *
1052
+ (2 * numVertices * Math.sin(Math.PI / numVertices)),
1053
+ });
1054
+ } else if (dependencyValues.specifiedArea !== null) {
1055
+ instructions.push({
1056
+ setDependency: "specifiedArea",
1057
+ desiredValue:
1058
+ desiredCircumradius ** 2 *
1059
+ ((numVertices / 2) * Math.sin((2 * Math.PI) / numVertices)),
1060
+ });
1061
+ } else {
1062
+ instructions.push({
1063
+ setDependency: "essentialCircumradius",
1064
+ desiredValue: desiredCircumradius,
1065
+ });
1066
+ }
1067
+
1068
+ instructions.push({
1069
+ setDependency: "essentialDirection",
1070
+ desiredValue: desiredDirection,
1071
+ });
1072
+
1073
+ let desiredVertices = {
1074
+ "0,0": me.fromAst(desiredDirectionWithRadius[0] + desiredCenter[0]),
1075
+ "0,1": me.fromAst(desiredDirectionWithRadius[1] + desiredCenter[1]),
1076
+ };
1077
+
1078
+ instructions.push({
1079
+ setDependency: "verticesAttr",
1080
+ desiredValue: desiredVertices,
1081
+ variableIndex: 0,
1082
+ });
1083
+ } else {
1084
+ // have at least two vertices specified
1085
+ // these vertices are adjacent vertices of the polygon, in counterclockwise order
1086
+
1087
+ let angle = (2 * Math.PI) / numVertices;
1088
+
1089
+ let c = Math.cos(angle);
1090
+ let s = Math.sin(angle);
1091
+
1092
+ let desiredDirectionWithRadius2 = [
1093
+ desiredDirectionWithRadius[0] * c -
1094
+ desiredDirectionWithRadius[1] * s,
1095
+ desiredDirectionWithRadius[0] * s +
1096
+ desiredDirectionWithRadius[1] * c,
1097
+ ];
1098
+
1099
+ let desiredVertices = {
1100
+ "0,0": me.fromAst(desiredDirectionWithRadius[0] + desiredCenter[0]),
1101
+ "0,1": me.fromAst(desiredDirectionWithRadius[1] + desiredCenter[1]),
1102
+ "1,0": me.fromAst(
1103
+ desiredDirectionWithRadius2[0] + desiredCenter[0],
1104
+ ),
1105
+ "1,1": me.fromAst(
1106
+ desiredDirectionWithRadius2[1] + desiredCenter[1],
1107
+ ),
1108
+ };
1109
+
1110
+ instructions.push({
1111
+ setDependency: "verticesAttr",
1112
+ desiredValue: desiredVertices,
1113
+ variableIndex: 0,
1114
+ });
1115
+ }
1116
+
1117
+ return {
1118
+ success: true,
1119
+ instructions,
1120
+ };
1121
+ },
1122
+ };
1123
+
1124
+ stateVariableDefinitions.vertices = {
1125
+ isLocation: true,
1126
+ public: true,
1127
+ shadowingInstructions: {
1128
+ createComponentOfType: "math",
1129
+ addAttributeComponentsShadowingStateVariables:
1130
+ returnRoundingAttributeComponentShadowing(),
1131
+ returnWrappingComponents(prefix) {
1132
+ if (prefix === "vertexX") {
1133
+ return [];
1134
+ } else {
1135
+ // vertex or entire array
1136
+ // wrap inner dimension by both <point> and <xs>
1137
+ // don't wrap outer dimension (for entire array)
1138
+ return [
1139
+ ["point", { componentType: "mathList", isAttribute: "xs" }],
1140
+ ];
1141
+ }
1142
+ },
1143
+ },
1144
+ isArray: true,
1145
+ numDimensions: 2,
1146
+ entryPrefixes: ["vertexX", "vertex"],
1147
+ getArrayKeysFromVarName({ arrayEntryPrefix, varEnding, arraySize }) {
1148
+ if (arrayEntryPrefix === "vertexX") {
1149
+ // vertexX1_2 is the 2nd component of the first vertex
1150
+ let indices = varEnding.split("_").map((x) => Number(x) - 1);
1151
+ if (
1152
+ indices.length === 2 &&
1153
+ indices.every((x, i) => Number.isInteger(x) && x >= 0)
1154
+ ) {
1155
+ if (arraySize) {
1156
+ if (indices.every((x, i) => x < arraySize[i])) {
1157
+ return [String(indices)];
1158
+ } else {
1159
+ return [];
1160
+ }
1161
+ } else {
1162
+ // If not given the array size,
1163
+ // then return the array keys assuming the array is large enough.
1164
+ // Must do this as it is used to determine potential array entries.
1165
+ return [String(indices)];
1166
+ }
1167
+ } else {
1168
+ return [];
1169
+ }
1170
+ } else {
1171
+ // vertex3 is all components of the third vertex
1172
+
1173
+ let pointInd = Number(varEnding) - 1;
1174
+ if (!(Number.isInteger(pointInd) && pointInd >= 0)) {
1175
+ return [];
1176
+ }
1177
+
1178
+ if (!arraySize) {
1179
+ // If don't have array size, we just need to determine if it is a potential entry.
1180
+ // Return the first entry assuming array is large enough
1181
+ return [pointInd + ",0"];
1182
+ }
1183
+ if (pointInd < arraySize[0]) {
1184
+ // array of "pointInd,i", where i=0, ..., arraySize[1]-1
1185
+ return Array.from(
1186
+ Array(arraySize[1]),
1187
+ (_, i) => pointInd + "," + i,
1188
+ );
1189
+ } else {
1190
+ return [];
1191
+ }
1192
+ }
1193
+ },
1194
+ arrayVarNameFromPropIndex(propIndex, varName) {
1195
+ if (varName === "vertices") {
1196
+ if (propIndex.length === 1) {
1197
+ return "vertex" + propIndex[0];
1198
+ } else {
1199
+ // if propIndex has additional entries, ignore them
1200
+ return `vertexX${propIndex[0]}_${propIndex[1]}`;
1201
+ }
1202
+ }
1203
+ if (varName.slice(0, 6) === "vertex") {
1204
+ // could be vertex or vertexX
1205
+ let vertexNum = Number(varName.slice(6));
1206
+ if (Number.isInteger(vertexNum) && vertexNum > 0) {
1207
+ // if propIndex has additional entries, ignore them
1208
+ return `vertexX${vertexNum}_${propIndex[0]}`;
1209
+ }
1210
+ }
1211
+ return null;
1212
+ },
1213
+ returnArraySizeDependencies: () => ({
1214
+ numVertices: {
1215
+ dependencyType: "stateVariable",
1216
+ variableName: "numVertices",
1217
+ },
1218
+ }),
1219
+ returnArraySize({ dependencyValues }) {
1220
+ return [dependencyValues.numVertices, 2];
1221
+ },
1222
+ returnArrayDependenciesByKey() {
1223
+ let globalDependencies = {
1224
+ numVertices: {
1225
+ dependencyType: "stateVariable",
1226
+ variableName: "numVertices",
1227
+ },
1228
+ centerComponents: {
1229
+ dependencyType: "stateVariable",
1230
+ variableName: "centerComponents",
1231
+ },
1232
+ directionWithRadius: {
1233
+ dependencyType: "stateVariable",
1234
+ variableName: "directionWithRadius",
1235
+ },
1236
+ };
1237
+
1238
+ return {
1239
+ globalDependencies,
1240
+ };
1241
+ },
1242
+ arrayDefinitionByKey({ globalDependencyValues }) {
1243
+ // just compute all vertices every time, as they are all mutually dependent
1244
+ // (rather than just computing for the array keys requested)
1245
+
1246
+ let numVertices = globalDependencyValues.numVertices;
1247
+
1248
+ let center = globalDependencyValues.centerComponents;
1249
+ let directionWithRadius = globalDependencyValues.directionWithRadius;
1250
+
1251
+ let vertices = {};
1252
+
1253
+ if (
1254
+ center.some((x) => !Number.isFinite(x)) ||
1255
+ directionWithRadius.some((x) => !Number.isFinite(x))
1256
+ ) {
1257
+ for (let vertexInd = 0; vertexInd < numVertices; vertexInd++) {
1258
+ vertices[`${vertexInd},0`] = me.fromAst("\uff3f");
1259
+ vertices[`${vertexInd},1`] = me.fromAst("\uff3f");
1260
+ }
1261
+ } else {
1262
+ for (let vertexInd = 0; vertexInd < numVertices; vertexInd++) {
1263
+ let rotation = (vertexInd * 2 * Math.PI) / numVertices;
1264
+
1265
+ let s = Math.sin(rotation);
1266
+ let c = Math.cos(rotation);
1267
+
1268
+ vertices[`${vertexInd},0`] = me.fromAst(
1269
+ center[0] +
1270
+ directionWithRadius[0] * c -
1271
+ directionWithRadius[1] * s,
1272
+ );
1273
+ vertices[`${vertexInd},1`] = me.fromAst(
1274
+ center[1] +
1275
+ directionWithRadius[0] * s +
1276
+ directionWithRadius[1] * c,
1277
+ );
1278
+ }
1279
+ }
1280
+
1281
+ return { setValue: { vertices } };
1282
+ },
1283
+
1284
+ async inverseArrayDefinitionByKey({
1285
+ desiredStateVariableValues,
1286
+ globalDependencyValues,
1287
+ stateValues,
1288
+ workspace,
1289
+ }) {
1290
+ let numVertices = globalDependencyValues.numVertices;
1291
+
1292
+ if (!workspace.desiredVertices) {
1293
+ workspace.desiredVertices = {};
1294
+ }
1295
+ Object.assign(
1296
+ workspace.desiredVertices,
1297
+ desiredStateVariableValues.vertices,
1298
+ );
1299
+
1300
+ let desiredKeys = Object.keys(workspace.desiredVertices);
1301
+ let vertexInd1String = desiredKeys[0].split(",")[0];
1302
+ let changingJustOneVertex = desiredKeys.every(
1303
+ (v) => v.split(",")[0] === vertexInd1String,
1304
+ );
1305
+
1306
+ let desiredCenter;
1307
+
1308
+ if (changingJustOneVertex) {
1309
+ // if change one vertex, then make sure that center stays the same
1310
+
1311
+ desiredCenter = (await stateValues.center).map((x) =>
1312
+ x.evaluate_to_constant(),
1313
+ );
1314
+ } else {
1315
+ // if change multiple vertices, then calculate center as average of all vertices
1316
+
1317
+ if (!workspace.allVertices) {
1318
+ workspace.allVertices = {};
1319
+ }
1320
+
1321
+ Object.assign(workspace.allVertices, workspace.desiredVertices);
1322
+
1323
+ let center_x = 0,
1324
+ center_y = 0;
1325
+
1326
+ for (let vertexInd = 0; vertexInd < numVertices; vertexInd++) {
1327
+ let v_x = workspace.allVertices[vertexInd + ",0"];
1328
+ if (!v_x) {
1329
+ let vertices = await stateValues.vertices;
1330
+ v_x = vertices[vertexInd][0];
1331
+ workspace.allVertices[vertexInd + ",0"] = v_x;
1332
+ }
1333
+
1334
+ let v_y = workspace.allVertices[vertexInd + ",1"];
1335
+ if (!v_y) {
1336
+ let vertices = await stateValues.vertices;
1337
+ v_y = vertices[vertexInd][1];
1338
+ workspace.allVertices[vertexInd + ",1"] = v_y;
1339
+ }
1340
+
1341
+ center_x += v_x.evaluate_to_constant();
1342
+ center_y += v_y.evaluate_to_constant();
1343
+ }
1344
+
1345
+ center_x /= numVertices;
1346
+ center_y /= numVertices;
1347
+
1348
+ desiredCenter = [center_x, center_y];
1349
+ }
1350
+
1351
+ // use the first index found in desired indices to determine directionWithRadius
1352
+ let vertexInd1 = Number(vertexInd1String);
1353
+
1354
+ let desiredVertex_x =
1355
+ workspace.desiredVertices[vertexInd1String + ",0"];
1356
+ if (!desiredVertex_x) {
1357
+ let vertices = await stateValues.vertices;
1358
+ desiredVertex_x = vertices[vertexInd1][0];
1359
+ }
1360
+
1361
+ let desiredVertex_y =
1362
+ workspace.desiredVertices[vertexInd1String + ",1"];
1363
+ if (!desiredVertex_y) {
1364
+ let vertices = await stateValues.vertices;
1365
+ desiredVertex_y = vertices[vertexInd1][1];
1366
+ }
1367
+
1368
+ let desiredVertex = [
1369
+ desiredVertex_x.evaluate_to_constant(),
1370
+ desiredVertex_y.evaluate_to_constant(),
1371
+ ];
1372
+
1373
+ let centerToVertex = [
1374
+ desiredVertex[0] - desiredCenter[0],
1375
+ desiredVertex[1] - desiredCenter[1],
1376
+ ];
1377
+
1378
+ let angle = (-vertexInd1 * 2 * Math.PI) / numVertices;
1379
+
1380
+ let c = Math.cos(angle);
1381
+ let s = Math.sin(angle);
1382
+
1383
+ let desiredDirectionWithRadius = [
1384
+ centerToVertex[0] * c - centerToVertex[1] * s,
1385
+ centerToVertex[0] * s + centerToVertex[1] * c,
1386
+ ];
1387
+
1388
+ let instructions = [
1389
+ {
1390
+ setDependency: "centerComponents",
1391
+ desiredValue: desiredCenter,
1392
+ },
1393
+ {
1394
+ setDependency: "directionWithRadius",
1395
+ desiredValue: desiredDirectionWithRadius,
1396
+ },
1397
+ ];
1398
+
1399
+ return {
1400
+ success: true,
1401
+ instructions,
1402
+ };
1403
+ },
1404
+ };
1405
+
1406
+ stateVariableDefinitions.center = {
1407
+ isLocation: true,
1408
+ public: true,
1409
+ isArray: true,
1410
+ entryPrefixes: ["centerX"],
1411
+ shadowingInstructions: {
1412
+ createComponentOfType: "math",
1413
+ addAttributeComponentsShadowingStateVariables:
1414
+ returnRoundingAttributeComponentShadowing(),
1415
+ returnWrappingComponents(prefix) {
1416
+ if (prefix === "centerX") {
1417
+ return [];
1418
+ } else {
1419
+ // entire array
1420
+ // wrap by both <point> and <xs>
1421
+ return [
1422
+ ["point", { componentType: "mathList", isAttribute: "xs" }],
1423
+ ];
1424
+ }
1425
+ },
1426
+ },
1427
+
1428
+ returnArraySizeDependencies: () => ({}),
1429
+ returnArraySize: () => [2],
1430
+
1431
+ returnArrayDependenciesByKey() {
1432
+ let globalDependencies = {
1433
+ centerComponents: {
1434
+ dependencyType: "stateVariable",
1435
+ variableName: "centerComponents",
1436
+ },
1437
+ };
1438
+
1439
+ return { globalDependencies };
1440
+ },
1441
+
1442
+ arrayDefinitionByKey({ globalDependencyValues }) {
1443
+ return {
1444
+ setValue: {
1445
+ center: globalDependencyValues.centerComponents.map((x) =>
1446
+ me.fromAst(x),
1447
+ ),
1448
+ },
1449
+ };
1450
+ },
1451
+
1452
+ async inverseArrayDefinitionByKey({
1453
+ desiredStateVariableValues,
1454
+ stateValues,
1455
+ workspace,
1456
+ }) {
1457
+ let desired_center_x = desiredStateVariableValues.center[0];
1458
+ if (!desired_center_x) {
1459
+ desired_center_x = workspace.desired_center_x;
1460
+ }
1461
+ if (!desired_center_x) {
1462
+ desired_center_x = (await stateValues.center)[0];
1463
+ }
1464
+ workspace.desired_center_x = desired_center_x;
1465
+
1466
+ let desired_center_y = desiredStateVariableValues.center[1];
1467
+ if (!desired_center_y) {
1468
+ desired_center_y = workspace.desired_center_y;
1469
+ }
1470
+ if (!desired_center_y) {
1471
+ desired_center_y = (await stateValues.center)[1];
1472
+ }
1473
+ workspace.desired_center_y = desired_center_y;
1474
+
1475
+ let instructions = [
1476
+ {
1477
+ setDependency: "centerComponents",
1478
+ desiredValue: [
1479
+ desired_center_x.evaluate_to_constant(),
1480
+ desired_center_y.evaluate_to_constant(),
1481
+ ],
1482
+ },
1483
+ ];
1484
+
1485
+ return {
1486
+ success: true,
1487
+ instructions,
1488
+ };
1489
+ },
1490
+ };
1491
+
1492
+ stateVariableDefinitions.circumradius = {
1493
+ isLocation: true,
1494
+ public: true,
1495
+ shadowingInstructions: {
1496
+ createComponentOfType: "number",
1497
+ addAttributeComponentsShadowingStateVariables:
1498
+ returnRoundingAttributeComponentShadowing(),
1499
+ },
1500
+ returnDependencies: () => ({
1501
+ center: {
1502
+ dependencyType: "stateVariable",
1503
+ variableName: "center",
1504
+ },
1505
+ vertex1: {
1506
+ dependencyType: "stateVariable",
1507
+ variableName: "vertex1",
1508
+ },
1509
+ }),
1510
+ definition({ dependencyValues }) {
1511
+ let center = dependencyValues.center.map((x) =>
1512
+ x.evaluate_to_constant(),
1513
+ );
1514
+
1515
+ let vertex1 = dependencyValues.vertex1.map((x) =>
1516
+ x.evaluate_to_constant(),
1517
+ );
1518
+
1519
+ let circumradius = Math.sqrt(
1520
+ (vertex1[0] - center[0]) ** 2 + (vertex1[1] - center[1]) ** 2,
1521
+ );
1522
+
1523
+ return { setValue: { circumradius } };
1524
+ },
1525
+ inverseDefinition({ desiredStateVariableValues, dependencyValues }) {
1526
+ let center = dependencyValues.center.map((x) =>
1527
+ x.evaluate_to_constant(),
1528
+ );
1529
+
1530
+ let vertex1 = dependencyValues.vertex1.map((x) =>
1531
+ x.evaluate_to_constant(),
1532
+ );
1533
+
1534
+ let directionWithRadius = [
1535
+ vertex1[0] - center[0],
1536
+ vertex1[1] - center[1],
1537
+ ];
1538
+
1539
+ let previousRadius = Math.sqrt(
1540
+ directionWithRadius[0] ** 2 + directionWithRadius[1] ** 2,
1541
+ );
1542
+
1543
+ let desiredRadius = desiredStateVariableValues.circumradius;
1544
+
1545
+ let desiredDirectionWithRadius = directionWithRadius.map(
1546
+ (x) => (x / previousRadius) * desiredRadius,
1547
+ );
1548
+
1549
+ let desiredVertex1 = [
1550
+ me.fromAst(desiredDirectionWithRadius[0] + center[0]),
1551
+ me.fromAst(desiredDirectionWithRadius[1] + center[1]),
1552
+ ];
1553
+
1554
+ return {
1555
+ success: true,
1556
+ instructions: [
1557
+ {
1558
+ setDependency: "vertex1",
1559
+ desiredValue: desiredVertex1,
1560
+ },
1561
+ ],
1562
+ };
1563
+ },
1564
+ };
1565
+
1566
+ stateVariableDefinitions.radius = {
1567
+ isAlias: true,
1568
+ targetVariableName: "circumradius",
1569
+ };
1570
+
1571
+ stateVariableDefinitions.inradius = {
1572
+ isLocation: true,
1573
+ public: true,
1574
+ shadowingInstructions: {
1575
+ createComponentOfType: "number",
1576
+ addAttributeComponentsShadowingStateVariables:
1577
+ returnRoundingAttributeComponentShadowing(),
1578
+ },
1579
+ returnDependencies: () => ({
1580
+ circumradius: {
1581
+ dependencyType: "stateVariable",
1582
+ variableName: "circumradius",
1583
+ },
1584
+ numVertices: {
1585
+ dependencyType: "stateVariable",
1586
+ variableName: "numVertices",
1587
+ },
1588
+ }),
1589
+ definition({ dependencyValues }) {
1590
+ let circumradius = dependencyValues.circumradius;
1591
+ let numVertices = dependencyValues.numVertices;
1592
+
1593
+ let inradius = circumradius * Math.cos(Math.PI / numVertices);
1594
+
1595
+ return { setValue: { inradius } };
1596
+ },
1597
+ inverseDefinition({ desiredStateVariableValues, dependencyValues }) {
1598
+ let desiredInradius = desiredStateVariableValues.inradius;
1599
+ let numVertices = dependencyValues.numVertices;
1600
+
1601
+ let desiredCircumradius =
1602
+ desiredInradius / Math.cos(Math.PI / numVertices);
1603
+
1604
+ return {
1605
+ success: true,
1606
+ instructions: [
1607
+ {
1608
+ setDependency: "circumradius",
1609
+ desiredValue: desiredCircumradius,
1610
+ },
1611
+ ],
1612
+ };
1613
+ },
1614
+ };
1615
+
1616
+ stateVariableDefinitions.apothem = {
1617
+ isAlias: true,
1618
+ targetVariableName: "inradius",
1619
+ };
1620
+
1621
+ stateVariableDefinitions.sideLength = {
1622
+ isLocation: true,
1623
+ public: true,
1624
+ shadowingInstructions: {
1625
+ createComponentOfType: "number",
1626
+ addAttributeComponentsShadowingStateVariables:
1627
+ returnRoundingAttributeComponentShadowing(),
1628
+ },
1629
+ returnDependencies: () => ({
1630
+ circumradius: {
1631
+ dependencyType: "stateVariable",
1632
+ variableName: "circumradius",
1633
+ },
1634
+ numVertices: {
1635
+ dependencyType: "stateVariable",
1636
+ variableName: "numVertices",
1637
+ },
1638
+ }),
1639
+ definition({ dependencyValues }) {
1640
+ let circumradius = dependencyValues.circumradius;
1641
+ let numVertices = dependencyValues.numVertices;
1642
+
1643
+ let sideLength = circumradius * (2 * Math.sin(Math.PI / numVertices));
1644
+
1645
+ return { setValue: { sideLength } };
1646
+ },
1647
+ inverseDefinition({ desiredStateVariableValues, dependencyValues }) {
1648
+ let desiredSideLength = desiredStateVariableValues.sideLength;
1649
+ let numVertices = dependencyValues.numVertices;
1650
+
1651
+ let desiredCircumradius =
1652
+ desiredSideLength / (2 * Math.sin(Math.PI / numVertices));
1653
+
1654
+ return {
1655
+ success: true,
1656
+ instructions: [
1657
+ {
1658
+ setDependency: "circumradius",
1659
+ desiredValue: desiredCircumradius,
1660
+ },
1661
+ ],
1662
+ };
1663
+ },
1664
+ };
1665
+
1666
+ stateVariableDefinitions.perimeter = {
1667
+ isLocation: true,
1668
+ public: true,
1669
+ shadowingInstructions: {
1670
+ createComponentOfType: "number",
1671
+ addAttributeComponentsShadowingStateVariables:
1672
+ returnRoundingAttributeComponentShadowing(),
1673
+ },
1674
+ returnDependencies: () => ({
1675
+ circumradius: {
1676
+ dependencyType: "stateVariable",
1677
+ variableName: "circumradius",
1678
+ },
1679
+ numVertices: {
1680
+ dependencyType: "stateVariable",
1681
+ variableName: "numVertices",
1682
+ },
1683
+ }),
1684
+ definition({ dependencyValues }) {
1685
+ let circumradius = dependencyValues.circumradius;
1686
+ let numVertices = dependencyValues.numVertices;
1687
+
1688
+ let perimeter =
1689
+ circumradius * (2 * numVertices * Math.sin(Math.PI / numVertices));
1690
+
1691
+ return { setValue: { perimeter } };
1692
+ },
1693
+ inverseDefinition({ desiredStateVariableValues, dependencyValues }) {
1694
+ let desiredPerimeter = desiredStateVariableValues.perimeter;
1695
+ let numVertices = dependencyValues.numVertices;
1696
+
1697
+ let desiredCircumradius =
1698
+ desiredPerimeter /
1699
+ (2 * numVertices * Math.sin(Math.PI / numVertices));
1700
+
1701
+ return {
1702
+ success: true,
1703
+ instructions: [
1704
+ {
1705
+ setDependency: "circumradius",
1706
+ desiredValue: desiredCircumradius,
1707
+ },
1708
+ ],
1709
+ };
1710
+ },
1711
+ };
1712
+
1713
+ stateVariableDefinitions.area = {
1714
+ isLocation: true,
1715
+ public: true,
1716
+ shadowingInstructions: {
1717
+ createComponentOfType: "number",
1718
+ addAttributeComponentsShadowingStateVariables:
1719
+ returnRoundingAttributeComponentShadowing(),
1720
+ },
1721
+ returnDependencies: () => ({
1722
+ circumradius: {
1723
+ dependencyType: "stateVariable",
1724
+ variableName: "circumradius",
1725
+ },
1726
+ numVertices: {
1727
+ dependencyType: "stateVariable",
1728
+ variableName: "numVertices",
1729
+ },
1730
+ }),
1731
+ definition({ dependencyValues }) {
1732
+ let circumradius = dependencyValues.circumradius;
1733
+ let numVertices = dependencyValues.numVertices;
1734
+
1735
+ let area =
1736
+ circumradius ** 2 *
1737
+ ((numVertices / 2) * Math.sin((2 * Math.PI) / numVertices));
1738
+
1739
+ return { setValue: { area } };
1740
+ },
1741
+ inverseDefinition({ desiredStateVariableValues, dependencyValues }) {
1742
+ let desiredArea = desiredStateVariableValues.area;
1743
+ let numVertices = dependencyValues.numVertices;
1744
+
1745
+ let desiredCircumradius = Math.sqrt(
1746
+ desiredArea /
1747
+ ((numVertices / 2) * Math.sin((2 * Math.PI) / numVertices)),
1748
+ );
1749
+
1750
+ return {
1751
+ success: true,
1752
+ instructions: [
1753
+ {
1754
+ setDependency: "circumradius",
1755
+ desiredValue: desiredCircumradius,
1756
+ },
1757
+ ],
1758
+ };
1759
+ },
1760
+ };
1761
+
1762
+ return stateVariableDefinitions;
1763
+ }
1764
+
1765
+ async movePolygon({
1766
+ pointCoords,
1767
+ transient,
1768
+ sourceDetails,
1769
+ actionId,
1770
+ sourceInformation = {},
1771
+ skipRendererUpdate = false,
1772
+ }) {
1773
+ let numVerticesMoved = Object.keys(pointCoords).length;
1774
+
1775
+ if (numVerticesMoved === 1) {
1776
+ // single vertex dragged
1777
+
1778
+ if (!(await this.stateValues.verticesDraggable)) {
1779
+ return await this.coreFunctions.resolveAction({ actionId });
1780
+ }
1781
+
1782
+ // Since the case where drag the entire regular polygon is complicated,
1783
+ // we perform the entire move for a single vertex here and return.
1784
+
1785
+ // If a single vertex is dragged, we perform update on the vertex,
1786
+ // as one typically does for a polygon
1787
+ let vertexComponents = {};
1788
+ for (let ind in pointCoords) {
1789
+ vertexComponents[ind + ",0"] = me.fromAst(pointCoords[ind][0]);
1790
+ vertexComponents[ind + ",1"] = me.fromAst(pointCoords[ind][1]);
1791
+ }
1792
+
1793
+ if (transient) {
1794
+ return await this.coreFunctions.performUpdate({
1795
+ updateInstructions: [
1796
+ {
1797
+ updateType: "updateValue",
1798
+ componentName: this.componentName,
1799
+ stateVariable: "vertices",
1800
+ value: vertexComponents,
1801
+ sourceDetails,
1802
+ },
1803
+ ],
1804
+ transient,
1805
+ actionId,
1806
+ sourceInformation,
1807
+ skipRendererUpdate,
1808
+ });
1809
+ } else {
1810
+ return await this.coreFunctions.performUpdate({
1811
+ updateInstructions: [
1812
+ {
1813
+ updateType: "updateValue",
1814
+ componentName: this.componentName,
1815
+ stateVariable: "vertices",
1816
+ value: vertexComponents,
1817
+ sourceDetails,
1818
+ },
1819
+ ],
1820
+ actionId,
1821
+ sourceInformation,
1822
+ skipRendererUpdate,
1823
+ event: {
1824
+ verb: "interacted",
1825
+ object: {
1826
+ componentName: this.componentName,
1827
+ componentType: this.componentType,
1828
+ },
1829
+ result: {
1830
+ pointCoordinates: pointCoords,
1831
+ },
1832
+ },
1833
+ });
1834
+ }
1835
+ }
1836
+
1837
+ // whole polyline dragged
1838
+ if (!(await this.stateValues.draggable)) {
1839
+ return await this.coreFunctions.resolveAction({ actionId });
1840
+ }
1841
+
1842
+ // In order to detect if one of the points used to defined the regular polygon is constrained
1843
+ // (so that we can adjust to keep the shape in that case)
1844
+ // we perform that calculations of the inverseDefinition of vertices here
1845
+ // and perform that update directly on centerComponents and directionWithRadius.
1846
+ // (The inverse definition of vertices will still be used if other components
1847
+ // are connected to the vertices.)
1848
+ // We just want this special behavior for the case when the entire polygon
1849
+ // is moved by the renderer.
1850
+
1851
+ let numVertices = await this.stateValues.numVertices;
1852
+
1853
+ // First calculate the desired centers as the average of all points
1854
+
1855
+ let center_x = 0,
1856
+ center_y = 0;
1857
+
1858
+ for (let vertexInd = 0; vertexInd < numVertices; vertexInd++) {
1859
+ center_x += pointCoords[vertexInd][0];
1860
+ center_y += pointCoords[vertexInd][1];
1861
+ }
1862
+
1863
+ center_x /= numVertices;
1864
+ center_y /= numVertices;
1865
+
1866
+ let center = [center_x, center_y];
1867
+
1868
+ // use the first index determine directionWithRadius
1869
+ let vertex1 = pointCoords[0];
1870
+
1871
+ let directionWithRadius = [vertex1[0] - center[0], vertex1[1] - center[1]];
1872
+
1873
+ let updateInstructions = [
1874
+ {
1875
+ updateType: "updateValue",
1876
+ componentName: this.componentName,
1877
+ stateVariable: "centerComponents",
1878
+ value: center,
1879
+ sourceDetails,
1880
+ },
1881
+ {
1882
+ updateType: "updateValue",
1883
+ componentName: this.componentName,
1884
+ stateVariable: "directionWithRadius",
1885
+ value: directionWithRadius,
1886
+ sourceDetails,
1887
+ },
1888
+ ];
1889
+
1890
+ // Note: we set skipRendererUpdate to true
1891
+ // so that we can make further adjustments before the renderers are updated
1892
+ if (transient) {
1893
+ await this.coreFunctions.performUpdate({
1894
+ updateInstructions,
1895
+ transient,
1896
+ actionId,
1897
+ sourceInformation,
1898
+ skipRendererUpdate: true,
1899
+ });
1900
+ } else {
1901
+ await this.coreFunctions.performUpdate({
1902
+ updateInstructions,
1903
+ actionId,
1904
+ sourceInformation,
1905
+ skipRendererUpdate: true,
1906
+ event: {
1907
+ verb: "interacted",
1908
+ object: {
1909
+ componentName: this.componentName,
1910
+ componentType: this.componentType,
1911
+ },
1912
+ result: {
1913
+ pointCoordinates: pointCoords,
1914
+ },
1915
+ },
1916
+ });
1917
+ }
1918
+
1919
+ // we will attempt to create a rigid translation of the polygon
1920
+ // even if a subset of the vertices are constrained.
1921
+ let numVerticesSpecified = await this.stateValues.numVerticesSpecified;
1922
+ let haveSpecifiedCenter = await this.stateValues.haveSpecifiedCenter;
1923
+
1924
+ if (haveSpecifiedCenter) {
1925
+ if (numVerticesSpecified >= 1) {
1926
+ // polygon was determined by center and 1 vertex
1927
+
1928
+ let resultingCenter = await this.stateValues.centerComponents;
1929
+
1930
+ let resultingDirectionWithRadius = await this.stateValues
1931
+ .directionWithRadius;
1932
+ let resultingVertex1 = [
1933
+ resultingCenter[0] + resultingDirectionWithRadius[0],
1934
+ resultingCenter[1] + resultingDirectionWithRadius[1],
1935
+ ];
1936
+
1937
+ let tol = 1e-6;
1938
+
1939
+ let vertex1Changed = !vertex1.every(
1940
+ (v, i) => Math.abs(v - resultingVertex1[i]) < tol,
1941
+ );
1942
+ let centerChanged = !center.every(
1943
+ (v, i) => Math.abs(v - resultingCenter[i]) < tol,
1944
+ );
1945
+
1946
+ if (centerChanged) {
1947
+ if (!vertex1Changed) {
1948
+ // only center changed
1949
+ // keep directionWithRadius the same
1950
+ // and use new center position
1951
+
1952
+ let newInstructions = [
1953
+ {
1954
+ updateType: "updateValue",
1955
+ componentName: this.componentName,
1956
+ stateVariable: "centerComponents",
1957
+ value: resultingCenter,
1958
+ },
1959
+ {
1960
+ updateType: "updateValue",
1961
+ componentName: this.componentName,
1962
+ stateVariable: "directionWithRadius",
1963
+ value: directionWithRadius,
1964
+ },
1965
+ ];
1966
+ return await this.coreFunctions.performUpdate({
1967
+ updateInstructions: newInstructions,
1968
+ transient,
1969
+ actionId,
1970
+ sourceInformation,
1971
+ skipRendererUpdate,
1972
+ });
1973
+ }
1974
+ } else if (vertex1Changed) {
1975
+ // only vertex 1 changed
1976
+ // keep directionWithRadius the same
1977
+ // adjust center to put vertex 1 at its new location
1978
+
1979
+ let newCenter = [
1980
+ resultingVertex1[0] - directionWithRadius[0],
1981
+ resultingVertex1[1] - directionWithRadius[1],
1982
+ ];
1983
+
1984
+ let newInstructions = [
1985
+ {
1986
+ updateType: "updateValue",
1987
+ componentName: this.componentName,
1988
+ stateVariable: "centerComponents",
1989
+ value: newCenter,
1990
+ },
1991
+ {
1992
+ updateType: "updateValue",
1993
+ componentName: this.componentName,
1994
+ stateVariable: "directionWithRadius",
1995
+ value: directionWithRadius,
1996
+ },
1997
+ ];
1998
+ return await this.coreFunctions.performUpdate({
1999
+ updateInstructions: newInstructions,
2000
+ transient,
2001
+ actionId,
2002
+ sourceInformation,
2003
+ skipRendererUpdate,
2004
+ });
2005
+ }
2006
+ }
2007
+ } else if (numVerticesSpecified >= 2) {
2008
+ //polygon was determined by two vertices
2009
+
2010
+ // calculate the value of vertex2 calculated from center and vertex1
2011
+ let angle = (2 * Math.PI) / numVertices;
2012
+
2013
+ let c = Math.cos(angle);
2014
+ let s = Math.sin(angle);
2015
+
2016
+ let directionWithRadius2 = [
2017
+ directionWithRadius[0] * c - directionWithRadius[1] * s,
2018
+ directionWithRadius[0] * s + directionWithRadius[1] * c,
2019
+ ];
2020
+
2021
+ let vertex2 = [
2022
+ directionWithRadius2[0] + center[0],
2023
+ directionWithRadius2[1] + center[1],
2024
+ ];
2025
+
2026
+ let resultingVertices = await this.stateValues.vertices;
2027
+ let resultingVertex1 = resultingVertices[0].map((x) =>
2028
+ x.evaluate_to_constant(),
2029
+ );
2030
+ let resultingVertex2 = resultingVertices[1].map((x) =>
2031
+ x.evaluate_to_constant(),
2032
+ );
2033
+
2034
+ let tol = 1e-6;
2035
+
2036
+ let vertex1Changed = !vertex1.every(
2037
+ (v, i) => Math.abs(v - resultingVertex1[i]) < tol,
2038
+ );
2039
+ let vertex2Changed = !vertex2.every(
2040
+ (v, i) => Math.abs(v - resultingVertex2[i]) < tol,
2041
+ );
2042
+
2043
+ if (vertex1Changed) {
2044
+ if (!vertex2Changed) {
2045
+ // only vertex 1 changed
2046
+ // keep directionWithRadius the same
2047
+ // adjust center to put vertex 1 at its new location
2048
+
2049
+ let newCenter = [
2050
+ resultingVertex1[0] - directionWithRadius[0],
2051
+ resultingVertex1[1] - directionWithRadius[1],
2052
+ ];
2053
+
2054
+ let newInstructions = [
2055
+ {
2056
+ updateType: "updateValue",
2057
+ componentName: this.componentName,
2058
+ stateVariable: "centerComponents",
2059
+ value: newCenter,
2060
+ },
2061
+ {
2062
+ updateType: "updateValue",
2063
+ componentName: this.componentName,
2064
+ stateVariable: "directionWithRadius",
2065
+ value: directionWithRadius,
2066
+ },
2067
+ ];
2068
+ return await this.coreFunctions.performUpdate({
2069
+ updateInstructions: newInstructions,
2070
+ transient,
2071
+ actionId,
2072
+ sourceInformation,
2073
+ skipRendererUpdate,
2074
+ });
2075
+ }
2076
+ } else if (vertex2Changed) {
2077
+ // only vertex 2 changed
2078
+ // keep directionWithRadius the same
2079
+ // adjust center to put vertex 2 at its new location
2080
+
2081
+ let newCenter = [
2082
+ resultingVertex2[0] - directionWithRadius2[0],
2083
+ resultingVertex2[1] - directionWithRadius2[1],
2084
+ ];
2085
+
2086
+ let newInstructions = [
2087
+ {
2088
+ updateType: "updateValue",
2089
+ componentName: this.componentName,
2090
+ stateVariable: "centerComponents",
2091
+ value: newCenter,
2092
+ },
2093
+ {
2094
+ updateType: "updateValue",
2095
+ componentName: this.componentName,
2096
+ stateVariable: "directionWithRadius",
2097
+ value: directionWithRadius,
2098
+ },
2099
+ ];
2100
+ return await this.coreFunctions.performUpdate({
2101
+ updateInstructions: newInstructions,
2102
+ transient,
2103
+ actionId,
2104
+ sourceInformation,
2105
+ skipRendererUpdate,
2106
+ });
2107
+ }
2108
+ }
2109
+
2110
+ // if no modifications were made, still need to update renderers
2111
+ // as original update was performed with skipping renderer update
2112
+ return await this.coreFunctions.updateRenderers({
2113
+ actionId,
2114
+ sourceInformation,
2115
+ skipRendererUpdate,
2116
+ });
2117
+ }
2118
+ }