@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.
- package/.prettierrc +3 -0
- package/LICENSE +661 -0
- package/README.md +146 -0
- package/cypress/e2e/ActivityViewer/activityVariants.cy.js +1770 -0
- package/cypress/e2e/ActivityViewer/compiledActivity.cy.js +83 -0
- package/cypress/e2e/ActivityViewer/relationshipsAmongPages.cy.js +697 -0
- package/cypress/e2e/answerValidation/errorinnumbers.cy.js +2125 -0
- package/cypress/e2e/answerValidation/factoring.cy.js +1945 -0
- package/cypress/e2e/answerValidation/factoringOldAlgorithm.cy.js +892 -0
- package/cypress/e2e/answerValidation/functionanswers.cy.js +314 -0
- package/cypress/e2e/answerValidation/matchingpatterns.cy.js +287 -0
- package/cypress/e2e/answerValidation/matchpartial.cy.js +6711 -0
- package/cypress/e2e/answerValidation/pointlocation.cy.js +3989 -0
- package/cypress/e2e/answerValidation/symbolicequality.cy.js +1893 -0
- package/cypress/e2e/answerValidation/videoProgress.cy.js +210 -0
- package/cypress/e2e/assignNames/basiccopy.cy.js +2376 -0
- package/cypress/e2e/assignNames/collections.cy.js +9247 -0
- package/cypress/e2e/assignNames/selects.cy.js +105 -0
- package/cypress/e2e/assignNames/sequences.cy.js +1964 -0
- package/cypress/e2e/baseComponent/basecomponentproperties.cy.js +999 -0
- package/cypress/e2e/baseComponent/doenetMLtext.cy.js +427 -0
- package/cypress/e2e/chemistry/atom.cy.js +201 -0
- package/cypress/e2e/chemistry/ion.cy.js +608 -0
- package/cypress/e2e/chemistry/ioniccompound.cy.js +133 -0
- package/cypress/e2e/dynamicalsystem/cobwebpolyline.cy.js +2653 -0
- package/cypress/e2e/dynamicalsystem/equilibriumcurve.cy.js +311 -0
- package/cypress/e2e/dynamicalsystem/equilibriumline.cy.js +279 -0
- package/cypress/e2e/dynamicalsystem/equilibriumpoint.cy.js +283 -0
- package/cypress/e2e/dynamicalsystem/odesystem.cy.js +1834 -0
- package/cypress/e2e/equality/mathexpressions.cy.js +948 -0
- package/cypress/e2e/graphing/graphreferences.cy.js +978 -0
- package/cypress/e2e/graphing/graphreferences2.cy.js +615 -0
- package/cypress/e2e/linearAlgebra/eigenDecomposition.cy.js +401 -0
- package/cypress/e2e/tagSpecific/angle.cy.js +3898 -0
- package/cypress/e2e/tagSpecific/animatefromsequence.cy.js +2306 -0
- package/cypress/e2e/tagSpecific/answer.cy.js +31647 -0
- package/cypress/e2e/tagSpecific/bestfitline.cy.js +612 -0
- package/cypress/e2e/tagSpecific/blockquote.cy.js +30 -0
- package/cypress/e2e/tagSpecific/boolean.cy.js +742 -0
- package/cypress/e2e/tagSpecific/booleaninput.cy.js +1283 -0
- package/cypress/e2e/tagSpecific/booleanlist.cy.js +588 -0
- package/cypress/e2e/tagSpecific/booleanoperators.cy.js +596 -0
- package/cypress/e2e/tagSpecific/booleanoperatorsonmath.cy.js +498 -0
- package/cypress/e2e/tagSpecific/callaction.cy.js +2835 -0
- package/cypress/e2e/tagSpecific/choiceinput.cy.js +3205 -0
- package/cypress/e2e/tagSpecific/circle.cy.js +22036 -0
- package/cypress/e2e/tagSpecific/codeeditor.cy.js +1995 -0
- package/cypress/e2e/tagSpecific/collect.cy.js +5035 -0
- package/cypress/e2e/tagSpecific/componentsize.cy.js +502 -0
- package/cypress/e2e/tagSpecific/conditionalcontent.cy.js +3495 -0
- package/cypress/e2e/tagSpecific/contentBrowser.cy.js +335 -0
- package/cypress/e2e/tagSpecific/contentpicker.cy.js +261 -0
- package/cypress/e2e/tagSpecific/copy.cy.js +12627 -0
- package/cypress/e2e/tagSpecific/copy2.cy.js +5698 -0
- package/cypress/e2e/tagSpecific/curve.bezier.cy.js +12440 -0
- package/cypress/e2e/tagSpecific/curve.cy.js +1716 -0
- package/cypress/e2e/tagSpecific/curve.function.cy.js +1471 -0
- package/cypress/e2e/tagSpecific/curve.parametrized.cy.js +920 -0
- package/cypress/e2e/tagSpecific/document.cy.js +234 -0
- package/cypress/e2e/tagSpecific/endpoint.cy.js +197 -0
- package/cypress/e2e/tagSpecific/evaluate.cy.js +8895 -0
- package/cypress/e2e/tagSpecific/extract.cy.js +2282 -0
- package/cypress/e2e/tagSpecific/feedback.cy.js +2941 -0
- package/cypress/e2e/tagSpecific/function.cy.js +9450 -0
- package/cypress/e2e/tagSpecific/functioniterates.cy.js +1178 -0
- package/cypress/e2e/tagSpecific/functionoperators.cy.js +4047 -0
- package/cypress/e2e/tagSpecific/graph.cy.js +2491 -0
- package/cypress/e2e/tagSpecific/group.cy.js +683 -0
- package/cypress/e2e/tagSpecific/hint.cy.js +204 -0
- package/cypress/e2e/tagSpecific/image.cy.js +770 -0
- package/cypress/e2e/tagSpecific/integer.cy.js +206 -0
- package/cypress/e2e/tagSpecific/label.cy.js +800 -0
- package/cypress/e2e/tagSpecific/legend.cy.js +1001 -0
- package/cypress/e2e/tagSpecific/line.cy.js +12167 -0
- package/cypress/e2e/tagSpecific/linesegment.cy.js +4749 -0
- package/cypress/e2e/tagSpecific/lorem.cy.js +289 -0
- package/cypress/e2e/tagSpecific/map.cy.js +4476 -0
- package/cypress/e2e/tagSpecific/matchespattern.cy.js +693 -0
- package/cypress/e2e/tagSpecific/math.cy.js +10990 -0
- package/cypress/e2e/tagSpecific/mathdisplay.cy.js +2689 -0
- package/cypress/e2e/tagSpecific/mathinput.cy.js +15628 -0
- package/cypress/e2e/tagSpecific/mathinputgraph.cy.js +566 -0
- package/cypress/e2e/tagSpecific/mathlist.cy.js +4073 -0
- package/cypress/e2e/tagSpecific/mathoperators.cy.js +13851 -0
- package/cypress/e2e/tagSpecific/matrix.cy.js +8825 -0
- package/cypress/e2e/tagSpecific/matrixinput.cy.js +16277 -0
- package/cypress/e2e/tagSpecific/module.cy.js +1771 -0
- package/cypress/e2e/tagSpecific/number.cy.js +2221 -0
- package/cypress/e2e/tagSpecific/numberlist.cy.js +1285 -0
- package/cypress/e2e/tagSpecific/p.cy.js +72 -0
- package/cypress/e2e/tagSpecific/paginator.cy.js +2983 -0
- package/cypress/e2e/tagSpecific/parabola.cy.js +14331 -0
- package/cypress/e2e/tagSpecific/paragraphmarkup.cy.js +104 -0
- package/cypress/e2e/tagSpecific/periodicset.cy.js +1439 -0
- package/cypress/e2e/tagSpecific/piecewisefunction.cy.js +1055 -0
- package/cypress/e2e/tagSpecific/pluralize.cy.js +274 -0
- package/cypress/e2e/tagSpecific/point.cy.js +8895 -0
- package/cypress/e2e/tagSpecific/point2.cy.js +10259 -0
- package/cypress/e2e/tagSpecific/polygon.cy.js +5039 -0
- package/cypress/e2e/tagSpecific/polyline.cy.js +4704 -0
- package/cypress/e2e/tagSpecific/problem.cy.js +2768 -0
- package/cypress/e2e/tagSpecific/ray.cy.js +10770 -0
- package/cypress/e2e/tagSpecific/rectangle.cy.js +2143 -0
- package/cypress/e2e/tagSpecific/ref.cy.js +420 -0
- package/cypress/e2e/tagSpecific/regularPolygon.cy.js +1006 -0
- package/cypress/e2e/tagSpecific/regularPolygon2.cy.js +100 -0
- package/cypress/e2e/tagSpecific/regularPolygon3.cy.js +777 -0
- package/cypress/e2e/tagSpecific/samplerandomnumbers.cy.js +3619 -0
- package/cypress/e2e/tagSpecific/sectioning.cy.js +3530 -0
- package/cypress/e2e/tagSpecific/select.cy.js +5376 -0
- package/cypress/e2e/tagSpecific/selectfromsequence.cy.js +3846 -0
- package/cypress/e2e/tagSpecific/selectrandomnumbers.cy.js +2914 -0
- package/cypress/e2e/tagSpecific/sequence.cy.js +2093 -0
- package/cypress/e2e/tagSpecific/shuffle.cy.js +490 -0
- package/cypress/e2e/tagSpecific/sidebyside.cy.js +8057 -0
- package/cypress/e2e/tagSpecific/singlecharactercomponents.cy.js +72 -0
- package/cypress/e2e/tagSpecific/slider.cy.js +914 -0
- package/cypress/e2e/tagSpecific/solution.cy.js +109 -0
- package/cypress/e2e/tagSpecific/solveequations.cy.js +1026 -0
- package/cypress/e2e/tagSpecific/sort.cy.js +1685 -0
- package/cypress/e2e/tagSpecific/spreadsheet.cy.js +5971 -0
- package/cypress/e2e/tagSpecific/subsetofreals.cy.js +2725 -0
- package/cypress/e2e/tagSpecific/substitute.cy.js +2646 -0
- package/cypress/e2e/tagSpecific/tabular.cy.js +36 -0
- package/cypress/e2e/tagSpecific/text.cy.js +975 -0
- package/cypress/e2e/tagSpecific/textinput.cy.js +2177 -0
- package/cypress/e2e/tagSpecific/textlist.cy.js +369 -0
- package/cypress/e2e/tagSpecific/triangle.cy.js +1936 -0
- package/cypress/e2e/tagSpecific/triggerset.cy.js +2023 -0
- package/cypress/e2e/tagSpecific/updatevalue.cy.js +3288 -0
- package/cypress/e2e/tagSpecific/vector.cy.js +20183 -0
- package/cypress/e2e/tagSpecific/video.cy.js +612 -0
- package/cypress/e2e/tagSpecific/when.cy.js +202 -0
- package/cypress/e2e/variants/specifysinglevariant.cy.js +6726 -0
- package/cypress/e2e/variants/uniquevariants.cy.js +4846 -0
- package/cypress/fixtures/example.json +5 -0
- package/cypress/support/commands.js +32 -0
- package/cypress/support/e2e.js +31 -0
- package/cypress.config.js +18 -0
- package/docs/codeSnippet.jsx +11 -0
- package/docs/index.html +133 -0
- package/docs/index.jsx +138 -0
- package/docs/prism.css +3 -0
- package/index.html +14 -0
- package/index.js +21 -0
- package/media/answer_example.png +0 -0
- package/media/graph_example.png +0 -0
- package/media/graph_markup_example.png +0 -0
- package/package.json +83 -0
- package/public/favicon.ico +0 -0
- package/public/fonts/files/open-sans-v18-latin-700.woff +0 -0
- package/public/fonts/files/open-sans-v18-latin-700.woff2 +0 -0
- package/public/fonts/files/open-sans-v18-latin-700italic.woff +0 -0
- package/public/fonts/files/open-sans-v18-latin-700italic.woff2 +0 -0
- package/public/fonts/files/open-sans-v18-latin-italic.woff +0 -0
- package/public/fonts/files/open-sans-v18-latin-italic.woff2 +0 -0
- package/public/fonts/files/open-sans-v18-latin-light-italic.woff +0 -0
- package/public/fonts/files/open-sans-v18-latin-light-italic.woff2 +0 -0
- package/public/fonts/files/open-sans-v18-latin-light.woff +0 -0
- package/public/fonts/files/open-sans-v18-latin-light.woff2 +0 -0
- package/public/fonts/files/open-sans-v18-latin-regular.woff +0 -0
- package/public/fonts/files/open-sans-v18-latin-regular.woff2 +0 -0
- package/src/Core/ComponentTypes.js +426 -0
- package/src/Core/Core.js +11852 -0
- package/src/Core/CoreWorker.js +127 -0
- package/src/Core/Dependencies.js +8226 -0
- package/src/Core/Numerics.js +473 -0
- package/src/Core/ParameterStack.js +36 -0
- package/src/Core/ReadOnlyProxyHandler.js +41 -0
- package/src/Core/StateProxyHandler.js +88 -0
- package/src/Core/components/Aliases.js +67 -0
- package/src/Core/components/Angle.js +758 -0
- package/src/Core/components/AnimateFromSequence.js +922 -0
- package/src/Core/components/Answer.js +2087 -0
- package/src/Core/components/AsList.js +83 -0
- package/src/Core/components/AttractTo.js +245 -0
- package/src/Core/components/AttractToAngles.js +262 -0
- package/src/Core/components/AttractToConstraint.js +104 -0
- package/src/Core/components/AttractToGrid.js +315 -0
- package/src/Core/components/Award.js +906 -0
- package/src/Core/components/BestFitLine.js +318 -0
- package/src/Core/components/BezierControls.js +719 -0
- package/src/Core/components/BlockQuote.js +35 -0
- package/src/Core/components/Boolean.js +500 -0
- package/src/Core/components/BooleanInput.js +330 -0
- package/src/Core/components/BooleanList.js +396 -0
- package/src/Core/components/BooleanOperators.js +35 -0
- package/src/Core/components/BooleanOperatorsOfMath.js +148 -0
- package/src/Core/components/CallAction.js +261 -0
- package/src/Core/components/Caption.js +73 -0
- package/src/Core/components/Case.js +56 -0
- package/src/Core/components/Cell.js +439 -0
- package/src/Core/components/CellBlock.js +64 -0
- package/src/Core/components/Chart.js +795 -0
- package/src/Core/components/Choice.js +266 -0
- package/src/Core/components/ChoiceInput.js +1407 -0
- package/src/Core/components/Circle.js +2884 -0
- package/src/Core/components/CodeEditor.js +647 -0
- package/src/Core/components/CodeViewer.js +294 -0
- package/src/Core/components/CollaborateGroupSetup.js +46 -0
- package/src/Core/components/CollaborateGroups.js +119 -0
- package/src/Core/components/Collect.js +850 -0
- package/src/Core/components/Column.js +608 -0
- package/src/Core/components/ConditionalContent.js +468 -0
- package/src/Core/components/ConsiderAsResponses.js +49 -0
- package/src/Core/components/ConstrainTo.js +161 -0
- package/src/Core/components/ConstrainToAngles.js +244 -0
- package/src/Core/components/ConstrainToGraph.js +142 -0
- package/src/Core/components/ConstrainToGrid.js +175 -0
- package/src/Core/components/ConstraintUnion.js +119 -0
- package/src/Core/components/Constraints.js +497 -0
- package/src/Core/components/ContentBrowser.js +441 -0
- package/src/Core/components/ContentPicker.js +263 -0
- package/src/Core/components/ControlVectors.js +25 -0
- package/src/Core/components/Coords.js +63 -0
- package/src/Core/components/Copy.js +3412 -0
- package/src/Core/components/Curve.js +4130 -0
- package/src/Core/components/CustomAttribute.js +175 -0
- package/src/Core/components/DataFrame.js +357 -0
- package/src/Core/components/DiscreteSimulationResultList.js +342 -0
- package/src/Core/components/DiscreteSimulationResultPolyline.js +581 -0
- package/src/Core/components/Divisions.js +55 -0
- package/src/Core/components/Document.js +888 -0
- package/src/Core/components/Embed.js +65 -0
- package/src/Core/components/Endpoint.js +62 -0
- package/src/Core/components/Evaluate.js +321 -0
- package/src/Core/components/Extract.js +656 -0
- package/src/Core/components/Extrema.js +556 -0
- package/src/Core/components/Feedback.js +200 -0
- package/src/Core/components/FeedbackDefinitions.js +97 -0
- package/src/Core/components/Figure.js +148 -0
- package/src/Core/components/Footnote.js +73 -0
- package/src/Core/components/Function.js +5344 -0
- package/src/Core/components/FunctionIterates.js +306 -0
- package/src/Core/components/FunctionOperators.js +702 -0
- package/src/Core/components/Graph.js +1679 -0
- package/src/Core/components/Group.js +7 -0
- package/src/Core/components/HasSameFactoring.js +407 -0
- package/src/Core/components/Hint.js +241 -0
- package/src/Core/components/Image.js +524 -0
- package/src/Core/components/Indexing.js +79 -0
- package/src/Core/components/IntComma.js +64 -0
- package/src/Core/components/Integer.js +81 -0
- package/src/Core/components/Intersection.js +328 -0
- package/src/Core/components/Interval.js +29 -0
- package/src/Core/components/Label.js +492 -0
- package/src/Core/components/Latex.js +104 -0
- package/src/Core/components/Legend.js +329 -0
- package/src/Core/components/Line.js +2040 -0
- package/src/Core/components/LineSegment.js +882 -0
- package/src/Core/components/Lists.js +180 -0
- package/src/Core/components/Lorem.js +249 -0
- package/src/Core/components/MMeMen.js +377 -0
- package/src/Core/components/Map.js +873 -0
- package/src/Core/components/Markers.js +101 -0
- package/src/Core/components/MatchesPattern.js +339 -0
- package/src/Core/components/Math.js +2552 -0
- package/src/Core/components/MathInput.js +948 -0
- package/src/Core/components/MathList.js +828 -0
- package/src/Core/components/MathOperators.js +1286 -0
- package/src/Core/components/Matrix.js +497 -0
- package/src/Core/components/MatrixInput.js +3157 -0
- package/src/Core/components/MdMdnMrow.js +394 -0
- package/src/Core/components/Module.js +16 -0
- package/src/Core/components/Number.js +1031 -0
- package/src/Core/components/NumberList.js +550 -0
- package/src/Core/components/Option.js +24 -0
- package/src/Core/components/P.js +71 -0
- package/src/Core/components/Paginator.js +338 -0
- package/src/Core/components/Panel.js +126 -0
- package/src/Core/components/Parabola.js +1561 -0
- package/src/Core/components/ParagraphMarkup.js +59 -0
- package/src/Core/components/Pegboard.js +43 -0
- package/src/Core/components/PeriodicSet.js +291 -0
- package/src/Core/components/PiecewiseFunction.js +832 -0
- package/src/Core/components/Pluralize.js +198 -0
- package/src/Core/components/Point.js +1295 -0
- package/src/Core/components/Polygon.js +408 -0
- package/src/Core/components/Polyline.js +841 -0
- package/src/Core/components/RandomizedTextList.js +225 -0
- package/src/Core/components/Ray.js +1737 -0
- package/src/Core/components/Rectangle.js +1535 -0
- package/src/Core/components/Ref.js +350 -0
- package/src/Core/components/RegionBetweenCurveXAxis.js +124 -0
- package/src/Core/components/RegionHalfPlane.js +107 -0
- package/src/Core/components/RegularPolygon.js +2118 -0
- package/src/Core/components/RenderDoenetML.js +181 -0
- package/src/Core/components/Row.js +780 -0
- package/src/Core/components/SampleRandomNumbers.js +653 -0
- package/src/Core/components/Sectioning.js +303 -0
- package/src/Core/components/Select.js +947 -0
- package/src/Core/components/SelectFromSequence.js +1242 -0
- package/src/Core/components/SelectRandomNumbers.js +225 -0
- package/src/Core/components/Sequence.js +444 -0
- package/src/Core/components/Setup.js +53 -0
- package/src/Core/components/Shuffle.js +470 -0
- package/src/Core/components/SideBySide.js +2130 -0
- package/src/Core/components/SingleCharacterComponents.js +41 -0
- package/src/Core/components/Slider.js +819 -0
- package/src/Core/components/SolutionContainer.js +67 -0
- package/src/Core/components/Solutions.js +334 -0
- package/src/Core/components/SolveEquations.js +568 -0
- package/src/Core/components/Sort.js +398 -0
- package/src/Core/components/Sources.js +108 -0
- package/src/Core/components/Split.js +205 -0
- package/src/Core/components/Spreadsheet.js +1507 -0
- package/src/Core/components/StyleDefinitions.js +111 -0
- package/src/Core/components/SubsetOfReals.js +348 -0
- package/src/Core/components/SubsetOfRealsInput.js +1474 -0
- package/src/Core/components/Substitute.js +496 -0
- package/src/Core/components/SummaryStatistics.js +652 -0
- package/src/Core/components/Table.js +145 -0
- package/src/Core/components/Tabular.js +384 -0
- package/src/Core/components/Template.js +360 -0
- package/src/Core/components/Text.js +341 -0
- package/src/Core/components/TextInput.js +566 -0
- package/src/Core/components/TextList.js +442 -0
- package/src/Core/components/TextListFromString.js +137 -0
- package/src/Core/components/TextOperatorsOfMath.js +21 -0
- package/src/Core/components/Triangle.js +280 -0
- package/src/Core/components/TriggerSet.js +189 -0
- package/src/Core/components/TupleList.js +43 -0
- package/src/Core/components/UpdateValue.js +435 -0
- package/src/Core/components/VariantControl.js +36 -0
- package/src/Core/components/Vector.js +2478 -0
- package/src/Core/components/Verbatim.js +125 -0
- package/src/Core/components/Video.js +673 -0
- package/src/Core/components/When.js +198 -0
- package/src/Core/components/abstract/AngleListComponent.js +140 -0
- package/src/Core/components/abstract/BaseComponent.js +1496 -0
- package/src/Core/components/abstract/BlockComponent.js +5 -0
- package/src/Core/components/abstract/BooleanBaseOperator.js +88 -0
- package/src/Core/components/abstract/BooleanBaseOperatorOfMath.js +100 -0
- package/src/Core/components/abstract/BooleanBaseOperatorOneInput.js +44 -0
- package/src/Core/components/abstract/ComponentSize.js +789 -0
- package/src/Core/components/abstract/ComponentWithSelectableType.js +537 -0
- package/src/Core/components/abstract/CompositeComponent.js +142 -0
- package/src/Core/components/abstract/ConstraintComponent.js +19 -0
- package/src/Core/components/abstract/FunctionBaseOperator.js +680 -0
- package/src/Core/components/abstract/GraphicalComponent.js +56 -0
- package/src/Core/components/abstract/InlineComponent.js +5 -0
- package/src/Core/components/abstract/InlineRenderInlineChildren.js +63 -0
- package/src/Core/components/abstract/Input.js +192 -0
- package/src/Core/components/abstract/IntervalListComponent.js +218 -0
- package/src/Core/components/abstract/LineListComponent.js +114 -0
- package/src/Core/components/abstract/MathBaseOperator.js +631 -0
- package/src/Core/components/abstract/MathBaseOperatorOneInput.js +112 -0
- package/src/Core/components/abstract/PointListComponent.js +238 -0
- package/src/Core/components/abstract/SectioningComponent.js +1262 -0
- package/src/Core/components/abstract/SingleCharacterInline.js +23 -0
- package/src/Core/components/abstract/TextBaseOperatorOfMath.js +47 -0
- package/src/Core/components/abstract/TextOrInline.js +66 -0
- package/src/Core/components/abstract/VariableName.js +31 -0
- package/src/Core/components/abstract/VariableNameList.js +83 -0
- package/src/Core/components/abstract/VectorListComponent.js +235 -0
- package/src/Core/components/chemistry/Atom.js +910 -0
- package/src/Core/components/chemistry/ElectronConfiguration.js +36 -0
- package/src/Core/components/chemistry/Ion.js +684 -0
- package/src/Core/components/chemistry/IonicCompound.js +189 -0
- package/src/Core/components/chemistry/OrbitalDiagram.js +175 -0
- package/src/Core/components/chemistry/OrbitalDiagramInput.js +753 -0
- package/src/Core/components/chemistry/index.js +6 -0
- package/src/Core/components/commonsugar/breakstrings.js +627 -0
- package/src/Core/components/commonsugar/lists.js +177 -0
- package/src/Core/components/dynamicalSystems/CobwebPolyline.js +913 -0
- package/src/Core/components/dynamicalSystems/EquilibriumCurve.js +95 -0
- package/src/Core/components/dynamicalSystems/EquilibriumLine.js +93 -0
- package/src/Core/components/dynamicalSystems/EquilibriumPoint.js +93 -0
- package/src/Core/components/dynamicalSystems/ODESystem.js +943 -0
- package/src/Core/components/dynamicalSystems/index.js +5 -0
- package/src/Core/components/linearAlgebra/EigenDecomposition.js +294 -0
- package/src/Core/utils/array.js +30 -0
- package/src/Core/utils/booleanLogic.js +965 -0
- package/src/Core/utils/checkEquality.js +818 -0
- package/src/Core/utils/cid.js +29 -0
- package/src/Core/utils/componentInfoObjects.js +100 -0
- package/src/Core/utils/constraints.js +23 -0
- package/src/Core/utils/copy.js +572 -0
- package/src/Core/utils/deepFunctions.js +173 -0
- package/src/Core/utils/descendants.js +252 -0
- package/src/Core/utils/enumeration.js +234 -0
- package/src/Core/utils/feedback.js +84 -0
- package/src/Core/utils/function.js +1343 -0
- package/src/Core/utils/graphical.js +196 -0
- package/src/Core/utils/label.js +396 -0
- package/src/Core/utils/math.js +1056 -0
- package/src/Core/utils/naming.js +45 -0
- package/src/Core/utils/periodicSetEquality.js +403 -0
- package/src/Core/utils/randomNumbers.js +70 -0
- package/src/Core/utils/retrieveMedia.js +98 -0
- package/src/Core/utils/retrieveTextFile.js +140 -0
- package/src/Core/utils/returnAllPossibleVariants.js +73 -0
- package/src/Core/utils/rounding.js +316 -0
- package/src/Core/utils/sequence.js +754 -0
- package/src/Core/utils/serializedStateProcessing.js +4049 -0
- package/src/Core/utils/size.js +22 -0
- package/src/Core/utils/stateVariables.js +138 -0
- package/src/Core/utils/style.js +535 -0
- package/src/Core/utils/subset-of-reals.js +796 -0
- package/src/Core/utils/table.js +41 -0
- package/src/Core/utils/text.js +16 -0
- package/src/Core/utils/triggering.js +167 -0
- package/src/Core/utils/variants.js +477 -0
- package/src/DoenetML.css +308 -0
- package/src/DoenetML.jsx +201 -0
- package/src/Parser/doenet.grammar +90 -0
- package/src/Parser/doenet.js +33 -0
- package/src/Parser/doenet.terms.js +20 -0
- package/src/Parser/parser.js +266 -0
- package/src/Parser/tokens.js +129 -0
- package/src/Tools/CodeMirror.jsx +440 -0
- package/src/Tools/DarkmodeController.jsx +21 -0
- package/src/Tools/Footers/MathInputSelector.jsx +34 -0
- package/src/Tools/Footers/VirtualKeyboard.jsx +751 -0
- package/src/Tools/cypressTest/CypressTest.jsx +341 -0
- package/src/Tools/cypressTest/index.html +102 -0
- package/src/Tools/cypressTest/index.jsx +40 -0
- package/src/Viewer/ActivityViewer.jsx +1461 -0
- package/src/Viewer/PageViewer.jsx +1329 -0
- package/src/Viewer/renderers/alert.jsx +17 -0
- package/src/Viewer/renderers/angle.jsx +209 -0
- package/src/Viewer/renderers/answer.jsx +206 -0
- package/src/Viewer/renderers/asList.jsx +25 -0
- package/src/Viewer/renderers/blockQuote.jsx +41 -0
- package/src/Viewer/renderers/boolean.jsx +17 -0
- package/src/Viewer/renderers/booleanInput.css +105 -0
- package/src/Viewer/renderers/booleanInput.jsx +636 -0
- package/src/Viewer/renderers/button.jsx +369 -0
- package/src/Viewer/renderers/c.jsx +17 -0
- package/src/Viewer/renderers/callAction.jsx +18 -0
- package/src/Viewer/renderers/cell.jsx +59 -0
- package/src/Viewer/renderers/chart.jsx +83 -0
- package/src/Viewer/renderers/choiceInput.css +223 -0
- package/src/Viewer/renderers/choiceInput.jsx +535 -0
- package/src/Viewer/renderers/circle.jsx +990 -0
- package/src/Viewer/renderers/cobwebPolyline.jsx +442 -0
- package/src/Viewer/renderers/codeEditor.jsx +248 -0
- package/src/Viewer/renderers/codeViewer.jsx +105 -0
- package/src/Viewer/renderers/containerBlock.jsx +41 -0
- package/src/Viewer/renderers/containerInline.jsx +17 -0
- package/src/Viewer/renderers/contentBrowser.jsx +159 -0
- package/src/Viewer/renderers/contentPicker.jsx +160 -0
- package/src/Viewer/renderers/curve.jsx +1072 -0
- package/src/Viewer/renderers/ellipsis.jsx +17 -0
- package/src/Viewer/renderers/em.jsx +17 -0
- package/src/Viewer/renderers/embed.jsx +110 -0
- package/src/Viewer/renderers/feedback.jsx +74 -0
- package/src/Viewer/renderers/figure.jsx +131 -0
- package/src/Viewer/renderers/footnote.jsx +52 -0
- package/src/Viewer/renderers/graph.jsx +925 -0
- package/src/Viewer/renderers/hint.jsx +142 -0
- package/src/Viewer/renderers/image.jsx +581 -0
- package/src/Viewer/renderers/jsxgraph-distrib/jsxgraphcore.mjs +2 -0
- package/src/Viewer/renderers/jsxgraph-distrib/jsxgraphcore.mjs.map +1 -0
- package/src/Viewer/renderers/label.jsx +470 -0
- package/src/Viewer/renderers/legend.jsx +306 -0
- package/src/Viewer/renderers/line.jsx +511 -0
- package/src/Viewer/renderers/lineSegment.jsx +754 -0
- package/src/Viewer/renderers/list.jsx +111 -0
- package/src/Viewer/renderers/lq.jsx +12 -0
- package/src/Viewer/renderers/lsq.jsx +12 -0
- package/src/Viewer/renderers/math.jsx +582 -0
- package/src/Viewer/renderers/mathInput.css +10 -0
- package/src/Viewer/renderers/mathInput.jsx +425 -0
- package/src/Viewer/renderers/mathInputog.jsx +534 -0
- package/src/Viewer/renderers/mathList.jsx +39 -0
- package/src/Viewer/renderers/matrixInput.jsx +317 -0
- package/src/Viewer/renderers/mdash.jsx +12 -0
- package/src/Viewer/renderers/nbsp.jsx +12 -0
- package/src/Viewer/renderers/ndash.jsx +12 -0
- package/src/Viewer/renderers/number.jsx +454 -0
- package/src/Viewer/renderers/numberList.jsx +35 -0
- package/src/Viewer/renderers/orbitalDiagram.jsx +247 -0
- package/src/Viewer/renderers/orbitalDiagramInput.jsx +450 -0
- package/src/Viewer/renderers/p.jsx +38 -0
- package/src/Viewer/renderers/paginatorControls.jsx +41 -0
- package/src/Viewer/renderers/pegboard.jsx +239 -0
- package/src/Viewer/renderers/point.jsx +649 -0
- package/src/Viewer/renderers/polygon.jsx +612 -0
- package/src/Viewer/renderers/polyline.jsx +608 -0
- package/src/Viewer/renderers/pre.jsx +34 -0
- package/src/Viewer/renderers/q.jsx +17 -0
- package/src/Viewer/renderers/ray.jsx +410 -0
- package/src/Viewer/renderers/ref.jsx +149 -0
- package/src/Viewer/renderers/regionBetweenCurveXAxis.jsx +182 -0
- package/src/Viewer/renderers/renderDoenetML.jsx +56 -0
- package/src/Viewer/renderers/row.jsx +31 -0
- package/src/Viewer/renderers/rq.jsx +12 -0
- package/src/Viewer/renderers/rsq.jsx +12 -0
- package/src/Viewer/renderers/section.jsx +427 -0
- package/src/Viewer/renderers/sideBySide.jsx +80 -0
- package/src/Viewer/renderers/slider.jsx +800 -0
- package/src/Viewer/renderers/solution.jsx +134 -0
- package/src/Viewer/renderers/spreadsheet.jsx +83 -0
- package/src/Viewer/renderers/sq.jsx +17 -0
- package/src/Viewer/renderers/styles/global.css +14 -0
- package/src/Viewer/renderers/subsetOfRealsInput.jsx +392 -0
- package/src/Viewer/renderers/summaryStatistics.jsx +83 -0
- package/src/Viewer/renderers/table.jsx +78 -0
- package/src/Viewer/renderers/tabular.jsx +58 -0
- package/src/Viewer/renderers/tag.jsx +26 -0
- package/src/Viewer/renderers/text.jsx +439 -0
- package/src/Viewer/renderers/textInput.jsx +774 -0
- package/src/Viewer/renderers/textList.jsx +30 -0
- package/src/Viewer/renderers/triggerSet.jsx +52 -0
- package/src/Viewer/renderers/updateValue.jsx +30 -0
- package/src/Viewer/renderers/utils/css.js +13 -0
- package/src/Viewer/renderers/utils/graph.js +159 -0
- package/src/Viewer/renderers/utils/offGraphIndicators.js +91 -0
- package/src/Viewer/renderers/vector.jsx +678 -0
- package/src/Viewer/renderers/video.jsx +494 -0
- package/src/Viewer/useDoenetRenderer.jsx +128 -0
- package/src/main.jsx +16 -0
- package/src/media/fonts/files/open-sans-v18-latin-700.woff +0 -0
- package/src/media/fonts/files/open-sans-v18-latin-700.woff2 +0 -0
- package/src/media/fonts/files/open-sans-v18-latin-700italic.woff +0 -0
- package/src/media/fonts/files/open-sans-v18-latin-700italic.woff2 +0 -0
- package/src/media/fonts/files/open-sans-v18-latin-italic.woff +0 -0
- package/src/media/fonts/files/open-sans-v18-latin-italic.woff2 +0 -0
- package/src/media/fonts/files/open-sans-v18-latin-light-italic.woff +0 -0
- package/src/media/fonts/files/open-sans-v18-latin-light-italic.woff2 +0 -0
- package/src/media/fonts/files/open-sans-v18-latin-light.woff +0 -0
- package/src/media/fonts/files/open-sans-v18-latin-light.woff2 +0 -0
- package/src/media/fonts/files/open-sans-v18-latin-regular.woff +0 -0
- package/src/media/fonts/files/open-sans-v18-latin-regular.woff2 +0 -0
- package/src/test/testCode.doenet +26 -0
- package/src/test/testViewer.jsx +158 -0
- package/src/uiComponents/ActionButton.jsx +157 -0
- package/src/uiComponents/ActionButtonGroup.jsx +93 -0
- package/src/uiComponents/Button.jsx +160 -0
- package/src/uiComponents/ButtonGroup.jsx +56 -0
- package/src/uiComponents/ToggleButton.jsx +194 -0
- package/src/uiComponents/ToggleButtonGroup.jsx +77 -0
- package/src/utils/activityUtils.js +713 -0
- package/src/utils/array.js +17 -0
- package/src/utils/cid.js +34 -0
- package/src/utils/componentInfoObjects.js +89 -0
- package/src/utils/deepFunctions.js +165 -0
- package/src/utils/enumeration.js +226 -0
- package/src/utils/math.js +624 -0
- package/src/utils/naming.js +44 -0
- package/src/utils/retrieveTextFile.js +156 -0
- package/src/utils/returnAllPossibleVariants.js +81 -0
- package/src/utils/sequence.js +715 -0
- package/src/utils/serialize.js +29 -0
- package/src/utils/serializedStateProcessing.js +2587 -0
- package/src/utils/subset-of-reals.js +783 -0
- package/src/utils/url.js +19 -0
- package/vite.config.js +14 -0
|
@@ -0,0 +1,1242 @@
|
|
|
1
|
+
import Sequence from "./Sequence";
|
|
2
|
+
import { enumerateSelectionCombinations } from "../utils/enumeration";
|
|
3
|
+
import { processAssignNames } from "../utils/serializedStateProcessing";
|
|
4
|
+
import { getFromText } from "../utils/math";
|
|
5
|
+
import {
|
|
6
|
+
calculateSequenceParameters,
|
|
7
|
+
lettersToNumber,
|
|
8
|
+
returnSequenceValueForIndex,
|
|
9
|
+
returnSequenceValues,
|
|
10
|
+
} from "../utils/sequence";
|
|
11
|
+
import { convertAttributesForComponentType } from "../utils/copy";
|
|
12
|
+
import { returnRoundingAttributes } from "../utils/rounding";
|
|
13
|
+
|
|
14
|
+
export default class SelectFromSequence extends Sequence {
|
|
15
|
+
static componentType = "selectFromSequence";
|
|
16
|
+
|
|
17
|
+
static assignNamesToReplacements = true;
|
|
18
|
+
|
|
19
|
+
static createsVariants = true;
|
|
20
|
+
|
|
21
|
+
static createAttributesObject() {
|
|
22
|
+
let attributes = super.createAttributesObject();
|
|
23
|
+
attributes.assignNamesSkip = {
|
|
24
|
+
createPrimitiveOfType: "number",
|
|
25
|
+
};
|
|
26
|
+
attributes.numToSelect = {
|
|
27
|
+
createComponentOfType: "integer",
|
|
28
|
+
createStateVariable: "numToSelect",
|
|
29
|
+
defaultValue: 1,
|
|
30
|
+
public: true,
|
|
31
|
+
};
|
|
32
|
+
attributes.withReplacement = {
|
|
33
|
+
createComponentOfType: "boolean",
|
|
34
|
+
createStateVariable: "withReplacement",
|
|
35
|
+
defaultValue: false,
|
|
36
|
+
public: true,
|
|
37
|
+
};
|
|
38
|
+
attributes.sortResults = {
|
|
39
|
+
createComponentOfType: "boolean",
|
|
40
|
+
createStateVariable: "sortResults",
|
|
41
|
+
defaultValue: false,
|
|
42
|
+
public: true,
|
|
43
|
+
};
|
|
44
|
+
attributes.excludeCombinations = {
|
|
45
|
+
createComponentOfType: "_componentListOfListsWithSelectableType",
|
|
46
|
+
};
|
|
47
|
+
return attributes;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
static returnStateVariableDefinitions() {
|
|
51
|
+
let stateVariableDefinitions = super.returnStateVariableDefinitions();
|
|
52
|
+
|
|
53
|
+
stateVariableDefinitions.excludedCombinations = {
|
|
54
|
+
returnDependencies: () => ({
|
|
55
|
+
excludeCombinations: {
|
|
56
|
+
dependencyType: "attributeComponent",
|
|
57
|
+
attributeName: "excludeCombinations",
|
|
58
|
+
variableNames: ["lists"],
|
|
59
|
+
},
|
|
60
|
+
type: {
|
|
61
|
+
dependencyType: "stateVariable",
|
|
62
|
+
variableName: "type",
|
|
63
|
+
},
|
|
64
|
+
numToSelect: {
|
|
65
|
+
dependencyType: "stateVariable",
|
|
66
|
+
variableName: "numToSelect",
|
|
67
|
+
},
|
|
68
|
+
}),
|
|
69
|
+
definition: function ({ dependencyValues }) {
|
|
70
|
+
if (dependencyValues.excludeCombinations !== null) {
|
|
71
|
+
let excludedCombinations =
|
|
72
|
+
dependencyValues.excludeCombinations.stateValues.lists
|
|
73
|
+
.map((x) => x.slice(0, dependencyValues.numToSelect))
|
|
74
|
+
.filter((x) => x.length === dependencyValues.numToSelect);
|
|
75
|
+
|
|
76
|
+
if (dependencyValues.type === "number") {
|
|
77
|
+
while (true) {
|
|
78
|
+
let result = mergeContainingCombinations(excludedCombinations);
|
|
79
|
+
if (result.merged) {
|
|
80
|
+
excludedCombinations = result.combinations;
|
|
81
|
+
} else {
|
|
82
|
+
break;
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
return {
|
|
88
|
+
setValue: { excludedCombinations },
|
|
89
|
+
};
|
|
90
|
+
} else {
|
|
91
|
+
return { setValue: { excludedCombinations: [] } };
|
|
92
|
+
}
|
|
93
|
+
},
|
|
94
|
+
};
|
|
95
|
+
|
|
96
|
+
stateVariableDefinitions.variants = {
|
|
97
|
+
returnDependencies: () => ({
|
|
98
|
+
variants: {
|
|
99
|
+
dependencyType: "variants",
|
|
100
|
+
},
|
|
101
|
+
}),
|
|
102
|
+
definition: function ({ dependencyValues }) {
|
|
103
|
+
return { setValue: { variants: dependencyValues.variants } };
|
|
104
|
+
},
|
|
105
|
+
};
|
|
106
|
+
|
|
107
|
+
stateVariableDefinitions.selectedValues = {
|
|
108
|
+
immutable: true,
|
|
109
|
+
hasEssential: true,
|
|
110
|
+
shadowVariable: true,
|
|
111
|
+
additionalStateVariablesDefined: [
|
|
112
|
+
{
|
|
113
|
+
variableName: "selectedIndices",
|
|
114
|
+
hasEssential: true,
|
|
115
|
+
shadowVariable: true,
|
|
116
|
+
immutable: true,
|
|
117
|
+
},
|
|
118
|
+
],
|
|
119
|
+
returnDependencies: ({ sharedParameters }) => ({
|
|
120
|
+
numToSelect: {
|
|
121
|
+
dependencyType: "stateVariable",
|
|
122
|
+
variableName: "numToSelect",
|
|
123
|
+
},
|
|
124
|
+
withReplacement: {
|
|
125
|
+
dependencyType: "stateVariable",
|
|
126
|
+
variableName: "withReplacement",
|
|
127
|
+
},
|
|
128
|
+
length: {
|
|
129
|
+
dependencyType: "stateVariable",
|
|
130
|
+
variableName: "length",
|
|
131
|
+
},
|
|
132
|
+
from: {
|
|
133
|
+
dependencyType: "stateVariable",
|
|
134
|
+
variableName: "from",
|
|
135
|
+
},
|
|
136
|
+
step: {
|
|
137
|
+
dependencyType: "stateVariable",
|
|
138
|
+
variableName: "step",
|
|
139
|
+
},
|
|
140
|
+
exclude: {
|
|
141
|
+
dependencyType: "stateVariable",
|
|
142
|
+
variableName: "exclude",
|
|
143
|
+
},
|
|
144
|
+
excludedCombinations: {
|
|
145
|
+
dependencyType: "stateVariable",
|
|
146
|
+
variableName: "excludedCombinations",
|
|
147
|
+
},
|
|
148
|
+
type: {
|
|
149
|
+
dependencyType: "stateVariable",
|
|
150
|
+
variableName: "type",
|
|
151
|
+
},
|
|
152
|
+
lowercase: {
|
|
153
|
+
dependencyType: "stateVariable",
|
|
154
|
+
variableName: "lowercase",
|
|
155
|
+
},
|
|
156
|
+
sortResults: {
|
|
157
|
+
dependencyType: "stateVariable",
|
|
158
|
+
variableName: "sortResults",
|
|
159
|
+
},
|
|
160
|
+
variants: {
|
|
161
|
+
dependencyType: "stateVariable",
|
|
162
|
+
variableName: "variants",
|
|
163
|
+
},
|
|
164
|
+
variantRng: {
|
|
165
|
+
dependencyType: "value",
|
|
166
|
+
value: sharedParameters.variantRng,
|
|
167
|
+
doNotProxy: true,
|
|
168
|
+
},
|
|
169
|
+
}),
|
|
170
|
+
definition: makeSelection,
|
|
171
|
+
};
|
|
172
|
+
|
|
173
|
+
stateVariableDefinitions.isVariantComponent = {
|
|
174
|
+
returnDependencies: () => ({}),
|
|
175
|
+
definition: () => ({ setValue: { isVariantComponent: true } }),
|
|
176
|
+
};
|
|
177
|
+
|
|
178
|
+
stateVariableDefinitions.generatedVariantInfo = {
|
|
179
|
+
returnDependencies: () => ({
|
|
180
|
+
selectedIndices: {
|
|
181
|
+
dependencyType: "stateVariable",
|
|
182
|
+
variableName: "selectedIndices",
|
|
183
|
+
},
|
|
184
|
+
}),
|
|
185
|
+
definition({ dependencyValues, componentName }) {
|
|
186
|
+
let generatedVariantInfo = {
|
|
187
|
+
indices: dependencyValues.selectedIndices,
|
|
188
|
+
meta: { createdBy: componentName },
|
|
189
|
+
};
|
|
190
|
+
|
|
191
|
+
return { setValue: { generatedVariantInfo } };
|
|
192
|
+
},
|
|
193
|
+
};
|
|
194
|
+
|
|
195
|
+
let originalReturnDependencies =
|
|
196
|
+
stateVariableDefinitions.readyToExpandWhenResolved.returnDependencies;
|
|
197
|
+
stateVariableDefinitions.readyToExpandWhenResolved.returnDependencies =
|
|
198
|
+
function () {
|
|
199
|
+
let deps = originalReturnDependencies();
|
|
200
|
+
|
|
201
|
+
deps.selectedValues = {
|
|
202
|
+
dependencyType: "stateVariable",
|
|
203
|
+
variableName: "selectedValues",
|
|
204
|
+
};
|
|
205
|
+
|
|
206
|
+
return deps;
|
|
207
|
+
};
|
|
208
|
+
|
|
209
|
+
return stateVariableDefinitions;
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
static async createSerializedReplacements({
|
|
213
|
+
component,
|
|
214
|
+
componentInfoObjects,
|
|
215
|
+
flags,
|
|
216
|
+
}) {
|
|
217
|
+
let componentType = await component.stateValues.type;
|
|
218
|
+
if (componentType === "letters") {
|
|
219
|
+
componentType = "text";
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
let newNamespace = component.attributes.newNamespace?.primitive;
|
|
223
|
+
|
|
224
|
+
let attributesToConvert = {};
|
|
225
|
+
for (let attr of ["fixed", ...Object.keys(returnRoundingAttributes())]) {
|
|
226
|
+
if (attr in component.attributes) {
|
|
227
|
+
attributesToConvert[attr] = component.attributes[attr];
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
// allow one to override the fixed (default true) attribute
|
|
232
|
+
// as well as rounding settings
|
|
233
|
+
// by specifying it on the sequence
|
|
234
|
+
let attributesFromComposite = {};
|
|
235
|
+
|
|
236
|
+
if (Object.keys(attributesToConvert).length > 0) {
|
|
237
|
+
attributesFromComposite = convertAttributesForComponentType({
|
|
238
|
+
attributes: attributesToConvert,
|
|
239
|
+
componentType,
|
|
240
|
+
componentInfoObjects,
|
|
241
|
+
compositeCreatesNewNamespace: newNamespace,
|
|
242
|
+
flags,
|
|
243
|
+
});
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
let replacements = [];
|
|
247
|
+
|
|
248
|
+
for (let value of await component.stateValues.selectedValues) {
|
|
249
|
+
replacements.push({
|
|
250
|
+
componentType,
|
|
251
|
+
attributes: attributesFromComposite,
|
|
252
|
+
state: { value, fixed: true },
|
|
253
|
+
});
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
let processResult = processAssignNames({
|
|
257
|
+
assignNames: component.doenetAttributes.assignNames,
|
|
258
|
+
serializedComponents: replacements,
|
|
259
|
+
parentName: component.componentName,
|
|
260
|
+
parentCreatesNewNamespace: newNamespace,
|
|
261
|
+
componentInfoObjects,
|
|
262
|
+
});
|
|
263
|
+
|
|
264
|
+
return { replacements: processResult.serializedComponents };
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
static calculateReplacementChanges() {
|
|
268
|
+
return [];
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
static determineNumberOfUniqueVariants({ serializedComponent }) {
|
|
272
|
+
let numToSelect = 1,
|
|
273
|
+
withReplacement = false;
|
|
274
|
+
|
|
275
|
+
let sequenceType = serializedComponent.attributes.type.primitive;
|
|
276
|
+
|
|
277
|
+
let numToSelectComponent =
|
|
278
|
+
serializedComponent.attributes.numToSelect?.component;
|
|
279
|
+
if (numToSelectComponent) {
|
|
280
|
+
// only implemented if have an integer with a single string child
|
|
281
|
+
if (
|
|
282
|
+
numToSelectComponent.componentType === "integer" &&
|
|
283
|
+
numToSelectComponent.children?.length === 1 &&
|
|
284
|
+
typeof numToSelectComponent.children[0] === "string"
|
|
285
|
+
) {
|
|
286
|
+
numToSelect = Number(numToSelectComponent.children[0]);
|
|
287
|
+
|
|
288
|
+
if (!(Number.isInteger(numToSelect) && numToSelect >= 0)) {
|
|
289
|
+
console.log(
|
|
290
|
+
`cannot determine unique variants of selectFromSequence as numToSelect isn't a non-negative integer.`,
|
|
291
|
+
);
|
|
292
|
+
return { success: false };
|
|
293
|
+
}
|
|
294
|
+
} else {
|
|
295
|
+
console.log(
|
|
296
|
+
`cannot determine unique variants of selectFromSequence as numToSelect isn't constant number.`,
|
|
297
|
+
);
|
|
298
|
+
return { success: false };
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
let withReplacementComponent =
|
|
303
|
+
serializedComponent.attributes.withReplacement?.component;
|
|
304
|
+
if (withReplacementComponent) {
|
|
305
|
+
// only implemented if have an boolean with a boolean value or a single string child
|
|
306
|
+
if (withReplacementComponent.componentType === "boolean") {
|
|
307
|
+
if (
|
|
308
|
+
withReplacementComponent.children?.length === 1 &&
|
|
309
|
+
typeof withReplacementComponent.children[0] === "string"
|
|
310
|
+
) {
|
|
311
|
+
withReplacement =
|
|
312
|
+
withReplacementComponent.children[0].toLowerCase() === "true";
|
|
313
|
+
} else if (
|
|
314
|
+
(withReplacementComponent.children === undefined ||
|
|
315
|
+
withReplacementComponent.children.length === 0) &&
|
|
316
|
+
typeof withReplacementComponent.state?.value === "boolean"
|
|
317
|
+
) {
|
|
318
|
+
withReplacement = withReplacementComponent.state.value;
|
|
319
|
+
} else {
|
|
320
|
+
console.log(
|
|
321
|
+
`cannot determine unique variants of selectFromSequence as withReplacement isn't constant boolean.`,
|
|
322
|
+
);
|
|
323
|
+
return { success: false };
|
|
324
|
+
}
|
|
325
|
+
} else {
|
|
326
|
+
console.log(
|
|
327
|
+
`cannot determine unique variants of selectFromSequence as withReplacement isn't constant boolean.`,
|
|
328
|
+
);
|
|
329
|
+
return { success: false };
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
let sequencePars = {
|
|
334
|
+
from: null,
|
|
335
|
+
to: null,
|
|
336
|
+
step: null,
|
|
337
|
+
length: null,
|
|
338
|
+
};
|
|
339
|
+
|
|
340
|
+
let fromComponent = serializedComponent.attributes.from?.component;
|
|
341
|
+
if (fromComponent) {
|
|
342
|
+
// from itself is a component with selectable type
|
|
343
|
+
let fromComponent2 = fromComponent.children[0];
|
|
344
|
+
// only implemented if have a single string child
|
|
345
|
+
if (
|
|
346
|
+
fromComponent2.children?.length === 1 &&
|
|
347
|
+
typeof fromComponent2.children[0] === "string"
|
|
348
|
+
) {
|
|
349
|
+
let from;
|
|
350
|
+
|
|
351
|
+
if (sequenceType === "number") {
|
|
352
|
+
from = Number(fromComponent2.children[0]);
|
|
353
|
+
if (!Number.isFinite(from)) {
|
|
354
|
+
console.log(
|
|
355
|
+
`cannot determine unique variants of selectFromSequence of number type as from isn't a number.`,
|
|
356
|
+
);
|
|
357
|
+
return { success: false };
|
|
358
|
+
}
|
|
359
|
+
} else if (sequenceType === "letters") {
|
|
360
|
+
from = lettersToNumber(fromComponent2.children[0]);
|
|
361
|
+
if (!Number.isFinite(from)) {
|
|
362
|
+
console.log(
|
|
363
|
+
`cannot determine unique variants of selectFromSequence of letters type as from isn't a combination of letters.`,
|
|
364
|
+
);
|
|
365
|
+
return { success: false };
|
|
366
|
+
}
|
|
367
|
+
} else {
|
|
368
|
+
let fromText = getFromText({
|
|
369
|
+
functionSymbols: ["f", "g"],
|
|
370
|
+
});
|
|
371
|
+
try {
|
|
372
|
+
from = fromText(fromComponent2.children[0]);
|
|
373
|
+
} catch (e) {
|
|
374
|
+
console.log(
|
|
375
|
+
`cannot determine unique variants of selectFromSequence of math type as from isn't a valid math expression.`,
|
|
376
|
+
);
|
|
377
|
+
return { success: false };
|
|
378
|
+
}
|
|
379
|
+
}
|
|
380
|
+
sequencePars.from = from;
|
|
381
|
+
} else {
|
|
382
|
+
console.log(
|
|
383
|
+
`cannot determine unique variants of selectFromSequence as from isn't a constant.`,
|
|
384
|
+
);
|
|
385
|
+
return { success: false };
|
|
386
|
+
}
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
let toComponent = serializedComponent.attributes.to?.component;
|
|
390
|
+
if (toComponent) {
|
|
391
|
+
// to itself is a component with selectable type
|
|
392
|
+
let toComponent2 = toComponent.children[0];
|
|
393
|
+
// only implemented if have a single string child
|
|
394
|
+
if (
|
|
395
|
+
toComponent2.children?.length === 1 &&
|
|
396
|
+
typeof toComponent2.children[0] === "string"
|
|
397
|
+
) {
|
|
398
|
+
let to;
|
|
399
|
+
|
|
400
|
+
if (sequenceType === "number") {
|
|
401
|
+
to = Number(toComponent2.children[0]);
|
|
402
|
+
if (!Number.isFinite(to)) {
|
|
403
|
+
console.log(
|
|
404
|
+
`cannot determine unique variants of selectFromSequence of number type as to isn't a number.`,
|
|
405
|
+
);
|
|
406
|
+
return { success: false };
|
|
407
|
+
}
|
|
408
|
+
} else if (sequenceType === "letters") {
|
|
409
|
+
to = lettersToNumber(toComponent2.children[0]);
|
|
410
|
+
if (!Number.isFinite(to)) {
|
|
411
|
+
console.log(
|
|
412
|
+
`cannot determine unique variants of selectFromSequence of letters type as to isn't a combination of letters.`,
|
|
413
|
+
);
|
|
414
|
+
return { success: false };
|
|
415
|
+
}
|
|
416
|
+
} else {
|
|
417
|
+
let fromText = getFromText({
|
|
418
|
+
functionSymbols: ["f", "g"],
|
|
419
|
+
});
|
|
420
|
+
try {
|
|
421
|
+
to = fromText(toComponent2.children[0]);
|
|
422
|
+
} catch (e) {
|
|
423
|
+
console.log(
|
|
424
|
+
`cannot determine unique variants of selectFromSequence of math type as to isn't a valid math expression.`,
|
|
425
|
+
);
|
|
426
|
+
return { success: false };
|
|
427
|
+
}
|
|
428
|
+
}
|
|
429
|
+
sequencePars.to = to;
|
|
430
|
+
} else {
|
|
431
|
+
console.log(
|
|
432
|
+
`cannot determine unique variants of selectFromSequence as to isn't a constant.`,
|
|
433
|
+
);
|
|
434
|
+
return { success: false };
|
|
435
|
+
}
|
|
436
|
+
}
|
|
437
|
+
|
|
438
|
+
let stepComponent = serializedComponent.attributes.step?.component;
|
|
439
|
+
if (stepComponent) {
|
|
440
|
+
// only implemented if have a single string child
|
|
441
|
+
if (
|
|
442
|
+
stepComponent.children?.length === 1 &&
|
|
443
|
+
typeof stepComponent.children[0] === "string"
|
|
444
|
+
) {
|
|
445
|
+
let step;
|
|
446
|
+
|
|
447
|
+
if (sequenceType === "number") {
|
|
448
|
+
step = Number(stepComponent.children[0]);
|
|
449
|
+
if (!Number.isFinite(step)) {
|
|
450
|
+
console.log(
|
|
451
|
+
`cannot determine unique variants of selectFromSequence of number type as step isn't a number.`,
|
|
452
|
+
);
|
|
453
|
+
return { success: false };
|
|
454
|
+
}
|
|
455
|
+
} else if (sequenceType === "letters") {
|
|
456
|
+
step = Number(stepComponent.children[0]);
|
|
457
|
+
if (!Number.isInteger(step)) {
|
|
458
|
+
console.log(
|
|
459
|
+
`cannot determine unique variants of selectFromSequence of letters type as step isn't an integer.`,
|
|
460
|
+
);
|
|
461
|
+
return { success: false };
|
|
462
|
+
}
|
|
463
|
+
} else {
|
|
464
|
+
let fromText = getFromText({
|
|
465
|
+
functionSymbols: ["f", "g"],
|
|
466
|
+
});
|
|
467
|
+
try {
|
|
468
|
+
step = fromText(stepComponent.children[0]);
|
|
469
|
+
} catch (e) {
|
|
470
|
+
console.log(
|
|
471
|
+
`cannot determine unique variants of selectFromSequence of math type as step isn't a valid math expression.`,
|
|
472
|
+
);
|
|
473
|
+
return { success: false };
|
|
474
|
+
}
|
|
475
|
+
}
|
|
476
|
+
sequencePars.step = step;
|
|
477
|
+
} else {
|
|
478
|
+
console.log(
|
|
479
|
+
`cannot determine unique variants of selectFromSequence as step isn't a constant.`,
|
|
480
|
+
);
|
|
481
|
+
return { success: false };
|
|
482
|
+
}
|
|
483
|
+
}
|
|
484
|
+
|
|
485
|
+
let lengthComponent = serializedComponent.attributes.length?.component;
|
|
486
|
+
if (lengthComponent) {
|
|
487
|
+
// only implemented if have a single string child
|
|
488
|
+
if (
|
|
489
|
+
lengthComponent.children?.length === 1 &&
|
|
490
|
+
typeof lengthComponent.children[0] === "string"
|
|
491
|
+
) {
|
|
492
|
+
let length = Number(lengthComponent.children[0]);
|
|
493
|
+
if (!Number.isInteger(length)) {
|
|
494
|
+
console.log(
|
|
495
|
+
`cannot determine unique variants of selectFromSequence as length isn't an integer.`,
|
|
496
|
+
);
|
|
497
|
+
return { success: false };
|
|
498
|
+
}
|
|
499
|
+
sequencePars.length = length;
|
|
500
|
+
} else {
|
|
501
|
+
console.log(
|
|
502
|
+
`cannot determine unique variants of selectFromSequence as length isn't a constant.`,
|
|
503
|
+
);
|
|
504
|
+
return { success: false };
|
|
505
|
+
}
|
|
506
|
+
}
|
|
507
|
+
|
|
508
|
+
if (serializedComponent.attributes.excludeCombinations) {
|
|
509
|
+
console.log(
|
|
510
|
+
"have not implemented unique variants of a selectFromSequence with excludeCombinations",
|
|
511
|
+
);
|
|
512
|
+
return { success: false };
|
|
513
|
+
}
|
|
514
|
+
|
|
515
|
+
let excludes = [];
|
|
516
|
+
|
|
517
|
+
let excludeComponent = serializedComponent.attributes.exclude?.component;
|
|
518
|
+
if (excludeComponent) {
|
|
519
|
+
if (sequenceType === "math") {
|
|
520
|
+
console.log(
|
|
521
|
+
"have not implemented unique variants of a selectFromSequence of type math with exclude",
|
|
522
|
+
);
|
|
523
|
+
return { success: false };
|
|
524
|
+
}
|
|
525
|
+
if (
|
|
526
|
+
!excludeComponent.children.every(
|
|
527
|
+
(x) => x.children?.length === 1 && typeof x.children[0] === "string",
|
|
528
|
+
)
|
|
529
|
+
) {
|
|
530
|
+
console.log(
|
|
531
|
+
"have not implemented unique variants of a selectFromSequence with non-constant exclude",
|
|
532
|
+
);
|
|
533
|
+
return { success: false };
|
|
534
|
+
}
|
|
535
|
+
if (sequenceType === "letters") {
|
|
536
|
+
excludes = excludeComponent.children.map((x) =>
|
|
537
|
+
lettersToNumber(x.children[0]),
|
|
538
|
+
);
|
|
539
|
+
} else {
|
|
540
|
+
excludes = excludeComponent.children.map((x) => Number(x.children[0]));
|
|
541
|
+
}
|
|
542
|
+
|
|
543
|
+
if (!excludes.every(Number.isFinite)) {
|
|
544
|
+
console.log(
|
|
545
|
+
"have not implemented unique variants of a selectFromSequence with non-constant exclude",
|
|
546
|
+
);
|
|
547
|
+
return { success: false };
|
|
548
|
+
}
|
|
549
|
+
}
|
|
550
|
+
|
|
551
|
+
sequencePars = calculateSequenceParameters(sequencePars);
|
|
552
|
+
|
|
553
|
+
let nOptions = sequencePars.length;
|
|
554
|
+
let excludeIndices = [];
|
|
555
|
+
if (excludes.length > 0) {
|
|
556
|
+
if (sequenceType !== "math") {
|
|
557
|
+
excludes.sort((a, b) => a - b);
|
|
558
|
+
excludes = excludes.filter((x, ind, a) => x != a[ind - 1]); // remove duplicates
|
|
559
|
+
for (let item of excludes) {
|
|
560
|
+
if (item < sequencePars.from) {
|
|
561
|
+
continue;
|
|
562
|
+
}
|
|
563
|
+
let ind = (item - sequencePars.from) / sequencePars.step;
|
|
564
|
+
if (ind > sequencePars.length - 1 + 1e-10) {
|
|
565
|
+
break;
|
|
566
|
+
}
|
|
567
|
+
if (Math.abs(ind - Math.round(ind)) < 1e-10) {
|
|
568
|
+
nOptions--;
|
|
569
|
+
excludeIndices.push(ind);
|
|
570
|
+
}
|
|
571
|
+
}
|
|
572
|
+
}
|
|
573
|
+
}
|
|
574
|
+
|
|
575
|
+
if (nOptions <= 0) {
|
|
576
|
+
return { success: false };
|
|
577
|
+
}
|
|
578
|
+
|
|
579
|
+
let uniqueVariantData = {
|
|
580
|
+
excludeIndices,
|
|
581
|
+
nOptions,
|
|
582
|
+
numToSelect,
|
|
583
|
+
withReplacement,
|
|
584
|
+
};
|
|
585
|
+
|
|
586
|
+
serializedComponent.variants.uniqueVariantData = uniqueVariantData;
|
|
587
|
+
|
|
588
|
+
let numberOfVariants;
|
|
589
|
+
|
|
590
|
+
if (withReplacement || numToSelect === 1) {
|
|
591
|
+
numberOfVariants = Math.pow(nOptions, numToSelect);
|
|
592
|
+
} else {
|
|
593
|
+
numberOfVariants = nOptions;
|
|
594
|
+
for (let n = nOptions - 1; n > nOptions - numToSelect; n--) {
|
|
595
|
+
numberOfVariants *= n;
|
|
596
|
+
}
|
|
597
|
+
}
|
|
598
|
+
|
|
599
|
+
serializedComponent.variants.numberOfVariants = numberOfVariants;
|
|
600
|
+
|
|
601
|
+
return {
|
|
602
|
+
success: true,
|
|
603
|
+
numberOfVariants: numberOfVariants,
|
|
604
|
+
};
|
|
605
|
+
}
|
|
606
|
+
|
|
607
|
+
static getUniqueVariant({ serializedComponent, variantIndex }) {
|
|
608
|
+
let numberOfVariants = serializedComponent.variants?.numberOfVariants;
|
|
609
|
+
if (numberOfVariants === undefined) {
|
|
610
|
+
return { success: false };
|
|
611
|
+
}
|
|
612
|
+
|
|
613
|
+
if (
|
|
614
|
+
!Number.isInteger(variantIndex) ||
|
|
615
|
+
variantIndex < 1 ||
|
|
616
|
+
variantIndex > numberOfVariants
|
|
617
|
+
) {
|
|
618
|
+
return { success: false };
|
|
619
|
+
}
|
|
620
|
+
|
|
621
|
+
let uniqueVariantData = serializedComponent.variants.uniqueVariantData;
|
|
622
|
+
let excludeIndices = uniqueVariantData.excludeIndices;
|
|
623
|
+
let nOptions = uniqueVariantData.nOptions;
|
|
624
|
+
let numToSelect = uniqueVariantData.numToSelect;
|
|
625
|
+
let withReplacement = uniqueVariantData.withReplacement;
|
|
626
|
+
|
|
627
|
+
let getSingleIndex = function (num) {
|
|
628
|
+
let ind = num;
|
|
629
|
+
for (let excludeInd of excludeIndices) {
|
|
630
|
+
if (ind >= excludeInd) {
|
|
631
|
+
ind++;
|
|
632
|
+
}
|
|
633
|
+
}
|
|
634
|
+
|
|
635
|
+
return ind;
|
|
636
|
+
};
|
|
637
|
+
|
|
638
|
+
if (numToSelect === 1) {
|
|
639
|
+
return {
|
|
640
|
+
success: true,
|
|
641
|
+
desiredVariant: { indices: [getSingleIndex(variantIndex - 1) + 1] },
|
|
642
|
+
};
|
|
643
|
+
}
|
|
644
|
+
|
|
645
|
+
let numbers = enumerateSelectionCombinations({
|
|
646
|
+
numberOfIndices: numToSelect,
|
|
647
|
+
numberOfOptions: nOptions,
|
|
648
|
+
maxNumber: variantIndex,
|
|
649
|
+
withReplacement,
|
|
650
|
+
})[variantIndex - 1];
|
|
651
|
+
let indices = numbers.map(getSingleIndex).map((x) => x + 1);
|
|
652
|
+
return { success: true, desiredVariant: { indices: indices } };
|
|
653
|
+
}
|
|
654
|
+
}
|
|
655
|
+
|
|
656
|
+
function makeSelection({ dependencyValues }) {
|
|
657
|
+
// console.log(`make selection`)
|
|
658
|
+
// console.log(dependencyValues)
|
|
659
|
+
|
|
660
|
+
if (dependencyValues.numToSelect < 1) {
|
|
661
|
+
return {
|
|
662
|
+
setEssentialValue: {
|
|
663
|
+
selectedValues: [],
|
|
664
|
+
selectedIndices: [],
|
|
665
|
+
},
|
|
666
|
+
setValue: {
|
|
667
|
+
selectedValues: [],
|
|
668
|
+
selectedIndices: [],
|
|
669
|
+
},
|
|
670
|
+
};
|
|
671
|
+
}
|
|
672
|
+
|
|
673
|
+
let numberUniqueRequired = 1;
|
|
674
|
+
if (!dependencyValues.withReplacement) {
|
|
675
|
+
numberUniqueRequired = dependencyValues.numToSelect;
|
|
676
|
+
}
|
|
677
|
+
|
|
678
|
+
if (numberUniqueRequired > dependencyValues.length) {
|
|
679
|
+
throw Error(
|
|
680
|
+
"Cannot select " +
|
|
681
|
+
numberUniqueRequired +
|
|
682
|
+
" values from a sequence of length " +
|
|
683
|
+
dependencyValues.length,
|
|
684
|
+
);
|
|
685
|
+
}
|
|
686
|
+
|
|
687
|
+
// if desiredIndices is specfied, use those
|
|
688
|
+
if (
|
|
689
|
+
dependencyValues.variants &&
|
|
690
|
+
dependencyValues.variants.desiredVariant !== undefined
|
|
691
|
+
) {
|
|
692
|
+
let desiredIndices = dependencyValues.variants.desiredVariant.indices;
|
|
693
|
+
if (desiredIndices !== undefined) {
|
|
694
|
+
if (desiredIndices.length !== dependencyValues.numToSelect) {
|
|
695
|
+
throw Error(
|
|
696
|
+
"Number of indices specified for select must match number to select",
|
|
697
|
+
);
|
|
698
|
+
}
|
|
699
|
+
desiredIndices = desiredIndices.map(Number);
|
|
700
|
+
if (!desiredIndices.every(Number.isInteger)) {
|
|
701
|
+
throw Error("All indices specified for select must be integers");
|
|
702
|
+
}
|
|
703
|
+
let n = dependencyValues.length;
|
|
704
|
+
desiredIndices = desiredIndices.map((x) => ((((x - 1) % n) + n) % n) + 1);
|
|
705
|
+
|
|
706
|
+
let selectedValues = [];
|
|
707
|
+
for (let indexFrom1 of desiredIndices) {
|
|
708
|
+
let componentValue = returnSequenceValueForIndex({
|
|
709
|
+
index: indexFrom1 - 1,
|
|
710
|
+
from: dependencyValues.from,
|
|
711
|
+
step: dependencyValues.step,
|
|
712
|
+
length: dependencyValues.length,
|
|
713
|
+
exclude: dependencyValues.exclude,
|
|
714
|
+
type: dependencyValues.type,
|
|
715
|
+
lowercase: dependencyValues.lowercase,
|
|
716
|
+
});
|
|
717
|
+
|
|
718
|
+
if (componentValue === null) {
|
|
719
|
+
throw Error(
|
|
720
|
+
"Specified index of selectfromsequence that was excluded",
|
|
721
|
+
);
|
|
722
|
+
}
|
|
723
|
+
|
|
724
|
+
selectedValues.push(componentValue);
|
|
725
|
+
}
|
|
726
|
+
|
|
727
|
+
if (
|
|
728
|
+
checkForExcludedCombination({
|
|
729
|
+
type: dependencyValues.type,
|
|
730
|
+
excludedCombinations: dependencyValues.excludedCombinations,
|
|
731
|
+
values: selectedValues,
|
|
732
|
+
})
|
|
733
|
+
) {
|
|
734
|
+
throw Error(
|
|
735
|
+
"Specified indices of selectfromsequence that was an excluded combination",
|
|
736
|
+
);
|
|
737
|
+
}
|
|
738
|
+
|
|
739
|
+
return {
|
|
740
|
+
setEssentialValue: { selectedValues, selectedIndices: desiredIndices },
|
|
741
|
+
setValue: { selectedValues, selectedIndices: desiredIndices },
|
|
742
|
+
};
|
|
743
|
+
}
|
|
744
|
+
}
|
|
745
|
+
|
|
746
|
+
let numberCombinationsExcluded = dependencyValues.excludedCombinations.length;
|
|
747
|
+
|
|
748
|
+
if (dependencyValues.type === "number") {
|
|
749
|
+
// account for fact that an excluded combination with a NaN is a wildcard
|
|
750
|
+
// this could be an overestimate, as different combinations could match the same value
|
|
751
|
+
numberCombinationsExcluded = 0;
|
|
752
|
+
let numValues = dependencyValues.length - dependencyValues.exclude.length;
|
|
753
|
+
for (let comb of dependencyValues.excludedCombinations) {
|
|
754
|
+
let numNans = comb.reduce((a, c) => a + (Number.isNaN(c) ? 1 : 0), 0);
|
|
755
|
+
|
|
756
|
+
if (numNans > 0) {
|
|
757
|
+
if (dependencyValues.withReplacement) {
|
|
758
|
+
numberCombinationsExcluded += Math.pow(numValues, numNans);
|
|
759
|
+
} else {
|
|
760
|
+
let n = numValues - dependencyValues.numToSelect + numNans;
|
|
761
|
+
let nExcl = n;
|
|
762
|
+
for (let i = 1; i < numNans; i++) {
|
|
763
|
+
nExcl *= n - i;
|
|
764
|
+
}
|
|
765
|
+
numberCombinationsExcluded += nExcl;
|
|
766
|
+
}
|
|
767
|
+
} else {
|
|
768
|
+
numberCombinationsExcluded += 1;
|
|
769
|
+
}
|
|
770
|
+
}
|
|
771
|
+
}
|
|
772
|
+
|
|
773
|
+
let selectedValues, selectedIndices;
|
|
774
|
+
|
|
775
|
+
if (numberCombinationsExcluded === 0) {
|
|
776
|
+
let selectedObj = selectValuesAndIndices({
|
|
777
|
+
stateValues: dependencyValues,
|
|
778
|
+
numberUniqueRequired: numberUniqueRequired,
|
|
779
|
+
numToSelect: dependencyValues.numToSelect,
|
|
780
|
+
withReplacement: dependencyValues.withReplacement,
|
|
781
|
+
rng: dependencyValues.variantRng,
|
|
782
|
+
});
|
|
783
|
+
|
|
784
|
+
selectedValues = selectedObj.selectedValues;
|
|
785
|
+
selectedIndices = selectedObj.selectedIndices;
|
|
786
|
+
} else {
|
|
787
|
+
let numberPossibilitiesLowerBound =
|
|
788
|
+
dependencyValues.length - dependencyValues.exclude.length;
|
|
789
|
+
|
|
790
|
+
if (dependencyValues.withReplacement) {
|
|
791
|
+
numberPossibilitiesLowerBound = Math.pow(
|
|
792
|
+
numberPossibilitiesLowerBound,
|
|
793
|
+
dependencyValues.numToSelect,
|
|
794
|
+
);
|
|
795
|
+
} else {
|
|
796
|
+
let n = numberPossibilitiesLowerBound;
|
|
797
|
+
for (let i = 1; i < dependencyValues.numToSelect; i++) {
|
|
798
|
+
numberPossibilitiesLowerBound *= n - i;
|
|
799
|
+
}
|
|
800
|
+
}
|
|
801
|
+
|
|
802
|
+
if (numberCombinationsExcluded > 0.7 * numberPossibilitiesLowerBound) {
|
|
803
|
+
// may have excluded over 70% of combinations
|
|
804
|
+
// need to determine actual number of possibilities
|
|
805
|
+
// to see if really have excluded that many combinations
|
|
806
|
+
|
|
807
|
+
let numberPossibilities = 0;
|
|
808
|
+
for (let index = 0; index < dependencyValues.length; index++) {
|
|
809
|
+
if (
|
|
810
|
+
returnSequenceValueForIndex({
|
|
811
|
+
index,
|
|
812
|
+
from: dependencyValues.from,
|
|
813
|
+
step: dependencyValues.step,
|
|
814
|
+
length: dependencyValues.length,
|
|
815
|
+
exclude: dependencyValues.exclude,
|
|
816
|
+
type: dependencyValues.type,
|
|
817
|
+
}) !== null
|
|
818
|
+
) {
|
|
819
|
+
numberPossibilities++;
|
|
820
|
+
}
|
|
821
|
+
}
|
|
822
|
+
|
|
823
|
+
if (dependencyValues.withReplacement) {
|
|
824
|
+
numberPossibilities = Math.pow(
|
|
825
|
+
numberPossibilities,
|
|
826
|
+
dependencyValues.numToSelect,
|
|
827
|
+
);
|
|
828
|
+
} else {
|
|
829
|
+
let n = numberPossibilities;
|
|
830
|
+
for (let i = 1; i < dependencyValues.numToSelect; i++) {
|
|
831
|
+
numberPossibilities *= n - i;
|
|
832
|
+
}
|
|
833
|
+
}
|
|
834
|
+
|
|
835
|
+
if (numberCombinationsExcluded > 0.7 * numberPossibilities) {
|
|
836
|
+
if (
|
|
837
|
+
dependencyValues.type === "number" &&
|
|
838
|
+
dependencyValues.excludedCombinations.some((x) =>
|
|
839
|
+
x.some(Number.isNaN),
|
|
840
|
+
)
|
|
841
|
+
) {
|
|
842
|
+
let numberDuplicated = estimateNumberOfDuplicateCombinations(
|
|
843
|
+
dependencyValues.excludedCombinations,
|
|
844
|
+
dependencyValues.length - dependencyValues.exclude.length,
|
|
845
|
+
dependencyValues.withReplacement,
|
|
846
|
+
);
|
|
847
|
+
|
|
848
|
+
numberCombinationsExcluded -= numberDuplicated;
|
|
849
|
+
|
|
850
|
+
if (numberCombinationsExcluded > 0.7 * numberPossibilities) {
|
|
851
|
+
throw Error(
|
|
852
|
+
"Excluded over 70% of combinations in selectFromSequence",
|
|
853
|
+
);
|
|
854
|
+
}
|
|
855
|
+
} else {
|
|
856
|
+
throw Error(
|
|
857
|
+
"Excluded over 70% of combinations in selectFromSequence",
|
|
858
|
+
);
|
|
859
|
+
}
|
|
860
|
+
}
|
|
861
|
+
}
|
|
862
|
+
|
|
863
|
+
// with 200 chances with at least 70% success,
|
|
864
|
+
// prob of failure less than 10^(-30)
|
|
865
|
+
let foundValidCombination = false;
|
|
866
|
+
for (let sampnum = 0; sampnum < 200; sampnum++) {
|
|
867
|
+
let selectedObj = selectValuesAndIndices({
|
|
868
|
+
stateValues: dependencyValues,
|
|
869
|
+
numberUniqueRequired: numberUniqueRequired,
|
|
870
|
+
numToSelect: dependencyValues.numToSelect,
|
|
871
|
+
withReplacement: dependencyValues.withReplacement,
|
|
872
|
+
rng: dependencyValues.variantRng,
|
|
873
|
+
});
|
|
874
|
+
|
|
875
|
+
selectedValues = selectedObj.selectedValues;
|
|
876
|
+
selectedIndices = selectedObj.selectedIndices;
|
|
877
|
+
|
|
878
|
+
// try again if hit excluded combination
|
|
879
|
+
if (
|
|
880
|
+
checkForExcludedCombination({
|
|
881
|
+
type: dependencyValues.type,
|
|
882
|
+
excludedCombinations: dependencyValues.excludedCombinations,
|
|
883
|
+
values: selectedValues,
|
|
884
|
+
})
|
|
885
|
+
) {
|
|
886
|
+
continue;
|
|
887
|
+
}
|
|
888
|
+
|
|
889
|
+
foundValidCombination = true;
|
|
890
|
+
break;
|
|
891
|
+
}
|
|
892
|
+
|
|
893
|
+
if (!foundValidCombination) {
|
|
894
|
+
// this won't happen, as occurs with prob < 10^(-30)
|
|
895
|
+
throw Error(
|
|
896
|
+
"By extremely unlikely fluke, couldn't select combination of random values",
|
|
897
|
+
);
|
|
898
|
+
}
|
|
899
|
+
}
|
|
900
|
+
|
|
901
|
+
if (dependencyValues.sortResults) {
|
|
902
|
+
// combine selectedIndices and selectedValues to sort together
|
|
903
|
+
let combinedList = [];
|
|
904
|
+
for (let [ind, val] of selectedValues.entries()) {
|
|
905
|
+
combinedList.push({ value: val, index: selectedIndices[ind] });
|
|
906
|
+
}
|
|
907
|
+
|
|
908
|
+
if (dependencyValues.type === "number") {
|
|
909
|
+
combinedList.sort((a, b) => a.value - b.value);
|
|
910
|
+
} else if (dependencyValues.type === "letters") {
|
|
911
|
+
// sort according to their numerical value, not as words
|
|
912
|
+
combinedList.sort(
|
|
913
|
+
(a, b) => lettersToNumber(a.value) - lettersToNumber(b.value),
|
|
914
|
+
);
|
|
915
|
+
}
|
|
916
|
+
|
|
917
|
+
selectedValues = combinedList.map((x) => x.value);
|
|
918
|
+
selectedIndices = combinedList.map((x) => x.index);
|
|
919
|
+
|
|
920
|
+
// don't sort type math
|
|
921
|
+
}
|
|
922
|
+
|
|
923
|
+
return {
|
|
924
|
+
setEssentialValue: { selectedValues, selectedIndices },
|
|
925
|
+
setValue: { selectedValues, selectedIndices },
|
|
926
|
+
};
|
|
927
|
+
}
|
|
928
|
+
|
|
929
|
+
function selectValuesAndIndices({
|
|
930
|
+
stateValues,
|
|
931
|
+
numberUniqueRequired = 1,
|
|
932
|
+
numToSelect = 1,
|
|
933
|
+
withReplacement = false,
|
|
934
|
+
rng,
|
|
935
|
+
}) {
|
|
936
|
+
let selectedValues = [];
|
|
937
|
+
let selectedIndices = [];
|
|
938
|
+
|
|
939
|
+
if (
|
|
940
|
+
stateValues.exclude.length + numberUniqueRequired <
|
|
941
|
+
0.5 * stateValues.length
|
|
942
|
+
) {
|
|
943
|
+
// the simplest case where the likelihood of getting excluded is less than 50%
|
|
944
|
+
// just randomly select from all possibilities
|
|
945
|
+
// and use rejection method to resample if an excluded is hit
|
|
946
|
+
// or repeat a value when withReplacement=false
|
|
947
|
+
|
|
948
|
+
for (let ind = 0; ind < numToSelect; ind++) {
|
|
949
|
+
// with 100 chances with at least 50% success,
|
|
950
|
+
// prob of failure less than 10^(-30)
|
|
951
|
+
let foundValid = false;
|
|
952
|
+
let componentValue;
|
|
953
|
+
let selectedIndex;
|
|
954
|
+
for (let sampnum = 0; sampnum < 100; sampnum++) {
|
|
955
|
+
// random number in [0, 1)
|
|
956
|
+
let rand = rng();
|
|
957
|
+
// random integer from 1 to length
|
|
958
|
+
selectedIndex = Math.floor(rand * stateValues.length) + 1;
|
|
959
|
+
|
|
960
|
+
if (!withReplacement && selectedIndices.includes(selectedIndex)) {
|
|
961
|
+
continue;
|
|
962
|
+
}
|
|
963
|
+
|
|
964
|
+
componentValue = returnSequenceValueForIndex({
|
|
965
|
+
index: selectedIndex - 1,
|
|
966
|
+
from: stateValues.from,
|
|
967
|
+
step: stateValues.step,
|
|
968
|
+
exclude: stateValues.exclude,
|
|
969
|
+
type: stateValues.type,
|
|
970
|
+
lowercase: stateValues.lowercase,
|
|
971
|
+
});
|
|
972
|
+
|
|
973
|
+
// try again if hit excluded value
|
|
974
|
+
if (componentValue === null) {
|
|
975
|
+
continue;
|
|
976
|
+
}
|
|
977
|
+
|
|
978
|
+
foundValid = true;
|
|
979
|
+
break;
|
|
980
|
+
}
|
|
981
|
+
|
|
982
|
+
if (!foundValid) {
|
|
983
|
+
// this won't happen, as occurs with prob < 10^(-30)
|
|
984
|
+
throw Error(
|
|
985
|
+
"By extremely unlikely fluke, couldn't select random value",
|
|
986
|
+
);
|
|
987
|
+
}
|
|
988
|
+
|
|
989
|
+
selectedValues.push(componentValue);
|
|
990
|
+
selectedIndices.push(selectedIndex);
|
|
991
|
+
}
|
|
992
|
+
|
|
993
|
+
return { selectedValues, selectedIndices };
|
|
994
|
+
}
|
|
995
|
+
|
|
996
|
+
// for cases when a large fraction might be excluded
|
|
997
|
+
// we will generate the list of possible values and pick from those
|
|
998
|
+
|
|
999
|
+
let possibleValuesAndIndices = returnSequenceValues(stateValues, true);
|
|
1000
|
+
|
|
1001
|
+
let numPossibleValues = possibleValuesAndIndices.length;
|
|
1002
|
+
|
|
1003
|
+
if (numberUniqueRequired > numPossibleValues) {
|
|
1004
|
+
throw Error(
|
|
1005
|
+
"Cannot select " +
|
|
1006
|
+
numberUniqueRequired +
|
|
1007
|
+
" unique values from sequence of length " +
|
|
1008
|
+
numPossibleValues,
|
|
1009
|
+
);
|
|
1010
|
+
}
|
|
1011
|
+
|
|
1012
|
+
if (numberUniqueRequired === 1) {
|
|
1013
|
+
for (let ind = 0; ind < numToSelect; ind++) {
|
|
1014
|
+
// random number in [0, 1)
|
|
1015
|
+
let rand = rng();
|
|
1016
|
+
// random integer from 0 to numPossibleValues-1
|
|
1017
|
+
let ind = Math.floor(rand * numPossibleValues);
|
|
1018
|
+
|
|
1019
|
+
selectedIndices.push(possibleValuesAndIndices[ind].originalIndex + 1);
|
|
1020
|
+
selectedValues.push(possibleValuesAndIndices[ind].value);
|
|
1021
|
+
}
|
|
1022
|
+
|
|
1023
|
+
return { selectedValues, selectedIndices };
|
|
1024
|
+
}
|
|
1025
|
+
|
|
1026
|
+
// need to select more than one value without replacement
|
|
1027
|
+
// shuffle array and choose first elements
|
|
1028
|
+
// https://stackoverflow.com/a/12646864
|
|
1029
|
+
for (let i = possibleValuesAndIndices.length - 1; i > 0; i--) {
|
|
1030
|
+
const rand = rng();
|
|
1031
|
+
const j = Math.floor(rand * (i + 1));
|
|
1032
|
+
[possibleValuesAndIndices[i], possibleValuesAndIndices[j]] = [
|
|
1033
|
+
possibleValuesAndIndices[j],
|
|
1034
|
+
possibleValuesAndIndices[i],
|
|
1035
|
+
];
|
|
1036
|
+
}
|
|
1037
|
+
|
|
1038
|
+
let selectedValuesAndIndices = possibleValuesAndIndices.slice(0, numToSelect);
|
|
1039
|
+
selectedValues = selectedValuesAndIndices.map((x) => x.value);
|
|
1040
|
+
selectedIndices = selectedValuesAndIndices.map((x) => x.originalIndex + 1);
|
|
1041
|
+
|
|
1042
|
+
return { selectedValues, selectedIndices };
|
|
1043
|
+
}
|
|
1044
|
+
|
|
1045
|
+
function checkForExcludedCombination({ type, excludedCombinations, values }) {
|
|
1046
|
+
if (type === "math") {
|
|
1047
|
+
return excludedCombinations.some((x) =>
|
|
1048
|
+
x.every((v, i) => v.equals(values[i])),
|
|
1049
|
+
);
|
|
1050
|
+
} else if (type === "number") {
|
|
1051
|
+
// if one entry of excluded combinations is NaN, then it is a wildcard
|
|
1052
|
+
// that will match any value
|
|
1053
|
+
return excludedCombinations.some((x) =>
|
|
1054
|
+
x.every(
|
|
1055
|
+
(v, i) =>
|
|
1056
|
+
Number.isNaN(v) ||
|
|
1057
|
+
Math.abs(v - values[i]) <=
|
|
1058
|
+
1e-14 * Math.max(Math.abs(v), Math.abs(values[i])),
|
|
1059
|
+
),
|
|
1060
|
+
);
|
|
1061
|
+
} else {
|
|
1062
|
+
return excludedCombinations.some((x) => x.every((v, i) => v === values[i]));
|
|
1063
|
+
}
|
|
1064
|
+
}
|
|
1065
|
+
|
|
1066
|
+
function mergeContainingCombinations(combinations) {
|
|
1067
|
+
if (combinations.length === 0) {
|
|
1068
|
+
return { merged: false, combinations: [] };
|
|
1069
|
+
}
|
|
1070
|
+
|
|
1071
|
+
let mergedCombinations = [combinations[0]];
|
|
1072
|
+
|
|
1073
|
+
let mergedAtLeastOne = false;
|
|
1074
|
+
|
|
1075
|
+
for (let comb of combinations.slice(1)) {
|
|
1076
|
+
let newCombinations = [];
|
|
1077
|
+
let merged = false;
|
|
1078
|
+
|
|
1079
|
+
for (let oldComb of mergedCombinations) {
|
|
1080
|
+
if (merged) {
|
|
1081
|
+
newCombinations.push(oldComb);
|
|
1082
|
+
continue;
|
|
1083
|
+
}
|
|
1084
|
+
let newComb = [];
|
|
1085
|
+
merged = true;
|
|
1086
|
+
let mergingInto = null;
|
|
1087
|
+
for (let k = 0; k < comb.length; k++) {
|
|
1088
|
+
let v1 = comb[k],
|
|
1089
|
+
v2 = oldComb[k];
|
|
1090
|
+
if (Number.isNaN(v1)) {
|
|
1091
|
+
if (Number.isNaN(v2)) {
|
|
1092
|
+
newComb.push(NaN);
|
|
1093
|
+
} else {
|
|
1094
|
+
// want to merge into 1
|
|
1095
|
+
if (mergingInto === 2) {
|
|
1096
|
+
// already merging into 2, so cannot merge
|
|
1097
|
+
merged = false;
|
|
1098
|
+
break;
|
|
1099
|
+
} else {
|
|
1100
|
+
newComb.push(NaN);
|
|
1101
|
+
mergingInto = 1;
|
|
1102
|
+
}
|
|
1103
|
+
}
|
|
1104
|
+
} else if (Number.isNaN(v2)) {
|
|
1105
|
+
// want to merge into 2
|
|
1106
|
+
if (mergingInto === 1) {
|
|
1107
|
+
// already merging into 1, so cannot merge
|
|
1108
|
+
merged = false;
|
|
1109
|
+
break;
|
|
1110
|
+
} else {
|
|
1111
|
+
newComb.push(NaN);
|
|
1112
|
+
mergingInto = 2;
|
|
1113
|
+
}
|
|
1114
|
+
} else {
|
|
1115
|
+
if (v1 === v2) {
|
|
1116
|
+
newComb.push(v1);
|
|
1117
|
+
} else {
|
|
1118
|
+
merged = false;
|
|
1119
|
+
break;
|
|
1120
|
+
}
|
|
1121
|
+
}
|
|
1122
|
+
}
|
|
1123
|
+
|
|
1124
|
+
if (merged) {
|
|
1125
|
+
newCombinations.push(newComb);
|
|
1126
|
+
} else {
|
|
1127
|
+
newCombinations.push(oldComb);
|
|
1128
|
+
}
|
|
1129
|
+
}
|
|
1130
|
+
|
|
1131
|
+
if (merged) {
|
|
1132
|
+
mergedAtLeastOne = true;
|
|
1133
|
+
} else {
|
|
1134
|
+
newCombinations.push(comb);
|
|
1135
|
+
}
|
|
1136
|
+
|
|
1137
|
+
mergedCombinations = newCombinations;
|
|
1138
|
+
}
|
|
1139
|
+
|
|
1140
|
+
return {
|
|
1141
|
+
merged: mergedAtLeastOne,
|
|
1142
|
+
combinations: mergedCombinations,
|
|
1143
|
+
};
|
|
1144
|
+
}
|
|
1145
|
+
|
|
1146
|
+
function estimateNumberOfDuplicateCombinations(
|
|
1147
|
+
combinations,
|
|
1148
|
+
numValues,
|
|
1149
|
+
withReplacement,
|
|
1150
|
+
) {
|
|
1151
|
+
// if have wildcards, get better estimate of number excluded
|
|
1152
|
+
|
|
1153
|
+
let nCombs = combinations.length;
|
|
1154
|
+
|
|
1155
|
+
if (nCombs === 0) {
|
|
1156
|
+
return 0;
|
|
1157
|
+
}
|
|
1158
|
+
|
|
1159
|
+
let duplicateCombinations = [];
|
|
1160
|
+
for (let i = 0; i < nCombs; i++) {
|
|
1161
|
+
let comb1 = combinations[i];
|
|
1162
|
+
for (let j = i + 1; j < nCombs; j++) {
|
|
1163
|
+
let comb2 = combinations[j];
|
|
1164
|
+
let foundDuplicate = true;
|
|
1165
|
+
let duplicate = [];
|
|
1166
|
+
for (let k = 0; k < comb1.length; k++) {
|
|
1167
|
+
let v1 = comb1[k],
|
|
1168
|
+
v2 = comb2[k];
|
|
1169
|
+
if (Number.isNaN(v1)) {
|
|
1170
|
+
if (Number.isNaN(v2)) {
|
|
1171
|
+
duplicate.push(NaN);
|
|
1172
|
+
} else {
|
|
1173
|
+
duplicate.push(v2);
|
|
1174
|
+
}
|
|
1175
|
+
} else if (Number.isNaN(v2)) {
|
|
1176
|
+
duplicate.push(v1);
|
|
1177
|
+
} else {
|
|
1178
|
+
if (v1 === v2) {
|
|
1179
|
+
duplicate.push(v1);
|
|
1180
|
+
} else {
|
|
1181
|
+
foundDuplicate = false;
|
|
1182
|
+
break;
|
|
1183
|
+
}
|
|
1184
|
+
}
|
|
1185
|
+
}
|
|
1186
|
+
|
|
1187
|
+
if (foundDuplicate) {
|
|
1188
|
+
if (withReplacement) {
|
|
1189
|
+
duplicateCombinations.push(duplicate);
|
|
1190
|
+
} else {
|
|
1191
|
+
let nonNanEntries = duplicate.filter((x) => !Number.isNaN(x));
|
|
1192
|
+
if ([...new Set(nonNanEntries)].length === nonNanEntries.length) {
|
|
1193
|
+
duplicateCombinations.push(duplicate);
|
|
1194
|
+
}
|
|
1195
|
+
}
|
|
1196
|
+
}
|
|
1197
|
+
}
|
|
1198
|
+
}
|
|
1199
|
+
|
|
1200
|
+
// TODO: get a more accurate count of the number of excluded combinations.
|
|
1201
|
+
// This is just a heuristic to reduce the count
|
|
1202
|
+
while (true) {
|
|
1203
|
+
let result = mergeContainingCombinations(duplicateCombinations);
|
|
1204
|
+
|
|
1205
|
+
if (result.merged) {
|
|
1206
|
+
duplicateCombinations = result.combinations;
|
|
1207
|
+
} else {
|
|
1208
|
+
break;
|
|
1209
|
+
}
|
|
1210
|
+
}
|
|
1211
|
+
|
|
1212
|
+
let numberDuplicated = 0;
|
|
1213
|
+
|
|
1214
|
+
if (duplicateCombinations.length > 0) {
|
|
1215
|
+
for (let comb of duplicateCombinations) {
|
|
1216
|
+
let numNans = comb.reduce((a, c) => a + (Number.isNaN(c) ? 1 : 0), 0);
|
|
1217
|
+
|
|
1218
|
+
if (numNans > 0) {
|
|
1219
|
+
if (withReplacement) {
|
|
1220
|
+
numberDuplicated += Math.pow(numValues, numNans);
|
|
1221
|
+
} else {
|
|
1222
|
+
let n = numValues - comb.length + numNans;
|
|
1223
|
+
let nDup = n;
|
|
1224
|
+
for (let i = 1; i < numNans; i++) {
|
|
1225
|
+
nDup *= n - i;
|
|
1226
|
+
}
|
|
1227
|
+
numberDuplicated += nDup;
|
|
1228
|
+
}
|
|
1229
|
+
} else {
|
|
1230
|
+
numberDuplicated += 1;
|
|
1231
|
+
}
|
|
1232
|
+
}
|
|
1233
|
+
}
|
|
1234
|
+
|
|
1235
|
+
numberDuplicated -= estimateNumberOfDuplicateCombinations(
|
|
1236
|
+
duplicateCombinations,
|
|
1237
|
+
numValues,
|
|
1238
|
+
withReplacement,
|
|
1239
|
+
);
|
|
1240
|
+
|
|
1241
|
+
return numberDuplicated;
|
|
1242
|
+
}
|