@classytic/labs 0.1.0 → 0.2.0
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/dist/_virtual/_rolldown/runtime.mjs +18 -0
- package/dist/biology/enzyme-rate/preset.mjs +5 -5
- package/dist/biology/genetic-cross/core.d.mts +7 -7
- package/dist/biology/genetic-cross/core.mjs +4 -4
- package/dist/biology/genetic-cross/grid.mjs +132 -123
- package/dist/biology/genetic-cross/preset.mjs +4 -4
- package/dist/biology/genetic-cross/sex-linked.mjs +7 -7
- package/dist/biology/photosynthesis-factors/preset.mjs +8 -8
- package/dist/biology/respiration/preset.mjs +4 -4
- package/dist/biology/sequence/central-dogma.mjs +5 -5
- package/dist/biology/sequence/core.d.mts +6 -6
- package/dist/biology/sequence/core.mjs +1 -1
- package/dist/biology/sequence/preset.mjs +6 -6
- package/dist/blocks/authoring.mjs +5 -5
- package/dist/blocks/biology.d.mts +2 -2
- package/dist/blocks/biology.mjs +5 -5
- package/dist/blocks/chem.d.mts +2 -2
- package/dist/blocks/chem.mjs +13 -13
- package/dist/blocks/circuits.d.mts +293 -4
- package/dist/blocks/circuits.mjs +874 -9
- package/dist/blocks/discrete.d.mts +30 -2
- package/dist/blocks/discrete.mjs +74 -4
- package/dist/blocks/economics.mjs +1 -1
- package/dist/blocks/geography.mjs +1 -1
- package/dist/blocks/geometry.mjs +3 -3
- package/dist/blocks/ict.d.mts +90 -1
- package/dist/blocks/ict.mjs +217 -7
- package/dist/blocks/index.d.mts +3064 -657
- package/dist/blocks/index.mjs +9 -9
- package/dist/blocks/lab-block.mjs +5 -5
- package/dist/blocks/lab-config.d.mts +1 -1
- package/dist/blocks/lab-config.mjs +4 -4
- package/dist/blocks/lab-gallery.d.mts +1 -1
- package/dist/blocks/lab-gallery.mjs +2 -2
- package/dist/blocks/language.d.mts +6 -6
- package/dist/blocks/language.mjs +12 -12
- package/dist/blocks/lesson.mjs +4 -4
- package/dist/blocks/math.d.mts +577 -11
- package/dist/blocks/math.mjs +1648 -14
- package/dist/blocks/ml.d.mts +45 -1
- package/dist/blocks/ml.mjs +80 -6
- package/dist/blocks/physics.d.mts +9 -4
- package/dist/blocks/physics.mjs +75 -28
- package/dist/blocks/statistics.mjs +1 -1
- package/dist/build/CircuitEditor.d.mts +14 -0
- package/dist/build/CircuitEditor.mjs +787 -0
- package/dist/build/CircuitPlayer.d.mts +19 -0
- package/dist/build/CircuitPlayer.mjs +53 -0
- package/dist/build/CircuitScene.d.mts +61 -0
- package/dist/build/CircuitScene.mjs +383 -0
- package/dist/build/contract.d.mts +116 -0
- package/dist/build/editor-ops.d.mts +65 -0
- package/dist/build/editor-ops.mjs +306 -0
- package/dist/build/editor-ui.mjs +121 -0
- package/dist/build/flow.d.mts +14 -0
- package/dist/build/flow.mjs +119 -0
- package/dist/build/index.d.mts +10 -0
- package/dist/build/index.mjs +10 -0
- package/dist/build/parts/ammeter.d.mts +1 -0
- package/dist/build/parts/ammeter.mjs +32 -0
- package/dist/build/parts/bulb.d.mts +1 -0
- package/dist/build/parts/bulb.mjs +50 -0
- package/dist/build/parts/capacitor.d.mts +1 -0
- package/dist/build/parts/capacitor.mjs +26 -0
- package/dist/build/parts/cell.d.mts +1 -0
- package/dist/build/parts/cell.mjs +40 -0
- package/dist/build/parts/diode.d.mts +1 -0
- package/dist/build/parts/diode.mjs +33 -0
- package/dist/build/parts/index.d.mts +5 -0
- package/dist/build/parts/index.mjs +43 -0
- package/dist/build/parts/mosfet.d.mts +1 -0
- package/dist/build/parts/mosfet.mjs +95 -0
- package/dist/build/parts/node.d.mts +1 -0
- package/dist/build/parts/node.mjs +32 -0
- package/dist/build/parts/resistor.d.mts +1 -0
- package/dist/build/parts/resistor.mjs +49 -0
- package/dist/build/parts/shared.mjs +42 -0
- package/dist/build/parts/switch.d.mts +1 -0
- package/dist/build/parts/switch.mjs +34 -0
- package/dist/build/parts.d.mts +1 -0
- package/dist/build/registry.d.mts +9 -0
- package/dist/build/registry.mjs +15 -0
- package/dist/build/solve.d.mts +8 -0
- package/dist/build/solve.mjs +0 -0
- package/dist/catalog/registry.d.mts +2 -2
- package/dist/catalog/templates.d.mts +1 -1
- package/dist/catalog/templates.mjs +6 -6
- package/dist/chem/battery.mjs +1 -1
- package/dist/chem/bohr-atom.mjs +4 -4
- package/dist/chem/diffusion/preset.mjs +4 -4
- package/dist/chem/electrochem/preset.mjs +5 -5
- package/dist/chem/equilibrium/preset.d.mts +1 -1
- package/dist/chem/equilibrium/preset.mjs +6 -6
- package/dist/chem/gas-box/preset.mjs +6 -6
- package/dist/chem/kinetics/preset.mjs +6 -6
- package/dist/chem/periodic-trends/preset.mjs +7 -7
- package/dist/chem/reaction-lab.mjs +3 -3
- package/dist/chem/reaction-profile.mjs +4 -4
- package/dist/chem/solution/dilution.mjs +6 -6
- package/dist/chem/solution/field.d.mts +2 -2
- package/dist/chem/solution/field.mjs +2 -2
- package/dist/chem/solution/solution-box.mjs +7 -7
- package/dist/chem/stoichiometry/preset.mjs +5 -5
- package/dist/chem/titration/preset.mjs +5 -5
- package/dist/circuits/ac-dc/asset.mjs +1 -1
- package/dist/circuits/ac-dc/preset.mjs +2 -2
- package/dist/circuits/brownout/index.d.mts +1 -0
- package/dist/circuits/brownout/preset.d.mts +22 -0
- package/dist/circuits/brownout/preset.mjs +399 -0
- package/dist/circuits/capacitor-leak/preset.mjs +13 -8
- package/dist/circuits/circuit/asset.mjs +71 -14
- package/dist/circuits/circuit/preset.mjs +23 -5
- package/dist/circuits/circuit-builder.mjs +60 -132
- package/dist/circuits/circuit-lab.mjs +60 -40
- package/dist/circuits/cmos-gate/index.d.mts +1 -0
- package/dist/circuits/cmos-gate/preset.d.mts +75 -0
- package/dist/circuits/cmos-gate/preset.mjs +1491 -0
- package/dist/circuits/diode/index.d.mts +1 -0
- package/dist/circuits/diode/preset.d.mts +25 -0
- package/dist/circuits/diode/preset.mjs +266 -0
- package/dist/circuits/index.d.mts +7 -1
- package/dist/circuits/index.mjs +7 -1
- package/dist/circuits/rc-charging/index.d.mts +1 -0
- package/dist/circuits/rc-charging/preset.d.mts +27 -0
- package/dist/circuits/rc-charging/preset.mjs +329 -0
- package/dist/circuits/semiconductor/index.d.mts +1 -0
- package/dist/circuits/semiconductor/preset.d.mts +102 -0
- package/dist/circuits/semiconductor/preset.mjs +1855 -0
- package/dist/circuits/transistor/index.d.mts +1 -0
- package/dist/circuits/transistor/preset.d.mts +27 -0
- package/dist/circuits/transistor/preset.mjs +329 -0
- package/dist/commerce/accounting/core.d.mts +1 -1
- package/dist/commerce/accounting/equation-balance.mjs +5 -5
- package/dist/commerce/accounting/journal-poster.mjs +8 -8
- package/dist/commerce/accounting/statement-sorter.mjs +4 -4
- package/dist/commerce/economics/core.d.mts +2 -2
- package/dist/commerce/economics/core.mjs +1 -1
- package/dist/commerce/economics/demand-shift-vs-move.mjs +6 -6
- package/dist/commerce/economics/elasticity-revenue.mjs +6 -6
- package/dist/commerce/economics/market-equilibrium.mjs +5 -5
- package/dist/core/easing.d.mts +3 -3
- package/dist/core/easing.mjs +2 -2
- package/dist/core/numeric.d.mts +3 -3
- package/dist/core/numeric.mjs +2 -2
- package/dist/core/reactive.d.mts +1 -1
- package/dist/core/reactive.mjs +1 -1
- package/dist/core/rng.d.mts +2 -2
- package/dist/core/rng.mjs +1 -1
- package/dist/core/tex.mjs +2 -2
- package/dist/core/timeline.d.mts +1 -1
- package/dist/core/timeline.mjs +1 -1
- package/dist/core/util.mjs +11 -1
- package/dist/discrete/arrangements/preset.mjs +6 -14
- package/dist/discrete/bayes/preset.mjs +43 -35
- package/dist/discrete/binomial/preset.mjs +2 -2
- package/dist/discrete/combination-studio/figure.d.mts +6 -0
- package/dist/discrete/combination-studio/figure.mjs +159 -0
- package/dist/discrete/combination-studio/index.d.mts +2 -0
- package/dist/discrete/combination-studio/preset.d.mts +44 -0
- package/dist/discrete/combination-studio/preset.mjs +440 -0
- package/dist/discrete/core/combinatorics.d.mts +23 -3
- package/dist/discrete/core/combinatorics.mjs +38 -3
- package/dist/discrete/core/pigeonhole.d.mts +1 -1
- package/dist/discrete/core/pigeonhole.mjs +1 -1
- package/dist/discrete/core/probability.d.mts +3 -3
- package/dist/discrete/core/probability.mjs +3 -3
- package/dist/discrete/core/sets.d.mts +1 -1
- package/dist/discrete/counting-slots/preset.mjs +8 -8
- package/dist/discrete/counting-tree/preset.mjs +65 -8
- package/dist/discrete/expected-value/preset.mjs +13 -13
- package/dist/discrete/hypergeometric/preset.mjs +48 -15
- package/dist/discrete/index.d.mts +4 -2
- package/dist/discrete/index.mjs +4 -2
- package/dist/discrete/karnaugh/preset.mjs +26 -20
- package/dist/discrete/lln/preset.mjs +44 -3
- package/dist/discrete/logic-circuit/preset.mjs +2 -2
- package/dist/discrete/monte-carlo/preset.d.mts +1 -1
- package/dist/discrete/monte-carlo/preset.mjs +14 -14
- package/dist/discrete/monty-hall/preset.mjs +6 -6
- package/dist/discrete/outcome-builder/preset.mjs +3 -3
- package/dist/discrete/pascal/preset.mjs +37 -7
- package/dist/discrete/rules.d.mts +20 -0
- package/dist/discrete/rules.mjs +264 -0
- package/dist/discrete/sample-space/preset.mjs +4 -4
- package/dist/discrete/selection/preset.mjs +7 -13
- package/dist/discrete/truth-table/preset.mjs +32 -9
- package/dist/discrete/venn/preset.mjs +71 -48
- package/dist/geography/cycle-lab/preset.mjs +17 -10
- package/dist/geography/cycles.d.mts +3 -3
- package/dist/geography/cycles.mjs +3 -3
- package/dist/geometry/board/preset.d.mts +2 -0
- package/dist/geometry/board/preset.mjs +11 -15
- package/dist/geometry/builder.mjs +3 -3
- package/dist/ict/number-systems/base-odometer.mjs +4 -4
- package/dist/ict/number-systems/bit-grouper.d.mts +1 -1
- package/dist/ict/number-systems/bit-grouper.mjs +4 -4
- package/dist/ict/number-systems/place-value-dial.d.mts +1 -1
- package/dist/ict/number-systems/place-value-dial.mjs +3 -3
- package/dist/ict/number-systems/wheel.d.mts +3 -3
- package/dist/ict/number-systems/wheel.mjs +4 -4
- package/dist/kit/annotate.mjs +3 -3
- package/dist/kit/answer-check.d.mts +2 -2
- package/dist/kit/answer-check.mjs +34 -6
- package/dist/kit/ask.d.mts +19 -0
- package/dist/kit/ask.mjs +46 -0
- package/dist/kit/bar-strip.mjs +53 -0
- package/dist/kit/calc.d.mts +33 -0
- package/dist/kit/calc.mjs +27 -0
- package/dist/kit/carrier-engine.mjs +147 -0
- package/dist/kit/clue-scene.d.mts +86 -0
- package/dist/kit/clue-scene.mjs +424 -0
- package/dist/kit/cluster.d.mts +30 -0
- package/dist/kit/cluster.mjs +81 -0
- package/dist/kit/controls.mjs +11 -5
- package/dist/kit/coords.d.mts +88 -0
- package/dist/kit/coords.mjs +192 -0
- package/dist/kit/data-scene.d.mts +27 -0
- package/dist/kit/data-scene.mjs +199 -0
- package/dist/kit/diagram.mjs +111 -50
- package/dist/kit/electronics.mjs +552 -60
- package/dist/kit/expr-analysis.d.mts +18 -6
- package/dist/kit/expr-analysis.mjs +82 -28
- package/dist/kit/frame.d.mts +3 -3
- package/dist/kit/frame.mjs +25 -6
- package/dist/kit/gameshow.mjs +2 -2
- package/dist/kit/index.d.mts +14 -2
- package/dist/kit/index.mjs +13 -1
- package/dist/kit/logic-gates.mjs +246 -47
- package/dist/kit/palette.mjs +26 -0
- package/dist/kit/pedagogy.d.mts +4 -4
- package/dist/kit/pedagogy.mjs +21 -17
- package/dist/kit/play.d.mts +1 -1
- package/dist/kit/play.mjs +3 -3
- package/dist/kit/predict.d.mts +55 -0
- package/dist/kit/predict.mjs +146 -0
- package/dist/kit/receipt.d.mts +29 -0
- package/dist/kit/receipt.mjs +94 -0
- package/dist/kit/rich.mjs +2 -2
- package/dist/kit/rule.d.mts +59 -0
- package/dist/kit/rule.mjs +215 -0
- package/dist/kit/scale.mjs +1 -1
- package/dist/kit/scene-library.d.mts +22 -0
- package/dist/kit/scene-library.mjs +311 -0
- package/dist/kit/scene-studio.d.mts +14 -0
- package/dist/kit/scene-studio.mjs +338 -0
- package/dist/kit/scenes.d.mts +31 -0
- package/dist/kit/scenes.mjs +569 -0
- package/dist/kit/slot-fill.d.mts +61 -0
- package/dist/kit/slot-fill.mjs +207 -0
- package/dist/kit/solve.d.mts +21 -0
- package/dist/kit/solve.mjs +75 -0
- package/dist/kit/space.mjs +5 -5
- package/dist/kit/steps.mjs +2 -2
- package/dist/kit/vessel.d.mts +69 -0
- package/dist/kit/vessel.mjs +191 -0
- package/dist/language/agreement/preset.mjs +2 -2
- package/dist/language/article-lens/preset.d.mts +1 -1
- package/dist/language/article-lens/preset.mjs +8 -8
- package/dist/language/deck.d.mts +3 -3
- package/dist/language/deck.mjs +1 -1
- package/dist/language/preposition-scene/preset.d.mts +2 -2
- package/dist/language/preposition-scene/preset.mjs +5 -5
- package/dist/language/sentence-builder/preset.mjs +5 -5
- package/dist/language/transform/preset.d.mts +2 -2
- package/dist/language/transform/preset.mjs +5 -5
- package/dist/language/ui.d.mts +3 -3
- package/dist/language/ui.mjs +4 -4
- package/dist/language/word-match/preset.mjs +3 -3
- package/dist/logic/LogicBuildLab.d.mts +22 -0
- package/dist/logic/LogicBuildLab.mjs +170 -0
- package/dist/logic/LogicEditScene.d.mts +31 -0
- package/dist/logic/LogicEditScene.mjs +276 -0
- package/dist/logic/LogicEditor.d.mts +14 -0
- package/dist/logic/LogicEditor.mjs +413 -0
- package/dist/logic/LogicScene.d.mts +32 -0
- package/dist/logic/LogicScene.mjs +277 -0
- package/dist/logic/contract.d.mts +72 -0
- package/dist/logic/display.d.mts +24 -0
- package/dist/logic/display.mjs +127 -0
- package/dist/logic/edit-ops.d.mts +44 -0
- package/dist/logic/edit-ops.mjs +177 -0
- package/dist/logic/evaluate.d.mts +11 -0
- package/dist/logic/evaluate.mjs +93 -0
- package/dist/logic/gates.d.mts +10 -0
- package/dist/logic/gates.mjs +73 -0
- package/dist/logic/index.d.mts +14 -0
- package/dist/logic/index.mjs +13 -0
- package/dist/logic/lab.d.mts +32 -0
- package/dist/logic/lab.mjs +160 -0
- package/dist/logic/presets.d.mts +12 -0
- package/dist/logic/presets.mjs +241 -0
- package/dist/logic/registry.d.mts +9 -0
- package/dist/logic/registry.mjs +15 -0
- package/dist/math/area-model/preset.mjs +70 -44
- package/dist/math/balance-algebra/preset.mjs +14 -5
- package/dist/math/broken-tree/index.d.mts +1 -0
- package/dist/math/broken-tree/preset.d.mts +26 -0
- package/dist/math/broken-tree/preset.mjs +435 -0
- package/dist/math/circle/index.d.mts +1 -0
- package/dist/math/circle/preset.d.mts +44 -0
- package/dist/math/circle/preset.mjs +198 -0
- package/dist/math/complex/core.d.mts +93 -0
- package/dist/math/complex/core.mjs +239 -0
- package/dist/math/complex/index.d.mts +3 -0
- package/dist/math/complex/preset.d.mts +31 -0
- package/dist/math/complex/preset.mjs +377 -0
- package/dist/math/complex/rules.d.mts +6 -0
- package/dist/math/complex/rules.mjs +121 -0
- package/dist/math/conic/index.d.mts +1 -0
- package/dist/math/conic/preset.d.mts +30 -0
- package/dist/math/conic/preset.mjs +334 -0
- package/dist/math/derivation.mjs +5 -5
- package/dist/math/derivative-explorer/preset.mjs +5 -5
- package/dist/math/domain-range/index.d.mts +1 -0
- package/dist/math/domain-range/preset.d.mts +33 -0
- package/dist/math/domain-range/preset.mjs +313 -0
- package/dist/math/fraction-bar/index.d.mts +1 -0
- package/dist/math/fraction-bar/preset.d.mts +27 -0
- package/dist/math/fraction-bar/preset.mjs +197 -0
- package/dist/math/function-machine/preset.mjs +2 -2
- package/dist/math/gradient-descent.mjs +6 -6
- package/dist/math/grapher/preset.d.mts +1 -1
- package/dist/math/grapher/preset.mjs +4 -4
- package/dist/math/harmonic-form/preset.mjs +6 -6
- package/dist/math/index.d.mts +27 -2
- package/dist/math/index.mjs +27 -2
- package/dist/math/integral-explorer/preset.mjs +2 -2
- package/dist/math/interactive/preset.mjs +3 -3
- package/dist/math/limit-explorer/preset.mjs +4 -4
- package/dist/math/linear-model/index.d.mts +1 -0
- package/dist/math/linear-model/preset.d.mts +53 -0
- package/dist/math/linear-model/preset.mjs +164 -0
- package/dist/math/linear-system/preset.mjs +4 -4
- package/dist/math/mystery-bucket/preset.mjs +6 -6
- package/dist/math/number-line/preset.mjs +3 -2
- package/dist/math/parabola/preset.mjs +4 -3
- package/dist/math/pattern/preset.mjs +7 -13
- package/dist/math/percent-bar/index.d.mts +1 -0
- package/dist/math/percent-bar/preset.d.mts +37 -0
- package/dist/math/percent-bar/preset.mjs +275 -0
- package/dist/math/poly/core.d.mts +50 -0
- package/dist/math/poly/core.mjs +268 -0
- package/dist/math/poly/index.d.mts +3 -0
- package/dist/math/poly/preset.d.mts +23 -0
- package/dist/math/poly/preset.mjs +141 -0
- package/dist/math/poly/steps.d.mts +10 -0
- package/dist/math/poly/steps.mjs +99 -0
- package/dist/math/rate-machine/index.d.mts +1 -0
- package/dist/math/rate-machine/preset.d.mts +35 -0
- package/dist/math/rate-machine/preset.mjs +281 -0
- package/dist/math/ratio-share/index.d.mts +1 -0
- package/dist/math/ratio-share/preset.d.mts +24 -0
- package/dist/math/ratio-share/preset.mjs +204 -0
- package/dist/math/receipt/index.d.mts +1 -0
- package/dist/math/receipt/preset.d.mts +22 -0
- package/dist/math/receipt/preset.mjs +137 -0
- package/dist/math/sequence-predict/index.d.mts +1 -0
- package/dist/math/sequence-predict/preset.d.mts +34 -0
- package/dist/math/sequence-predict/preset.mjs +130 -0
- package/dist/math/straight-line/index.d.mts +1 -0
- package/dist/math/straight-line/preset.d.mts +37 -0
- package/dist/math/straight-line/preset.mjs +374 -0
- package/dist/math/system-solve/index.d.mts +1 -0
- package/dist/math/system-solve/preset.d.mts +21 -0
- package/dist/math/system-solve/preset.mjs +227 -0
- package/dist/math/transform/index.d.mts +1 -0
- package/dist/math/transform/preset.d.mts +41 -0
- package/dist/math/transform/preset.mjs +343 -0
- package/dist/math/triangle-trig/preset.mjs +12 -9
- package/dist/math/trig/core.d.mts +37 -0
- package/dist/math/trig/core.mjs +150 -0
- package/dist/math/trig/diagrams.d.mts +1 -0
- package/dist/math/trig/diagrams.mjs +321 -0
- package/dist/math/trig/index.d.mts +3 -0
- package/dist/math/trig/preset.d.mts +25 -0
- package/dist/math/trig/preset.mjs +260 -0
- package/dist/math/trig/rules.d.mts +6 -0
- package/dist/math/trig/rules.mjs +159 -0
- package/dist/math/trig-explorer.mjs +4 -4
- package/dist/ml/boundary/preset.mjs +8 -3
- package/dist/ml/classifier/preset.mjs +31 -6
- package/dist/ml/kmeans/preset.mjs +4 -4
- package/dist/ml/knn/preset.mjs +47 -12
- package/dist/ml/regression/preset.mjs +36 -7
- package/dist/physics/atwood/preset.mjs +4 -4
- package/dist/physics/bullet-walls/preset.d.mts +1 -1
- package/dist/physics/bullet-walls/preset.mjs +7 -7
- package/dist/physics/carnot/preset.mjs +6 -6
- package/dist/physics/circular-motion/preset.mjs +36 -5
- package/dist/physics/collision-track/preset.mjs +35 -5
- package/dist/physics/efficiency/preset.d.mts +2 -2
- package/dist/physics/efficiency/preset.mjs +5 -5
- package/dist/physics/electric-field/preset.mjs +32 -23
- package/dist/physics/electric-flux/index.d.mts +1 -0
- package/dist/physics/electric-flux/preset.d.mts +29 -0
- package/dist/physics/electric-flux/preset.mjs +264 -0
- package/dist/physics/energy-skate/preset.mjs +5 -5
- package/dist/physics/entropy/preset.mjs +7 -7
- package/dist/physics/expansion/preset.mjs +13 -13
- package/dist/physics/exponential/asset.mjs +1 -1
- package/dist/physics/exponential/preset.mjs +4 -4
- package/dist/physics/gas-process/preset.mjs +3 -3
- package/dist/physics/gauss-law/index.d.mts +1 -0
- package/dist/physics/gauss-law/preset.d.mts +20 -0
- package/dist/physics/gauss-law/preset.mjs +286 -0
- package/dist/physics/gravitation/preset.mjs +7 -7
- package/dist/physics/gravity-drop.mjs +4 -4
- package/dist/physics/heat-transfer/preset.d.mts +1 -1
- package/dist/physics/heat-transfer/preset.mjs +10 -10
- package/dist/physics/impulse/preset.mjs +5 -5
- package/dist/physics/index.d.mts +4 -1
- package/dist/physics/index.mjs +4 -1
- package/dist/physics/kepler/preset.mjs +4 -4
- package/dist/physics/lever/preset.mjs +3 -3
- package/dist/physics/lorentz/preset.mjs +11 -11
- package/dist/physics/magnetism/preset.mjs +3 -3
- package/dist/physics/optics/preset.mjs +2 -2
- package/dist/physics/orbit-lab.mjs +5 -5
- package/dist/physics/projectile-lab.mjs +4 -4
- package/dist/physics/rain-relative/preset.mjs +5 -5
- package/dist/physics/ramp-forces/preset.mjs +5 -5
- package/dist/physics/river-boat.mjs +6 -6
- package/dist/physics/shm/preset.mjs +9 -9
- package/dist/physics/stopping-distance/preset.mjs +3 -3
- package/dist/physics/temperature-scales/preset.mjs +105 -116
- package/dist/physics/terminal-velocity/preset.mjs +5 -5
- package/dist/physics/thermal/preset.mjs +5 -5
- package/dist/physics/vector-board/preset.mjs +7 -6
- package/dist/physics/vector-scene.mjs +2 -2
- package/dist/physics/vector-types/preset.mjs +37 -3
- package/dist/physics/water-density/preset.mjs +12 -12
- package/dist/physics/waves/doppler.mjs +2 -2
- package/dist/physics/waves/preset.mjs +4 -4
- package/dist/physics/waves/ripple.mjs +6 -6
- package/dist/physics/waves/string.mjs +5 -5
- package/dist/physics/work-energy/preset.mjs +4 -4
- package/dist/physics/work-potential/index.d.mts +1 -0
- package/dist/physics/work-potential/preset.d.mts +20 -0
- package/dist/physics/work-potential/preset.mjs +276 -0
- package/dist/schemas/index.d.mts +6 -6
- package/dist/schemas/index.mjs +3 -3
- package/dist/statistics/center-spread/preset.mjs +3 -3
- package/dist/statistics/core/descriptive.d.mts +2 -2
- package/dist/statistics/core/descriptive.mjs +2 -2
- package/dist/statistics/core/normal.d.mts +3 -3
- package/dist/statistics/core/normal.mjs +3 -3
- package/dist/statistics/core/sequences.d.mts +1 -1
- package/dist/statistics/galton/preset.mjs +2 -2
- package/dist/statistics/histogram/preset.mjs +6 -6
- package/dist/statistics/normal/preset.mjs +2 -2
- package/dist/statistics/sampling/preset.mjs +4 -4
- package/dist/statistics/sequence/preset.mjs +58 -15
- package/dist/statistics/z-table/preset.mjs +17 -4
- package/package.json +11 -3
- package/styles.css +4 -1
|
@@ -8,7 +8,7 @@ import { jsx, jsxs } from "react/jsx-runtime";
|
|
|
8
8
|
|
|
9
9
|
//#region src/language/article-lens/preset.tsx
|
|
10
10
|
/**
|
|
11
|
-
* ArticleLens
|
|
11
|
+
* ArticleLens, choose a / an / the /, (no article).
|
|
12
12
|
*
|
|
13
13
|
* Bangla has no articles, so this is the highest-novelty English error for
|
|
14
14
|
* Bangla speakers. The "lens" framing: tap the article that fits, and on a
|
|
@@ -19,15 +19,15 @@ const CHOICES = [
|
|
|
19
19
|
"a",
|
|
20
20
|
"an",
|
|
21
21
|
"the",
|
|
22
|
-
"
|
|
22
|
+
", "
|
|
23
23
|
];
|
|
24
24
|
const RULE = {
|
|
25
25
|
a: "a → any one (new), before a consonant sound",
|
|
26
26
|
an: "an → any one (new), before a vowel sound",
|
|
27
27
|
the: "the → the specific one we both know",
|
|
28
|
-
"
|
|
28
|
+
", ": "no article → general or uncountable"
|
|
29
29
|
};
|
|
30
|
-
function ArticleLensLab({ items, objectives, hints: hintList, title = "Choose the article", prompt = "Bangla has no a/an/the
|
|
30
|
+
function ArticleLensLab({ items, objectives, hints: hintList, title = "Choose the article", prompt = "Bangla has no a/an/the: pick what English needs." }) {
|
|
31
31
|
const [idx, setIdx] = useState(0);
|
|
32
32
|
const [picked, setPicked] = useState(null);
|
|
33
33
|
const [solvedCount, setSolvedCount] = useState(0);
|
|
@@ -50,7 +50,7 @@ function ArticleLensLab({ items, objectives, hints: hintList, title = "Choose th
|
|
|
50
50
|
},
|
|
51
51
|
hintsUsed: hints.count
|
|
52
52
|
});
|
|
53
|
-
const blank = useMemo(() => picked === null ? "▢" : picked === "
|
|
53
|
+
const blank = useMemo(() => picked === null ? "▢" : picked === ", " ? "∅" : picked, [picked]);
|
|
54
54
|
if (!item) return null;
|
|
55
55
|
const pick = (a) => {
|
|
56
56
|
if (correct) return;
|
|
@@ -92,15 +92,15 @@ function ArticleLensLab({ items, objectives, hints: hintList, title = "Choose th
|
|
|
92
92
|
"data-state": picked === a ? correct ? "ok" : "no" : "idle",
|
|
93
93
|
disabled: correct,
|
|
94
94
|
onClick: () => pick(a),
|
|
95
|
-
"aria-label": a === "
|
|
96
|
-
children: a === "
|
|
95
|
+
"aria-label": a === ", " ? "no article" : a,
|
|
96
|
+
children: a === ", " ? "no article" : a
|
|
97
97
|
}, a))
|
|
98
98
|
}),
|
|
99
99
|
picked !== null && /* @__PURE__ */ jsx("p", {
|
|
100
100
|
className: "lang-why",
|
|
101
101
|
"data-state": correct ? "ok" : "no",
|
|
102
102
|
"aria-live": "polite",
|
|
103
|
-
children: correct ? item.why ?? RULE[item.answer] : "Not quite
|
|
103
|
+
children: correct ? item.why ?? RULE[item.answer] : "Not quite, try another."
|
|
104
104
|
})
|
|
105
105
|
]
|
|
106
106
|
});
|
package/dist/language/deck.d.mts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { IconValue } from "./icon.mjs";
|
|
2
2
|
|
|
3
3
|
//#region src/language/deck.d.ts
|
|
4
|
-
/** Part of speech
|
|
4
|
+
/** Part of speech, drives the Montessori-style colour coding across grammar
|
|
5
5
|
* labs so a learner builds one consistent visual intuition. */
|
|
6
6
|
type Pos = 'noun' | 'verb' | 'article' | 'adjective' | 'preposition' | 'pronoun' | 'conjunction' | 'adverb' | 'other';
|
|
7
7
|
declare const POS_LABEL: Record<Pos, string>;
|
|
@@ -14,7 +14,7 @@ interface DeckItem {
|
|
|
14
14
|
transliteration?: string;
|
|
15
15
|
/** Optional audio: an uploaded media URL OR an external URL. Never generated. */
|
|
16
16
|
audioUrl?: string;
|
|
17
|
-
/** Optional picture for kids/visual decks
|
|
17
|
+
/** Optional picture for kids/visual decks, an emoji string, or an `IconRef`
|
|
18
18
|
* ({ kind:'emoji'|'svg'|'image', … }) for a registered SVG / uploaded image. */
|
|
19
19
|
icon?: IconValue;
|
|
20
20
|
/** Optional usage example (target language). */
|
|
@@ -38,7 +38,7 @@ declare function hasVoiceFor(lang: string): boolean;
|
|
|
38
38
|
declare function canSpeak(item: DeckItem, lang: string): boolean;
|
|
39
39
|
/** Play an item's audio. Returns false if nothing was playable. */
|
|
40
40
|
declare function speak(item: DeckItem, lang: string): boolean;
|
|
41
|
-
/** Deterministic shuffle (seeded LCG)
|
|
41
|
+
/** Deterministic shuffle (seeded LCG), same input+seed → same order, so SSR
|
|
42
42
|
* and client agree. Never uses Math.random at module scope. */
|
|
43
43
|
declare function seededShuffle<T>(arr: readonly T[], seed?: number): T[];
|
|
44
44
|
//#endregion
|
package/dist/language/deck.mjs
CHANGED
|
@@ -39,7 +39,7 @@ function speak(item, lang) {
|
|
|
39
39
|
}
|
|
40
40
|
return false;
|
|
41
41
|
}
|
|
42
|
-
/** Deterministic shuffle (seeded LCG)
|
|
42
|
+
/** Deterministic shuffle (seeded LCG), same input+seed → same order, so SSR
|
|
43
43
|
* and client agree. Never uses Math.random at module scope. */
|
|
44
44
|
function seededShuffle(arr, seed = 1) {
|
|
45
45
|
const a = arr.slice();
|
|
@@ -13,9 +13,9 @@ interface PrepItem {
|
|
|
13
13
|
options: string[];
|
|
14
14
|
/** Spatial relation to depict (positions the figure vs the landmark). */
|
|
15
15
|
scene: Relation;
|
|
16
|
-
/** The figure being placed
|
|
16
|
+
/** The figure being placed, an emoji string or an `IconRef`. Default a ball. */
|
|
17
17
|
figure?: IconValue;
|
|
18
|
-
/** The reference landmark
|
|
18
|
+
/** The reference landmark, an emoji/`IconRef`, OR a backdrop key string
|
|
19
19
|
* ('sky'|'water'|'ground'|'room'). Default a box. */
|
|
20
20
|
landmark?: IconValue;
|
|
21
21
|
note?: string;
|
|
@@ -9,12 +9,12 @@ import { jsx, jsxs } from "react/jsx-runtime";
|
|
|
9
9
|
|
|
10
10
|
//#region src/language/preposition-scene/preset.tsx
|
|
11
11
|
/**
|
|
12
|
-
* PrepositionScene
|
|
12
|
+
* PrepositionScene, pick the preposition that matches a spatial picture.
|
|
13
13
|
*
|
|
14
14
|
* Prepositions are inherently spatial, so each item shows a little scene (a
|
|
15
15
|
* thing in / on / under / beside a box) and the learner names the relation.
|
|
16
16
|
* The teaching point for Bangla speakers: English puts the preposition BEFORE
|
|
17
|
-
* the noun ("on the box"), where Bangla uses a postposition AFTER it
|
|
17
|
+
* the noun ("on the box"), where Bangla uses a postposition AFTER it, so the
|
|
18
18
|
* answer slots in front of the noun and the note makes that contrast explicit.
|
|
19
19
|
*/
|
|
20
20
|
const figAt = (left, top, scale = 1, opacity) => ({
|
|
@@ -96,7 +96,7 @@ function backdropFigPos(kind, rel) {
|
|
|
96
96
|
if (kind === "ground") return hi ? figAt("50%", "20%") : lo ? figAt("50%", "86%") : figAt("50%", "60%");
|
|
97
97
|
return figAt("50%", "48%");
|
|
98
98
|
}
|
|
99
|
-
/** Plain-text label for an icon value (emoji char or IconRef.alt)
|
|
99
|
+
/** Plain-text label for an icon value (emoji char or IconRef.alt), for the
|
|
100
100
|
* scene's aria-label, since the visuals themselves are decorative. */
|
|
101
101
|
function iconLabel(v) {
|
|
102
102
|
const r = normalizeIcon(v);
|
|
@@ -134,7 +134,7 @@ function SceneView({ relation, figure = "🔵", landmark = "📦" }) {
|
|
|
134
134
|
]
|
|
135
135
|
});
|
|
136
136
|
}
|
|
137
|
-
function PrepositionSceneLab({ items, title = "Where is it?", prompt = "Pick the preposition
|
|
137
|
+
function PrepositionSceneLab({ items, title = "Where is it?", prompt = "Pick the preposition: in English it comes BEFORE the noun." }) {
|
|
138
138
|
const [idx, setIdx] = useState(0);
|
|
139
139
|
const [picked, setPicked] = useState(null);
|
|
140
140
|
const [solvedCount, setSolvedCount] = useState(0);
|
|
@@ -211,7 +211,7 @@ function PrepositionSceneLab({ items, title = "Where is it?", prompt = "Pick the
|
|
|
211
211
|
className: "lang-why",
|
|
212
212
|
"data-state": correct ? "ok" : "no",
|
|
213
213
|
"aria-live": "polite",
|
|
214
|
-
children: correct ? item.note ?? `English: "${item.answer} ${item.noun}"
|
|
214
|
+
children: correct ? item.note ?? `English: "${item.answer} ${item.noun}", the preposition comes first.` : "Not quite, look at the picture."
|
|
215
215
|
})
|
|
216
216
|
]
|
|
217
217
|
});
|
|
@@ -10,16 +10,16 @@ import { jsx, jsxs } from "react/jsx-runtime";
|
|
|
10
10
|
|
|
11
11
|
//#region src/language/sentence-builder/preset.tsx
|
|
12
12
|
/**
|
|
13
|
-
* SentenceBuilder
|
|
13
|
+
* SentenceBuilder, order the words into a correct sentence.
|
|
14
14
|
*
|
|
15
15
|
* The flagship grammar lab: tiles are colour-coded by part of speech and carry
|
|
16
16
|
* an optional L1 gloss, so a learner SEES the structure while building it. The
|
|
17
|
-
* `prompt` shows the meaning (e.g. the learner's-language sentence) above
|
|
17
|
+
* `prompt` shows the meaning (e.g. the learner's-language sentence) above ,
|
|
18
18
|
* which is exactly how a Bangla speaker meets English word order: same meaning,
|
|
19
19
|
* different slot order (SOV → SVO).
|
|
20
20
|
*
|
|
21
21
|
* Tap a tile in the bank to place it; tap a placed tile to take it back. No
|
|
22
|
-
* drag
|
|
22
|
+
* drag, buttons are touch- and keyboard-friendly. Validates by resulting text,
|
|
23
23
|
* so duplicate/interchangeable words still pass.
|
|
24
24
|
*/
|
|
25
25
|
function SentenceBuilderLab({ tiles, prompt, promptDir = "ltr", targetDir = "ltr", title = "Build the sentence", hint = "Tap the words in the right order." }) {
|
|
@@ -80,7 +80,7 @@ function SentenceBuilderLab({ tiles, prompt, promptDir = "ltr", targetDir = "ltr
|
|
|
80
80
|
gloss: tiles[i].gloss,
|
|
81
81
|
dir: targetDir,
|
|
82
82
|
onClick: () => take(i),
|
|
83
|
-
ariaLabel: `${tiles[i].text}
|
|
83
|
+
ariaLabel: `${tiles[i].text}, tap to remove`
|
|
84
84
|
}, i))
|
|
85
85
|
}),
|
|
86
86
|
/* @__PURE__ */ jsx("div", {
|
|
@@ -92,7 +92,7 @@ function SentenceBuilderLab({ tiles, prompt, promptDir = "ltr", targetDir = "ltr
|
|
|
92
92
|
gloss: tiles[i].gloss,
|
|
93
93
|
dir: targetDir,
|
|
94
94
|
onClick: () => place(i),
|
|
95
|
-
ariaLabel: `${tiles[i].text}
|
|
95
|
+
ariaLabel: `${tiles[i].text}, tap to place`
|
|
96
96
|
}, i))
|
|
97
97
|
}),
|
|
98
98
|
/* @__PURE__ */ jsx(LiveRegion, { children: checked ? correct ? "Correct word order" : "Not the right order yet" : "" })
|
|
@@ -8,9 +8,9 @@ interface TransformTile {
|
|
|
8
8
|
gloss?: string;
|
|
9
9
|
}
|
|
10
10
|
interface TransformProps {
|
|
11
|
-
/** Source sentence tiles (correct order)
|
|
11
|
+
/** Source sentence tiles (correct order), shown read-only. */
|
|
12
12
|
from: TransformTile[];
|
|
13
|
-
/** Target sentence tiles (correct order)
|
|
13
|
+
/** Target sentence tiles (correct order), the learner rebuilds these. */
|
|
14
14
|
to: TransformTile[];
|
|
15
15
|
/** What to do, e.g. "Make it a question". */
|
|
16
16
|
instruction?: string;
|
|
@@ -10,11 +10,11 @@ import { jsx, jsxs } from "react/jsx-runtime";
|
|
|
10
10
|
|
|
11
11
|
//#region src/language/transform/preset.tsx
|
|
12
12
|
/**
|
|
13
|
-
* TransformLab
|
|
13
|
+
* TransformLab, change one sentence into another and SEE what changed.
|
|
14
14
|
*
|
|
15
15
|
* Shows the source sentence (read-only), an instruction ("Make it a question"),
|
|
16
16
|
* and the learner rebuilds the target by tapping tiles. On success the words
|
|
17
|
-
* that are NEW vs the source are ringed
|
|
17
|
+
* that are NEW vs the source are ringed, so the rule (e.g. English injects
|
|
18
18
|
* "Do" for a question; Bangla has no do-support) is visible, not just stated.
|
|
19
19
|
*/
|
|
20
20
|
function TransformLab({ from, to, instruction = "Change the sentence.", note, title = "Transform it", targetDir = "ltr" }) {
|
|
@@ -90,7 +90,7 @@ function TransformLab({ from, to, instruction = "Change the sentence.", note, ti
|
|
|
90
90
|
dir: targetDir,
|
|
91
91
|
selected: checked && correct && isNew(i),
|
|
92
92
|
onClick: () => take(i),
|
|
93
|
-
ariaLabel: `${to[i].text}
|
|
93
|
+
ariaLabel: `${to[i].text}, tap to remove`
|
|
94
94
|
}, i))
|
|
95
95
|
}),
|
|
96
96
|
/* @__PURE__ */ jsx("div", {
|
|
@@ -102,7 +102,7 @@ function TransformLab({ from, to, instruction = "Change the sentence.", note, ti
|
|
|
102
102
|
gloss: to[i].gloss,
|
|
103
103
|
dir: targetDir,
|
|
104
104
|
onClick: () => place(i),
|
|
105
|
-
ariaLabel: `${to[i].text}
|
|
105
|
+
ariaLabel: `${to[i].text}, tap to place`
|
|
106
106
|
}, i))
|
|
107
107
|
}),
|
|
108
108
|
checked && correct && note ? /* @__PURE__ */ jsx("p", {
|
|
@@ -118,7 +118,7 @@ function TransformLab({ from, to, instruction = "Change the sentence.", note, ti
|
|
|
118
118
|
prompt: instruction,
|
|
119
119
|
aside: checked ? /* @__PURE__ */ jsx(StatusPill, {
|
|
120
120
|
ok: correct,
|
|
121
|
-
children: correct ? "✓ Done
|
|
121
|
+
children: correct ? "✓ Done, see what changed" : "Not the right order yet"
|
|
122
122
|
}) : void 0,
|
|
123
123
|
controls: /* @__PURE__ */ jsxs(ControlBar, { children: [/* @__PURE__ */ jsx(CheckButton, {
|
|
124
124
|
onClick: () => setChecked(true),
|
package/dist/language/ui.d.mts
CHANGED
|
@@ -5,7 +5,7 @@ import { ReactNode } from "react";
|
|
|
5
5
|
/**
|
|
6
6
|
* True once the browser's TTS voice list is populated (it loads async).
|
|
7
7
|
*
|
|
8
|
-
* Starts `false
|
|
8
|
+
* Starts `false`, NOT seeded from `getVoices()`, so the first client render
|
|
9
9
|
* matches the server (where there's no `speechSynthesis`). Seeding from the
|
|
10
10
|
* live voice list would make a TTS-only item render its speaker button on the
|
|
11
11
|
* client but not the server → a hydration mismatch that forces React to
|
|
@@ -14,11 +14,11 @@ import { ReactNode } from "react";
|
|
|
14
14
|
*/
|
|
15
15
|
declare function useVoicesReady(): boolean;
|
|
16
16
|
/**
|
|
17
|
-
* A speaker button
|
|
17
|
+
* A speaker button, renders nothing if the item can't be voiced.
|
|
18
18
|
*
|
|
19
19
|
* `audioUrl` items can voice on the server too (no browser needed), so they
|
|
20
20
|
* render the button consistently across SSR/hydration. Browser-TTS items only
|
|
21
|
-
* become voiceable once `voicesReady` flips post-mount
|
|
21
|
+
* become voiceable once `voicesReady` flips post-mount, gating on it (instead
|
|
22
22
|
* of querying `window.speechSynthesis` during render) keeps the first client
|
|
23
23
|
* render identical to the server.
|
|
24
24
|
*/
|
package/dist/language/ui.mjs
CHANGED
|
@@ -6,7 +6,7 @@ import { jsx, jsxs } from "react/jsx-runtime";
|
|
|
6
6
|
|
|
7
7
|
//#region src/language/ui.tsx
|
|
8
8
|
/**
|
|
9
|
-
* Shared DOM UI for the language labs
|
|
9
|
+
* Shared DOM UI for the language labs, Speaker button + POS-coloured Tile.
|
|
10
10
|
* Themed via the `.lang-*` classes shipped in `@classytic/labs/styles.css`
|
|
11
11
|
* (POS colours come from `--lang-pos-*` tokens). Kept here, not in the generic
|
|
12
12
|
* `kit/controls`, so non-language labs pay nothing for it.
|
|
@@ -14,7 +14,7 @@ import { jsx, jsxs } from "react/jsx-runtime";
|
|
|
14
14
|
/**
|
|
15
15
|
* True once the browser's TTS voice list is populated (it loads async).
|
|
16
16
|
*
|
|
17
|
-
* Starts `false
|
|
17
|
+
* Starts `false`, NOT seeded from `getVoices()`, so the first client render
|
|
18
18
|
* matches the server (where there's no `speechSynthesis`). Seeding from the
|
|
19
19
|
* live voice list would make a TTS-only item render its speaker button on the
|
|
20
20
|
* client but not the server → a hydration mismatch that forces React to
|
|
@@ -35,11 +35,11 @@ function useVoicesReady() {
|
|
|
35
35
|
return ready;
|
|
36
36
|
}
|
|
37
37
|
/**
|
|
38
|
-
* A speaker button
|
|
38
|
+
* A speaker button, renders nothing if the item can't be voiced.
|
|
39
39
|
*
|
|
40
40
|
* `audioUrl` items can voice on the server too (no browser needed), so they
|
|
41
41
|
* render the button consistently across SSR/hydration. Browser-TTS items only
|
|
42
|
-
* become voiceable once `voicesReady` flips post-mount
|
|
42
|
+
* become voiceable once `voicesReady` flips post-mount, gating on it (instead
|
|
43
43
|
* of querying `window.speechSynthesis` during render) keeps the first client
|
|
44
44
|
* render identical to the server.
|
|
45
45
|
*/
|
|
@@ -11,11 +11,11 @@ import { jsx, jsxs } from "react/jsx-runtime";
|
|
|
11
11
|
|
|
12
12
|
//#region src/language/word-match/preset.tsx
|
|
13
13
|
/**
|
|
14
|
-
* WordMatch
|
|
14
|
+
* WordMatch, pair each word with its meaning (or picture).
|
|
15
15
|
*
|
|
16
16
|
* Tap a word on the left, then its match on the right; a correct pair locks
|
|
17
|
-
* green, a wrong pair flashes. Right side shows the translation, or
|
|
18
|
-
* concrete vocab
|
|
17
|
+
* green, a wrong pair flashes. Right side shows the translation, or, for kids /
|
|
18
|
+
* concrete vocab, the item's icon (emoji/SVG), which is where image-based
|
|
19
19
|
* learning genuinely helps (dual coding). Reads its whole content from a `Deck`,
|
|
20
20
|
* so a new language pair is just new data.
|
|
21
21
|
*/
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { LogicDoc } from "./contract.mjs";
|
|
2
|
+
import { ReactNode } from "react";
|
|
3
|
+
|
|
4
|
+
//#region src/logic/LogicBuildLab.d.ts
|
|
5
|
+
interface LogicBuildProps {
|
|
6
|
+
/** starting canvas. Defaults to a seed derived from the goal, or an empty board. */
|
|
7
|
+
doc?: LogicDoc;
|
|
8
|
+
/** a reference LogicDoc or preset key; when set, the lab grades against its truth table. */
|
|
9
|
+
goal?: LogicDoc | string;
|
|
10
|
+
title?: string;
|
|
11
|
+
prompt?: string;
|
|
12
|
+
activity?: string;
|
|
13
|
+
}
|
|
14
|
+
declare function LogicBuildLab({
|
|
15
|
+
doc: doc0,
|
|
16
|
+
goal,
|
|
17
|
+
title,
|
|
18
|
+
prompt,
|
|
19
|
+
activity
|
|
20
|
+
}?: LogicBuildProps): ReactNode;
|
|
21
|
+
//#endregion
|
|
22
|
+
export { LogicBuildLab, LogicBuildProps };
|
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
import { LabFrame } from "../kit/frame.mjs";
|
|
4
|
+
import { useCheckpoint } from "../kit/pedagogy.mjs";
|
|
5
|
+
import { evaluate } from "./evaluate.mjs";
|
|
6
|
+
import { presetDoc } from "./presets.mjs";
|
|
7
|
+
import { LogicEditor } from "./LogicEditor.mjs";
|
|
8
|
+
import { useState } from "react";
|
|
9
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
10
|
+
|
|
11
|
+
//#region src/logic/LogicBuildLab.tsx
|
|
12
|
+
/**
|
|
13
|
+
* LogicBuildLab — a build-your-own-circuit activity on top of LogicEditor. In sandbox mode it
|
|
14
|
+
* is an open canvas (build, wire, play, watch the signal glow). Given a `goal` (a reference
|
|
15
|
+
* LogicDoc or a preset key) it becomes a graded DLD task: the target truth table is shown, the
|
|
16
|
+
* learner wires gates, and the checkpoint fires when their circuit reproduces every target
|
|
17
|
+
* output column (matched by label, over every input combination). The seed canvas starts with
|
|
18
|
+
* the right switches and LEDs so the learner only has to wire the logic.
|
|
19
|
+
*/
|
|
20
|
+
const SIZE = {
|
|
21
|
+
w: 640,
|
|
22
|
+
h: 360
|
|
23
|
+
};
|
|
24
|
+
const labelOf = (n) => n.label ?? n.id;
|
|
25
|
+
/** The column of `outputLabel` over every combination of `inputLabels` (given order); null if missing. */
|
|
26
|
+
function columnByLabels(doc, inputLabels, outputLabel) {
|
|
27
|
+
const idFor = inputLabels.map((lab) => doc.inputs.find((i) => labelOf(i) === lab)?.id);
|
|
28
|
+
if (idFor.some((id) => !id)) return null;
|
|
29
|
+
const out = doc.outputs.find((o) => labelOf(o) === outputLabel);
|
|
30
|
+
if (!out) return null;
|
|
31
|
+
const n = inputLabels.length;
|
|
32
|
+
if (n > 12) return null;
|
|
33
|
+
const col = [];
|
|
34
|
+
for (let m = 0; m < 2 ** n; m++) {
|
|
35
|
+
const setVals = new Map(idFor.map((id, k) => [id, Boolean(m >> n - 1 - k & 1)]));
|
|
36
|
+
const probe = {
|
|
37
|
+
...doc,
|
|
38
|
+
inputs: doc.inputs.map((i) => setVals.has(i.id) ? {
|
|
39
|
+
...i,
|
|
40
|
+
value: setVals.get(i.id)
|
|
41
|
+
} : i)
|
|
42
|
+
};
|
|
43
|
+
col.push(evaluate(probe).outputs[out.id] ?? false);
|
|
44
|
+
}
|
|
45
|
+
return col;
|
|
46
|
+
}
|
|
47
|
+
const eqCol = (a, b) => !!a && !!b && a.length === b.length && a.every((v, i) => v === b[i]);
|
|
48
|
+
/** Seed a starting canvas from the goal: its switches + empty LEDs, so the learner just wires gates. */
|
|
49
|
+
function seedFromGoal(goalDoc) {
|
|
50
|
+
return {
|
|
51
|
+
size: SIZE,
|
|
52
|
+
inputs: goalDoc.inputs.map((inp, i) => ({
|
|
53
|
+
id: `in${i + 1}`,
|
|
54
|
+
label: labelOf(inp),
|
|
55
|
+
value: false,
|
|
56
|
+
x: 40,
|
|
57
|
+
y: 36 + i * 58
|
|
58
|
+
})),
|
|
59
|
+
gates: [],
|
|
60
|
+
outputs: goalDoc.outputs.map((o, i) => ({
|
|
61
|
+
id: `out${i + 1}`,
|
|
62
|
+
in: "",
|
|
63
|
+
label: labelOf(o),
|
|
64
|
+
x: SIZE.w - 76,
|
|
65
|
+
y: 56 + i * 72
|
|
66
|
+
}))
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
function LogicBuildLab({ doc: doc0, goal, title = "Build the circuit", prompt, activity = "logic-build" } = {}) {
|
|
70
|
+
const goalDoc = goal === void 0 ? null : typeof goal === "string" ? presetDoc(goal) : goal;
|
|
71
|
+
const [doc, setDoc] = useState(() => doc0 ?? (goalDoc ? seedFromGoal(goalDoc) : {
|
|
72
|
+
size: SIZE,
|
|
73
|
+
inputs: [],
|
|
74
|
+
gates: [],
|
|
75
|
+
outputs: []
|
|
76
|
+
}));
|
|
77
|
+
const inputLabels = goalDoc ? goalDoc.inputs.map(labelOf) : [];
|
|
78
|
+
const targets = goalDoc ? goalDoc.outputs.map((o) => ({
|
|
79
|
+
label: labelOf(o),
|
|
80
|
+
col: columnByLabels(goalDoc, inputLabels, labelOf(o))
|
|
81
|
+
})) : [];
|
|
82
|
+
const matchedSame = goalDoc ? doc.inputs.length === goalDoc.inputs.length : false;
|
|
83
|
+
const perOutput = targets.map((t) => ({
|
|
84
|
+
label: t.label,
|
|
85
|
+
ok: matchedSame && eqCol(columnByLabels(doc, inputLabels, t.label), t.col)
|
|
86
|
+
}));
|
|
87
|
+
const solved = !!goalDoc && perOutput.length > 0 && perOutput.every((p) => p.ok);
|
|
88
|
+
useCheckpoint({
|
|
89
|
+
solved,
|
|
90
|
+
activity
|
|
91
|
+
});
|
|
92
|
+
const targetTable = goalDoc ? /* @__PURE__ */ jsx("div", {
|
|
93
|
+
style: { overflowX: "auto" },
|
|
94
|
+
children: /* @__PURE__ */ jsxs("table", {
|
|
95
|
+
style: {
|
|
96
|
+
borderCollapse: "collapse",
|
|
97
|
+
fontSize: 12,
|
|
98
|
+
fontVariantNumeric: "tabular-nums"
|
|
99
|
+
},
|
|
100
|
+
children: [/* @__PURE__ */ jsx("thead", { children: /* @__PURE__ */ jsxs("tr", { children: [inputLabels.map((l) => /* @__PURE__ */ jsx("th", {
|
|
101
|
+
style: {
|
|
102
|
+
padding: "3px 7px",
|
|
103
|
+
color: "var(--stage-fg)",
|
|
104
|
+
borderBottom: "1px solid var(--stage-grid)"
|
|
105
|
+
},
|
|
106
|
+
children: l
|
|
107
|
+
}, l)), perOutput.map((p) => /* @__PURE__ */ jsxs("th", {
|
|
108
|
+
style: {
|
|
109
|
+
padding: "3px 7px",
|
|
110
|
+
color: p.ok ? "var(--stage-good)" : "var(--stage-accent)",
|
|
111
|
+
borderBottom: "1px solid var(--stage-grid)"
|
|
112
|
+
},
|
|
113
|
+
children: [p.label, p.ok ? " ✓" : ""]
|
|
114
|
+
}, p.label))] }) }), /* @__PURE__ */ jsx("tbody", { children: Array.from({ length: 1 << inputLabels.length }, (_, m) => /* @__PURE__ */ jsxs("tr", { children: [inputLabels.map((_l, k) => /* @__PURE__ */ jsx("td", {
|
|
115
|
+
style: {
|
|
116
|
+
padding: "3px 7px",
|
|
117
|
+
textAlign: "center",
|
|
118
|
+
color: "var(--stage-muted)"
|
|
119
|
+
},
|
|
120
|
+
children: m >> inputLabels.length - 1 - k & 1
|
|
121
|
+
}, k)), targets.map((t) => /* @__PURE__ */ jsx("td", {
|
|
122
|
+
style: {
|
|
123
|
+
padding: "3px 7px",
|
|
124
|
+
textAlign: "center",
|
|
125
|
+
fontWeight: 700,
|
|
126
|
+
color: t.col?.[m] ? "var(--stage-good)" : "var(--stage-fg)"
|
|
127
|
+
},
|
|
128
|
+
children: t.col?.[m] ? 1 : 0
|
|
129
|
+
}, t.label))] }, m)) })]
|
|
130
|
+
})
|
|
131
|
+
}) : null;
|
|
132
|
+
return /* @__PURE__ */ jsxs(LabFrame, {
|
|
133
|
+
title,
|
|
134
|
+
prompt: prompt ?? (goalDoc ? "Drag gates from the palette and wire them so each LED follows the target column for every input." : "Build any circuit: drop sources, gates, and LEDs, wire them up, and flip the switches to watch the signal flow."),
|
|
135
|
+
children: [goalDoc && /* @__PURE__ */ jsxs("div", {
|
|
136
|
+
style: {
|
|
137
|
+
display: "flex",
|
|
138
|
+
flexWrap: "wrap",
|
|
139
|
+
gap: 16,
|
|
140
|
+
alignItems: "flex-start",
|
|
141
|
+
marginBottom: 14
|
|
142
|
+
},
|
|
143
|
+
children: [/* @__PURE__ */ jsx("div", {
|
|
144
|
+
className: "lab-pill",
|
|
145
|
+
"data-state": solved ? "ok" : "no",
|
|
146
|
+
role: "status",
|
|
147
|
+
children: solved ? "✓ your circuit matches the target" : "wire gates so each output matches its column"
|
|
148
|
+
}), /* @__PURE__ */ jsxs("div", {
|
|
149
|
+
style: {
|
|
150
|
+
display: "flex",
|
|
151
|
+
flexDirection: "column",
|
|
152
|
+
gap: 4
|
|
153
|
+
},
|
|
154
|
+
children: [/* @__PURE__ */ jsx("span", {
|
|
155
|
+
style: {
|
|
156
|
+
fontSize: 12,
|
|
157
|
+
color: "var(--stage-muted)"
|
|
158
|
+
},
|
|
159
|
+
children: "target truth table (build a circuit that does this)"
|
|
160
|
+
}), targetTable]
|
|
161
|
+
})]
|
|
162
|
+
}), /* @__PURE__ */ jsx(LogicEditor, {
|
|
163
|
+
value: doc,
|
|
164
|
+
onChange: setDoc
|
|
165
|
+
})]
|
|
166
|
+
});
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
//#endregion
|
|
170
|
+
export { LogicBuildLab };
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { LogicDoc } from "./contract.mjs";
|
|
2
|
+
import { PortRef } from "./edit-ops.mjs";
|
|
3
|
+
import { PointerEvent, ReactNode } from "react";
|
|
4
|
+
|
|
5
|
+
//#region src/logic/LogicEditScene.d.ts
|
|
6
|
+
interface LogicEditSceneProps {
|
|
7
|
+
doc: LogicDoc;
|
|
8
|
+
selectedId?: string;
|
|
9
|
+
wireStart?: PortRef;
|
|
10
|
+
/** cursor position (canvas coords) while a wire is pending: the rubber-band trails to it. */
|
|
11
|
+
previewCursor?: {
|
|
12
|
+
x: number;
|
|
13
|
+
y: number;
|
|
14
|
+
};
|
|
15
|
+
onNodePointerDown?: (id: string, e: PointerEvent) => void;
|
|
16
|
+
onPortPointerDown?: (ref: PortRef, e: PointerEvent) => void;
|
|
17
|
+
onBackground?: () => void;
|
|
18
|
+
ariaLabel?: string;
|
|
19
|
+
}
|
|
20
|
+
declare function LogicEditScene({
|
|
21
|
+
doc,
|
|
22
|
+
selectedId,
|
|
23
|
+
wireStart,
|
|
24
|
+
previewCursor,
|
|
25
|
+
onNodePointerDown,
|
|
26
|
+
onPortPointerDown,
|
|
27
|
+
onBackground,
|
|
28
|
+
ariaLabel
|
|
29
|
+
}: LogicEditSceneProps): ReactNode;
|
|
30
|
+
//#endregion
|
|
31
|
+
export { LogicEditScene, LogicEditSceneProps };
|