@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
|
@@ -10,9 +10,9 @@ import { Scene, registerAsset } from "@classytic/stage";
|
|
|
10
10
|
|
|
11
11
|
//#region src/chem/diffusion/preset.tsx
|
|
12
12
|
/**
|
|
13
|
-
* DiffusionLab
|
|
13
|
+
* DiffusionLab, two gases, one box: the `particles` core made tangible. The blue
|
|
14
14
|
* and red particles start on opposite sides; press Play and they random-walk into a
|
|
15
|
-
* uniform mix
|
|
15
|
+
* uniform mix, diffusion, and why it never spontaneously un-mixes. Hotter (faster)
|
|
16
16
|
* particles mix sooner. SceneDoc + particles sim + the diffusion asset (sim ≠ render).
|
|
17
17
|
*/
|
|
18
18
|
registerAsset("diffusion", DIFFUSION_ASSET);
|
|
@@ -23,7 +23,7 @@ const DIFFUSION_CHALLENGE = [{
|
|
|
23
23
|
choices: [
|
|
24
24
|
{
|
|
25
25
|
value: "no",
|
|
26
|
-
label: "No
|
|
26
|
+
label: "No: mixing is one-way"
|
|
27
27
|
},
|
|
28
28
|
{
|
|
29
29
|
value: "wait",
|
|
@@ -56,7 +56,7 @@ const DIFFUSION_CHALLENGE = [{
|
|
|
56
56
|
answer: "faster",
|
|
57
57
|
explain: "Faster particles travel and collide more, so the uniform mix is reached sooner."
|
|
58
58
|
}];
|
|
59
|
-
function DiffusionLab({ title = "Diffusion
|
|
59
|
+
function DiffusionLab({ title = "Diffusion: why things mix", prompt = "Blue and red gas start apart. Press Play: random collisions spread them into a uniform mix, and it never un-mixes on its own.", objectives = [
|
|
60
60
|
"See diffusion as random motion, not a force",
|
|
61
61
|
"Watch two gases mix to uniform (the \"mixed %\" climbs)",
|
|
62
62
|
"Hotter (faster) particles mix sooner"
|
|
@@ -11,16 +11,16 @@ import { galvanicCell } from "@classytic/stage/chem";
|
|
|
11
11
|
|
|
12
12
|
//#region src/chem/electrochem/preset.tsx
|
|
13
13
|
/**
|
|
14
|
-
* ElectrochemLab
|
|
14
|
+
* ElectrochemLab, a galvanic (voltaic) cell with a live voltmeter, on the shared
|
|
15
15
|
* `@classytic/stage/chem` Nernst engine. Two metal/metal-ion half-cells joined by a
|
|
16
16
|
* salt bridge: the metal that's easier to oxidise (lower E°) becomes the ANODE (−),
|
|
17
17
|
* the other the CATHODE (+), and electrons stream anode→cathode through the wire.
|
|
18
18
|
*
|
|
19
19
|
* The voltmeter reads the Nernst EMF E = E°cell − (RT/nF)·ln Q, so dragging an ion
|
|
20
|
-
* concentration moves the needle in real time
|
|
20
|
+
* concentration moves the needle in real time, dilute the cathode ion and the
|
|
21
21
|
* voltage drops; pick the SAME metal both sides for a concentration cell (E° = 0,
|
|
22
22
|
* driven purely by the concentration difference). Pick the two electrodes (Daniell
|
|
23
|
-
* Zn/Cu by default)
|
|
23
|
+
* Zn/Cu by default), fully authorable. Play-gated electron flow; pure SVG.
|
|
24
24
|
*/
|
|
25
25
|
const METALS = {
|
|
26
26
|
Mg: {
|
|
@@ -89,7 +89,7 @@ const hc = (m, conc) => ({
|
|
|
89
89
|
E0: METALS[m].E0,
|
|
90
90
|
conc
|
|
91
91
|
});
|
|
92
|
-
function ElectrochemLab({ metalA = "Zn", metalB = "Cu", concA = 1, concB = 1, title = "Galvanic cell
|
|
92
|
+
function ElectrochemLab({ metalA = "Zn", metalB = "Cu", concA = 1, concB = 1, title = "Galvanic cell: the voltage from a reaction", prompt = "Two metals in their salt solutions, joined by a wire and a salt bridge. The voltmeter reads the cell EMF from the Nernst equation, change a concentration and watch it move.", objectives = [
|
|
93
93
|
"Identify the anode (oxidation, −) and cathode (reduction, +) from E°",
|
|
94
94
|
"Read the standard cell EMF E°cell = E°cathode − E°anode",
|
|
95
95
|
"Use the Nernst equation E = E°cell − (RT/nF)·ln Q to see concentration shift the voltage"
|
|
@@ -335,7 +335,7 @@ function ElectrochemLab({ metalA = "Zn", metalB = "Cu", concA = 1, concB = 1, ti
|
|
|
335
335
|
}),
|
|
336
336
|
" is the cathode (reduced). ",
|
|
337
337
|
sameMetal ? /* @__PURE__ */ jsxs(Fragment$1, { children: [
|
|
338
|
-
"Same metal both sides ⇒ E°cell = 0
|
|
338
|
+
"Same metal both sides ⇒ E°cell = 0, this is a ",
|
|
339
339
|
/* @__PURE__ */ jsx("strong", {
|
|
340
340
|
style: { color: "var(--stage-fg)" },
|
|
341
341
|
children: "concentration cell"
|
|
@@ -8,7 +8,7 @@ interface LeChatelierProps {
|
|
|
8
8
|
productName?: string;
|
|
9
9
|
/** Product stoichiometric coefficient ν (A ⇌ ν·B). */
|
|
10
10
|
productCoeff?: number;
|
|
11
|
-
/** Product colour token
|
|
11
|
+
/** Product colour token, the flask tints toward this as product forms. */
|
|
12
12
|
productColor?: string;
|
|
13
13
|
/** Reactant colour token. */
|
|
14
14
|
reactantColor?: string;
|
|
@@ -12,10 +12,10 @@ import { EquilibriumCore } from "@classytic/stage/sim";
|
|
|
12
12
|
|
|
13
13
|
//#region src/chem/equilibrium/preset.tsx
|
|
14
14
|
/**
|
|
15
|
-
* LeChatelierLab
|
|
15
|
+
* LeChatelierLab, a reversible reaction at equilibrium that fights back, on the
|
|
16
16
|
* shared `equilibrium` core. The reaction is AUTHORABLE: a creator declares the two
|
|
17
17
|
* species, the product coefficient, the colours, K, and whether the forward reaction
|
|
18
|
-
* is endothermic
|
|
18
|
+
* is endothermic, so the SAME lab teaches N₂O₄⇌2NO₂ (brown/colourless), the
|
|
19
19
|
* chromate⇌dichromate colour change, a cobalt-complex equilibrium, and so on. The
|
|
20
20
|
* default is the classic:
|
|
21
21
|
*
|
|
@@ -23,7 +23,7 @@ import { EquilibriumCore } from "@classytic/stage/sim";
|
|
|
23
23
|
*
|
|
24
24
|
* The flask tint tracks the product; concentration bars + a live trace show both.
|
|
25
25
|
* Apply a stress (add a species, compress, heat/cool) and watch Le Chatelier shift
|
|
26
|
-
* it to oppose the change
|
|
26
|
+
* it to oppose the change, the SHIFT DIRECTION emerges from the core's Q-vs-K, never
|
|
27
27
|
* hardcoded, so it stays correct for whatever reaction the creator declares.
|
|
28
28
|
* Hand-driven on EquilibriumCore, play-gated.
|
|
29
29
|
*/
|
|
@@ -48,7 +48,7 @@ const EQUILIBRIUM_CHALLENGE = [{
|
|
|
48
48
|
}
|
|
49
49
|
],
|
|
50
50
|
answer: "reactant",
|
|
51
|
-
explain: "Squeezing favours the side with fewer gas moles
|
|
51
|
+
explain: "Squeezing favours the side with fewer gas moles, 1 mol N₂O₄ beats 2 mol NO₂, so the mix goes paler."
|
|
52
52
|
}, {
|
|
53
53
|
id: "heat",
|
|
54
54
|
prompt: "The forward reaction is endothermic. Heating the flask makes the mix…",
|
|
@@ -69,7 +69,7 @@ const EQUILIBRIUM_CHALLENGE = [{
|
|
|
69
69
|
answer: "browner",
|
|
70
70
|
explain: "Heat is a reactant for an endothermic forward step, so it drives more NO₂ (browner) and raises K."
|
|
71
71
|
}];
|
|
72
|
-
function LeChatelierLab({ reactantName = "N₂O₄", productName = "NO₂", productCoeff = 2, productColor = "rgb(150,82,40)", reactantColor = "var(--stage-accent, #3b82f6)", K = .6, endothermic = true, title = "Le Chatelier
|
|
72
|
+
function LeChatelierLab({ reactantName = "N₂O₄", productName = "NO₂", productCoeff = 2, productColor = "rgb(150,82,40)", reactantColor = "var(--stage-accent, #3b82f6)", K = .6, endothermic = true, title = "Le Chatelier: equilibrium fights back", prompt = "A reversible reaction sits at equilibrium (Q = K). Stress it, add a gas, squeeze it, heat it, and watch the reaction shift to oppose the change.", objectives = [
|
|
73
73
|
"Read equilibrium as Q = K (the reaction quotient meets the constant)",
|
|
74
74
|
"Predict the shift when you add/remove a species or change the volume",
|
|
75
75
|
"See heating favour the endothermic side and change K itself"
|
|
@@ -335,7 +335,7 @@ function LeChatelierLab({ reactantName = "N₂O₄", productName = "NO₂", prod
|
|
|
335
335
|
}),
|
|
336
336
|
". Add a species and it’s consumed; compress and it shifts to fewer moles; ",
|
|
337
337
|
endothermic ? "heat and the endothermic forward reaction wins" : "heat and the exothermic reverse reaction wins",
|
|
338
|
-
"
|
|
338
|
+
", and K itself changes with temperature."
|
|
339
339
|
]
|
|
340
340
|
})]
|
|
341
341
|
})] }),
|
|
@@ -12,17 +12,17 @@ import { CanvasLayer, fmt } from "@classytic/stage";
|
|
|
12
12
|
|
|
13
13
|
//#region src/chem/gas-box/preset.tsx
|
|
14
14
|
/**
|
|
15
|
-
* GasBoxLab
|
|
15
|
+
* GasBoxLab, gas in a box: pressure you can watch being MADE.
|
|
16
16
|
*
|
|
17
17
|
* Hundreds of molecules bounce in a box on <CanvasLayer>; drag the piston to set
|
|
18
18
|
* volume, slide temperature (every molecule speeds up, cool→hot colour) and amount
|
|
19
|
-
* n (dots appear/vanish). Pressure is NOT a control
|
|
19
|
+
* n (dots appear/vanish). Pressure is NOT a control, it is MEASURED from how often
|
|
20
20
|
* + how hard the molecules drum the walls (each wall strike flashes), so PV=nRT
|
|
21
21
|
* emerges from the mechanism instead of being plugged in. A "hold constant" lock
|
|
22
22
|
* yields Boyle (lock T), Gay-Lussac (lock V), Charles (lock P → piston floats).
|
|
23
23
|
*
|
|
24
24
|
* The kinetic-theory algebra (P = ⅓(N/V)m⟨v²⟩ → PV=nRT) lives in a PAIRED
|
|
25
|
-
* MathDerivation block, not here
|
|
25
|
+
* MathDerivation block, not here, the sim makes it felt, the derivation proves it.
|
|
26
26
|
* SVG gauge/readouts overlay the canvas; honours prefers-reduced-motion.
|
|
27
27
|
*/
|
|
28
28
|
const GASBOX_CHALLENGE = [{
|
|
@@ -43,7 +43,7 @@ const GASBOX_CHALLENGE = [{
|
|
|
43
43
|
}
|
|
44
44
|
],
|
|
45
45
|
answer: "double",
|
|
46
|
-
explain: "Same molecules strike half the space twice as often
|
|
46
|
+
explain: "Same molecules strike half the space twice as often, Boyle’s law, P ∝ 1/V."
|
|
47
47
|
}, {
|
|
48
48
|
id: "gaylussac",
|
|
49
49
|
prompt: "Hold the volume fixed and HEAT the gas. The pressure…",
|
|
@@ -62,12 +62,12 @@ const GASBOX_CHALLENGE = [{
|
|
|
62
62
|
}
|
|
63
63
|
],
|
|
64
64
|
answer: "rise",
|
|
65
|
-
explain: "Hotter molecules move faster and hit the walls harder and more often
|
|
65
|
+
explain: "Hotter molecules move faster and hit the walls harder and more often, Gay-Lussac, P ∝ T."
|
|
66
66
|
}];
|
|
67
67
|
const H = 6, MAXV = 10, MINV = 2.5, R = .13, MAXN = 320;
|
|
68
68
|
const T0 = 300, SPEED0 = 5.5, TMIN = 80, TMAX = 600;
|
|
69
69
|
const PDISP = 1.5;
|
|
70
|
-
function GasBoxLab({ holdConstant = "none", particleCount = 180, temperature = 300, volume = 7, showGauge = true, title = "Gas in a box
|
|
70
|
+
function GasBoxLab({ holdConstant = "none", particleCount = 180, temperature = 300, volume = 7, showGauge = true, title = "Gas in a box: watch pressure being made", prompt = "Drag the piston, heat it up, add molecules. Pressure is the drumbeat of hits on the walls.", height = 300, objectives }) {
|
|
71
71
|
const [mode, setMode] = useState(holdConstant);
|
|
72
72
|
const [vol, setVol] = useState(clamp(volume, MINV, MAXV));
|
|
73
73
|
const [temp, setTemp] = useState(clamp(temperature, TMIN, TMAX));
|
|
@@ -12,9 +12,9 @@ import { R, fractionAboveEa, halfLife } from "@classytic/stage/chem";
|
|
|
12
12
|
|
|
13
13
|
//#region src/chem/kinetics/preset.tsx
|
|
14
14
|
/**
|
|
15
|
-
* KineticsLab
|
|
15
|
+
* KineticsLab, why heat and catalysts speed reactions, shown the visceral way: a
|
|
16
16
|
* vessel of molecules bouncing around (faster when hot), where only collisions with
|
|
17
|
-
* enough energy (≥ Eₐ) succeed
|
|
17
|
+
* enough energy (≥ Eₐ) succeed, those flash and convert reactant A → product B.
|
|
18
18
|
* Beside it, the Maxwell–Boltzmann energy spread shows the SAME story as the shaded
|
|
19
19
|
* "can react" tail past Eₐ, and a composition bar tracks A→B in real time.
|
|
20
20
|
*
|
|
@@ -49,7 +49,7 @@ const KINETICS_CHALLENGE = [{
|
|
|
49
49
|
}
|
|
50
50
|
],
|
|
51
51
|
answer: "energy",
|
|
52
|
-
explain: "Heat widens the energy spread, so a larger fraction (e^(−Eₐ/RT)) clears the barrier
|
|
52
|
+
explain: "Heat widens the energy spread, so a larger fraction (e^(−Eₐ/RT)) clears the barrier, and they move faster, so collide more often."
|
|
53
53
|
}, {
|
|
54
54
|
id: "cat",
|
|
55
55
|
prompt: "A catalyst speeds a reaction by…",
|
|
@@ -68,9 +68,9 @@ const KINETICS_CHALLENGE = [{
|
|
|
68
68
|
}
|
|
69
69
|
],
|
|
70
70
|
answer: "lowerEa",
|
|
71
|
-
explain: "A catalyst offers a lower-Eₐ path, so far more collisions succeed
|
|
71
|
+
explain: "A catalyst offers a lower-Eₐ path, so far more collisions succeed, without being used up or changing the energy of reactants/products."
|
|
72
72
|
}];
|
|
73
|
-
function KineticsLab({ EaKJ = 50, kRef = .6, order = 1, molecules = 30, T0 = 300, title = "Reaction rate
|
|
73
|
+
function KineticsLab({ EaKJ = 50, kRef = .6, order = 1, molecules = 30, T0 = 300, title = "Reaction rate: temperature, activation energy & collisions", prompt = "Molecules must collide with enough energy (≥ Eₐ) to react. Heat them up or lower Eₐ with a catalyst and watch many more collisions succeed.", objectives = [
|
|
74
74
|
"Explain rate by the collision model: enough-energy collisions react",
|
|
75
75
|
"See temperature widen the energy spread so more molecules clear Eₐ",
|
|
76
76
|
"Use Arrhenius k = A·e^(−Eₐ/RT); see a catalyst lower Eₐ, not ΔH"
|
|
@@ -417,7 +417,7 @@ function KineticsLab({ EaKJ = 50, kRef = .6, order = 1, molecules = 30, T0 = 300
|
|
|
417
417
|
children: ["Only collisions with energy ≥ Eₐ react. ", catalyst ? /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsx("strong", {
|
|
418
418
|
style: { color: B_COL },
|
|
419
419
|
children: "Catalyst on"
|
|
420
|
-
}), "
|
|
420
|
+
}), ", Eₐ is lowered, so far more collisions succeed (ΔH is unchanged)."] }) : /* @__PURE__ */ jsx(Fragment$1, { children: "Heat the vessel and the energy spread widens, pushing more molecules past Eₐ." })]
|
|
421
421
|
})]
|
|
422
422
|
})] });
|
|
423
423
|
const footer = /* @__PURE__ */ jsx(ChallengeCard, {
|
|
@@ -9,12 +9,12 @@ import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
|
|
|
9
9
|
|
|
10
10
|
//#region src/chem/periodic-trends/preset.tsx
|
|
11
11
|
/**
|
|
12
|
-
* PeriodicTrendsLab
|
|
12
|
+
* PeriodicTrendsLab, the periodic table as a heatmap, so a trend you usually have to
|
|
13
13
|
* memorise becomes a colour gradient you can read at a glance. Pick a property
|
|
14
14
|
* (atomic radius, ionisation energy, electronegativity) and every tile recolours;
|
|
15
15
|
* hover an element for its value. The gradients make the rules obvious: radius grows
|
|
16
16
|
* DOWN and LEFT (toward caesium); ionisation energy and electronegativity grow UP and
|
|
17
|
-
* RIGHT (toward fluorine). Periods 1–5 (H–Xe); a curated dataset, not a formula
|
|
17
|
+
* RIGHT (toward fluorine). Periods 1–5 (H–Xe); a curated dataset, not a formula ,
|
|
18
18
|
* which property is shown (and any highlighted element) is authorable, and a
|
|
19
19
|
* predict-first question ships with it.
|
|
20
20
|
*/
|
|
@@ -602,7 +602,7 @@ const CHALLENGE = [{
|
|
|
602
602
|
}
|
|
603
603
|
],
|
|
604
604
|
answer: "down",
|
|
605
|
-
explain: "More protons pull the same shell of electrons in tighter, so atoms shrink across a period
|
|
605
|
+
explain: "More protons pull the same shell of electrons in tighter, so atoms shrink across a period, even as electrons are added."
|
|
606
606
|
}, {
|
|
607
607
|
id: "ie",
|
|
608
608
|
prompt: "Ionisation energy is generally highest…",
|
|
@@ -623,7 +623,7 @@ const CHALLENGE = [{
|
|
|
623
623
|
answer: "tr",
|
|
624
624
|
explain: "Small, tightly-held atoms top-right cling hardest to their electrons, so they need the most energy to ionise."
|
|
625
625
|
}];
|
|
626
|
-
function PeriodicTrendsLab({ property: prop0 = "radius", highlight, title = "Periodic trends
|
|
626
|
+
function PeriodicTrendsLab({ property: prop0 = "radius", highlight, title = "Periodic trends: read the table as a heatmap", prompt = "Colour every element by a property and the trend appears as a gradient. Hover an element for its value; switch the property to see the pattern flip.", objectives = [
|
|
627
627
|
"Read periodic trends as colour gradients across the table",
|
|
628
628
|
"Atomic radius grows down a group and shrinks across a period",
|
|
629
629
|
"Ionisation energy & electronegativity grow up and to the right"
|
|
@@ -664,7 +664,7 @@ function PeriodicTrendsLab({ property: prop0 = "radius", highlight, title = "Per
|
|
|
664
664
|
children: [
|
|
665
665
|
cfg.label,
|
|
666
666
|
cfg.unit ? ` (${cfg.unit})` : "",
|
|
667
|
-
"
|
|
667
|
+
", ",
|
|
668
668
|
cfg.trend
|
|
669
669
|
]
|
|
670
670
|
}),
|
|
@@ -767,7 +767,7 @@ function PeriodicTrendsLab({ property: prop0 = "radius", highlight, title = "Per
|
|
|
767
767
|
children: [
|
|
768
768
|
cfg.label,
|
|
769
769
|
": ",
|
|
770
|
-
sel[cfg.idx] != null ? `${sel[cfg.idx]} ${cfg.unit}` : "
|
|
770
|
+
sel[cfg.idx] != null ? `${sel[cfg.idx]} ${cfg.unit}` : ", "
|
|
771
771
|
]
|
|
772
772
|
})]
|
|
773
773
|
}) : /* @__PURE__ */ jsxs("span", {
|
|
@@ -794,7 +794,7 @@ function PeriodicTrendsLab({ property: prop0 = "radius", highlight, title = "Per
|
|
|
794
794
|
style: { color: "var(--stage-fg)" },
|
|
795
795
|
children: cfg.trend
|
|
796
796
|
}),
|
|
797
|
-
"
|
|
797
|
+
", ",
|
|
798
798
|
cfg.corner,
|
|
799
799
|
". Switch the property and watch the gradient flip direction."
|
|
800
800
|
]
|
|
@@ -10,9 +10,9 @@ import { Circle, Label, Segment, Stage, useFrameLoop, useInView } from "@classyt
|
|
|
10
10
|
|
|
11
11
|
//#region src/chem/reaction-lab.tsx
|
|
12
12
|
/**
|
|
13
|
-
* ReactionLab
|
|
13
|
+
* ReactionLab, a synthesis reaction as moving atoms: A + B collide and bond into
|
|
14
14
|
* A–B. Raise the temperature and they collide harder/more often (kinetics); press
|
|
15
|
-
* React to run it. Atoms are conserved
|
|
15
|
+
* React to run it. Atoms are conserved, none created or destroyed, just
|
|
16
16
|
* rearranged.
|
|
17
17
|
*
|
|
18
18
|
* Now on the @classytic/stage engine (SVG, accessible, themed).
|
|
@@ -126,7 +126,7 @@ function ReactionLab({ a = "A", b = "B", title = "A + B → A–B", height = 300
|
|
|
126
126
|
})] });
|
|
127
127
|
return /* @__PURE__ */ jsx(LabFrame, {
|
|
128
128
|
title,
|
|
129
|
-
prompt: "Atoms rearrange
|
|
129
|
+
prompt: "Atoms rearrange, none are created or destroyed. Raise the temperature to react faster.",
|
|
130
130
|
aside: /* @__PURE__ */ jsx(Callout, {
|
|
131
131
|
tone: "result",
|
|
132
132
|
children: bonded ? "product" : playing ? "reacting…" : "reactants"
|
|
@@ -10,7 +10,7 @@ import { Label, Polyline, Segment, Stage } from "@classytic/stage";
|
|
|
10
10
|
|
|
11
11
|
//#region src/chem/reaction-profile.tsx
|
|
12
12
|
/**
|
|
13
|
-
* ReactionProfile
|
|
13
|
+
* ReactionProfile, an energy vs. reaction-coordinate diagram.
|
|
14
14
|
*
|
|
15
15
|
* Reactants plateau → activation-energy hump (transition state) → products
|
|
16
16
|
* plateau. Tune ΔH (exothermic vs endothermic) and the activation energy Eₐ; flip
|
|
@@ -38,7 +38,7 @@ function sample(f) {
|
|
|
38
38
|
}
|
|
39
39
|
return pts;
|
|
40
40
|
}
|
|
41
|
-
/** The predict/classify activity
|
|
41
|
+
/** The predict/classify activity, read straight off the diagram the learner just tuned. */
|
|
42
42
|
const CHALLENGE = [{
|
|
43
43
|
id: "type",
|
|
44
44
|
prompt: "When the products end up LOWER in energy than the reactants, the reaction is…",
|
|
@@ -69,7 +69,7 @@ const CHALLENGE = [{
|
|
|
69
69
|
}
|
|
70
70
|
],
|
|
71
71
|
answer: "ea",
|
|
72
|
-
explain: "The reactant and product levels are unchanged
|
|
72
|
+
explain: "The reactant and product levels are unchanged, only the hump (Eₐ) drops, so ΔH is the same."
|
|
73
73
|
}];
|
|
74
74
|
function ReactionProfile({ deltaH, activationEnergy, catalyst: catalystInit = false, title = "Reaction energy profile", height = 320 } = {}) {
|
|
75
75
|
const [dH, setDH] = useState(clamp(num(deltaH, -40), -80, 80));
|
|
@@ -252,7 +252,7 @@ function ReactionProfile({ deltaH, activationEnergy, catalyst: catalystInit = fa
|
|
|
252
252
|
] });
|
|
253
253
|
return /* @__PURE__ */ jsx(LabFrame, {
|
|
254
254
|
title,
|
|
255
|
-
prompt: "Tune ΔH and the activation energy. A catalyst lowers the hump (green)
|
|
255
|
+
prompt: "Tune ΔH and the activation energy. A catalyst lowers the hump (green), a faster path, same ΔH.",
|
|
256
256
|
aside: /* @__PURE__ */ jsx(Callout, {
|
|
257
257
|
tone: "result",
|
|
258
258
|
children: /* @__PURE__ */ jsxs("span", {
|
|
@@ -11,11 +11,11 @@ import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
|
|
|
11
11
|
|
|
12
12
|
//#region src/chem/solution/dilution.tsx
|
|
13
13
|
/**
|
|
14
|
-
* DilutionLab
|
|
14
|
+
* DilutionLab, C₁V₁ = C₂V₂ is just: the dots don't leave.
|
|
15
15
|
*
|
|
16
16
|
* Take an aliquot of stock (V₁) and dilute it to a final volume (V₂). Two beakers
|
|
17
|
-
* show the SAME solute dots
|
|
18
|
-
* spread through the larger volume on the right
|
|
17
|
+
* show the SAME solute dots, concentrated in the small aliquot on the left,
|
|
18
|
+
* spread through the larger volume on the right, so the conserved quantity
|
|
19
19
|
* (moles = C·V) is SEEN, not memorized: same dots, bigger box, paler colour, lower
|
|
20
20
|
* C. Composes the shared SolutionField (single source of truth for the dots).
|
|
21
21
|
*
|
|
@@ -41,7 +41,7 @@ const DILUTION_CHALLENGE = [{
|
|
|
41
41
|
}
|
|
42
42
|
],
|
|
43
43
|
answer: "moles",
|
|
44
|
-
explain: "Adding water never removes solute
|
|
44
|
+
explain: "Adding water never removes solute, n = C·V is conserved, which is exactly C₁V₁ = C₂V₂."
|
|
45
45
|
}, {
|
|
46
46
|
id: "doubleV",
|
|
47
47
|
prompt: "Keep the same aliquot but DOUBLE the final volume V₂. The final concentration C₂…",
|
|
@@ -60,9 +60,9 @@ const DILUTION_CHALLENGE = [{
|
|
|
60
60
|
}
|
|
61
61
|
],
|
|
62
62
|
answer: "halves",
|
|
63
|
-
explain: "C₂ = n/V₂ with n fixed
|
|
63
|
+
explain: "C₂ = n/V₂ with n fixed, twice the volume means half the concentration."
|
|
64
64
|
}];
|
|
65
|
-
function DilutionLab({ stockConcentration = 2, aliquotVolume = .25, finalVolume = 1, maxMolarity = 4, hue = 200, title = "Dilution
|
|
65
|
+
function DilutionLab({ stockConcentration = 2, aliquotVolume = .25, finalVolume = 1, maxMolarity = 4, hue = 200, title = "Dilution: the dots don’t leave", prompt = "Take an aliquot of stock, add water to the final volume. Same dots, bigger box → lower concentration.", height = 180, objectives }) {
|
|
66
66
|
const c1 = clamp(stockConcentration, .5, maxMolarity);
|
|
67
67
|
const [v1, setV1] = useState(clamp(aliquotVolume, .1, .5));
|
|
68
68
|
const [v2, setV2] = useState(clamp(finalVolume, .5, 1.5));
|
|
@@ -6,9 +6,9 @@ interface SolutionFieldProps {
|
|
|
6
6
|
dots: number;
|
|
7
7
|
/** Liquid's share of the box width, 0..1 (represents volume). */
|
|
8
8
|
fill: number;
|
|
9
|
-
/** Density tint 0..1 (e.g. molarity / maxMolarity)
|
|
9
|
+
/** Density tint 0..1 (e.g. molarity / maxMolarity), deepens the colour. */
|
|
10
10
|
tint: number;
|
|
11
|
-
/** Solute hue in degrees (HSL)
|
|
11
|
+
/** Solute hue in degrees (HSL), encodes the species; default teal. */
|
|
12
12
|
hue?: number;
|
|
13
13
|
height?: number;
|
|
14
14
|
/** Drag a fixed-size probe to count dots in a sub-region. */
|
|
@@ -8,13 +8,13 @@ import { CanvasLayer, useInView } from "@classytic/stage";
|
|
|
8
8
|
|
|
9
9
|
//#region src/chem/solution/field.tsx
|
|
10
10
|
/**
|
|
11
|
-
* SolutionField
|
|
11
|
+
* SolutionField, the SHARED "solute dots in a solution box" primitive (single
|
|
12
12
|
* source of truth for the concentration family). Both SolutionBoxLab and
|
|
13
13
|
* DilutionLab compose it, so the dot-field, density tint, Brownian jitter and the
|
|
14
14
|
* draggable probe live in exactly ONE place.
|
|
15
15
|
*
|
|
16
16
|
* GENERIC on purpose: it takes a dot COUNT + a fill fraction (the liquid's share
|
|
17
|
-
* of the box = volume) + a tint 0..1
|
|
17
|
+
* of the box = volume) + a tint 0..1, the chemistry (moles→dots, M→tint) is the
|
|
18
18
|
* lab's job, not the field's. Dots hold fixed fractional positions so growing the
|
|
19
19
|
* box spreads the SAME dots apart (dilution = spreading, never removing). SVG-free
|
|
20
20
|
* CanvasLayer; deterministic seed (no Math.random at render) so SSR == client;
|
|
@@ -10,20 +10,20 @@ import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
|
|
|
10
10
|
|
|
11
11
|
//#region src/chem/solution/solution-box.tsx
|
|
12
12
|
/**
|
|
13
|
-
* SolutionBoxLab
|
|
13
|
+
* SolutionBoxLab, molarity is a CROWD: particles per litre, seen.
|
|
14
14
|
*
|
|
15
15
|
* Solute shown as discrete dots in a transparent box. Add solute (more dots =
|
|
16
16
|
* more moles, the numerator) or add water (the box widens so the SAME dots spread
|
|
17
|
-
* apart, the denominator)
|
|
17
|
+
* apart, the denominator), and M = n/V is read off as both a number AND the
|
|
18
18
|
* colour intensity. A draggable probe counts dots in a fixed region, proving
|
|
19
19
|
* molarity is a LOCAL density, not a whole-apparatus label. Composes the shared
|
|
20
20
|
* SolutionField (single source of truth for the dot engine).
|
|
21
21
|
*
|
|
22
22
|
* The unit-bridging algebra (mol↔g via molar mass, mol↔particles via Nₐ) belongs
|
|
23
|
-
* in a paired MathDerivation
|
|
23
|
+
* in a paired MathDerivation, this lab only makes density-vs-amount felt.
|
|
24
24
|
*/
|
|
25
25
|
const DOTS_PER_MOL = 200;
|
|
26
|
-
/** Predict how M = n/V responds to changing the numerator vs the denominator
|
|
26
|
+
/** Predict how M = n/V responds to changing the numerator vs the denominator, the core molarity misconception. */
|
|
27
27
|
const SOLUTION_CHALLENGE = [{
|
|
28
28
|
id: "add-water",
|
|
29
29
|
prompt: "Add water (more volume, same solute). The molarity M = n/V…",
|
|
@@ -42,7 +42,7 @@ const SOLUTION_CHALLENGE = [{
|
|
|
42
42
|
}
|
|
43
43
|
],
|
|
44
44
|
answer: "falls",
|
|
45
|
-
explain: "The same dots spread through a bigger box
|
|
45
|
+
explain: "The same dots spread through a bigger box, n is fixed, V grows, so the density n/V drops."
|
|
46
46
|
}, {
|
|
47
47
|
id: "add-solute",
|
|
48
48
|
prompt: "Add more solute at the same volume. The molarity…",
|
|
@@ -61,9 +61,9 @@ const SOLUTION_CHALLENGE = [{
|
|
|
61
61
|
}
|
|
62
62
|
],
|
|
63
63
|
answer: "rises",
|
|
64
|
-
explain: "More dots in the same box
|
|
64
|
+
explain: "More dots in the same box, n grows, V is fixed, so n/V climbs."
|
|
65
65
|
}];
|
|
66
|
-
function SolutionBoxLab({ moles = .5, volume = .5, maxMolarity = 4, hue = 178, showProbe = true, title = "Molarity is a crowd
|
|
66
|
+
function SolutionBoxLab({ moles = .5, volume = .5, maxMolarity = 4, hue = 178, showProbe = true, title = "Molarity is a crowd: particles per litre", prompt = "Add solute (more dots) or add water (same dots, bigger box). M = n / V is the dot density.", height = 230, objectives }) {
|
|
67
67
|
const [n, setN] = useState(clamp(moles, .1, 1));
|
|
68
68
|
const [v, setV] = useState(clamp(volume, .2, 1));
|
|
69
69
|
const M = n / v;
|
|
@@ -9,13 +9,13 @@ import { solveStoichiometry } from "@classytic/stage/chem";
|
|
|
9
9
|
|
|
10
10
|
//#region src/chem/stoichiometry/preset.tsx
|
|
11
11
|
/**
|
|
12
|
-
* StoichiometryLab
|
|
12
|
+
* StoichiometryLab, the limiting reagent, seen as a recipe. A balanced reaction is
|
|
13
13
|
* a recipe (2 H₂ + O₂ → 2 H₂O = "2 hydrogens and 1 oxygen make 2 waters"); given how
|
|
14
14
|
* much of each reactant you have, the one that runs out first caps how much product
|
|
15
15
|
* you can make, and the rest is left over.
|
|
16
16
|
*
|
|
17
17
|
* Each reactant is a tray of molecule tokens: the part CONSUMED is solid, the
|
|
18
|
-
* LEFTOVER fades out
|
|
18
|
+
* LEFTOVER fades out, so the limiting reagent is the tray that empties completely
|
|
19
19
|
* (highlighted), and the excess shows as faded tokens. The product tray fills with
|
|
20
20
|
* what's formed. Backed by `solveStoichiometry` (@classytic/stage/chem): extent,
|
|
21
21
|
* limiting reagent, product moles/grams and leftovers. Drag the amounts, pick a
|
|
@@ -131,14 +131,14 @@ const STOICH_CHALLENGE = [{
|
|
|
131
131
|
}
|
|
132
132
|
],
|
|
133
133
|
answer: "runsout",
|
|
134
|
-
explain: "Compare moles ÷ coefficient for each reactant
|
|
134
|
+
explain: "Compare moles ÷ coefficient for each reactant, the smallest is the limiting one. Raw moles or the coefficient alone can mislead."
|
|
135
135
|
}, {
|
|
136
136
|
id: "excess",
|
|
137
137
|
prompt: "Adding MORE of the reactant that is already in excess changes the product made by…",
|
|
138
138
|
choices: [
|
|
139
139
|
{
|
|
140
140
|
value: "none",
|
|
141
|
-
label: "nothing
|
|
141
|
+
label: "nothing: it just piles up as leftover"
|
|
142
142
|
},
|
|
143
143
|
{
|
|
144
144
|
value: "more",
|
|
@@ -155,7 +155,7 @@ const STOICH_CHALLENGE = [{
|
|
|
155
155
|
const co = (n) => n === 1 ? "" : `${n} `;
|
|
156
156
|
const eqn = (rx) => `${rx.reactants.map((s) => co(s.coeff) + s.name).join(" + ")} → ${rx.products.map((s) => co(s.coeff) + s.name).join(" + ")}`;
|
|
157
157
|
const fmt = (n) => Math.abs(n - Math.round(n)) < 1e-6 ? Math.round(n).toString() : n.toFixed(2);
|
|
158
|
-
function StoichiometryLab({ reaction = "water", amounts: amounts0, reactants: customR, products: customP, title = "Stoichiometry
|
|
158
|
+
function StoichiometryLab({ reaction = "water", amounts: amounts0, reactants: customR, products: customP, title = "Stoichiometry: the limiting reagent", prompt = "A balanced equation is a recipe. Whichever reactant runs out first limits how much product you can make, the rest is left over. Drag the amounts and watch.", objectives = [
|
|
159
159
|
"Read a balanced equation as a mole ratio (a recipe)",
|
|
160
160
|
"Find the limiting reagent: the one that runs out first (smallest moles ÷ coeff)",
|
|
161
161
|
"Work out the product formed and the reactant left in excess"
|
|
@@ -10,7 +10,7 @@ import { pHAt, titrationCurve } from "@classytic/stage/chem";
|
|
|
10
10
|
|
|
11
11
|
//#region src/chem/titration/preset.tsx
|
|
12
12
|
/**
|
|
13
|
-
* TitrationLab
|
|
13
|
+
* TitrationLab, add base to an acid drop by drop and watch the pH curve build, on
|
|
14
14
|
* the shared `@classytic/stage/chem` acid–base kernel (pH solved exactly from the
|
|
15
15
|
* charge balance at every volume).
|
|
16
16
|
*
|
|
@@ -19,7 +19,7 @@ import { pHAt, titrationCurve } from "@classytic/stage/chem";
|
|
|
19
19
|
* signature shape: a gentle start, then for a WEAK acid a flat BUFFER region whose
|
|
20
20
|
* midpoint sits at pH = pKa, a steep jump through the equivalence point, and a
|
|
21
21
|
* levelling-off in excess base. A strong acid skips the buffer and crosses pH 7 at
|
|
22
|
-
* equivalence; a weak acid's equivalence point is basic (pH > 7). Interactive
|
|
22
|
+
* equivalence; a weak acid's equivalence point is basic (pH > 7). Interactive, drag
|
|
23
23
|
* the volume, no simulation loop.
|
|
24
24
|
*/
|
|
25
25
|
const W = 720, H = 400;
|
|
@@ -64,7 +64,7 @@ const TITRATION_CHALLENGE = [{
|
|
|
64
64
|
answer: "basic",
|
|
65
65
|
explain: "All acid is now its conjugate base, which hydrolyses water to give pH > 7. (A strong acid would cross pH 7.)"
|
|
66
66
|
}];
|
|
67
|
-
function TitrationLab({ analyte: analyte0 = "weak-acid", concAcid = .1, volAcidMl = 25, concBase = .1, pKa: pKa0 = 4.76, title = "Acid–base titration
|
|
67
|
+
function TitrationLab({ analyte: analyte0 = "weak-acid", concAcid = .1, volAcidMl = 25, concBase = .1, pKa: pKa0 = 4.76, title = "Acid–base titration: build the pH curve", prompt = "Drip strong base into the acid and track the pH. Watch the buffer region, the steep jump at the equivalence point, and the indicator flip pink.", objectives = [
|
|
68
68
|
"Read a titration curve: start, buffer, equivalence jump, excess base",
|
|
69
69
|
"For a weak acid, see the half-equivalence pH equals the pKa",
|
|
70
70
|
"See the equivalence pH is 7 for a strong acid but >7 for a weak acid"
|
|
@@ -178,7 +178,7 @@ function TitrationLab({ analyte: analyte0 = "weak-acid", concAcid = .1, volAcidM
|
|
|
178
178
|
textAnchor: "middle",
|
|
179
179
|
fontSize: 11,
|
|
180
180
|
fill: "var(--stage-muted)",
|
|
181
|
-
children: pink > .5 ? "pink
|
|
181
|
+
children: pink > .5 ? "pink, past end point" : "colourless"
|
|
182
182
|
}),
|
|
183
183
|
/* @__PURE__ */ jsx("line", {
|
|
184
184
|
x1: GX0,
|
|
@@ -349,7 +349,7 @@ function TitrationLab({ analyte: analyte0 = "weak-acid", concAcid = .1, volAcidM
|
|
|
349
349
|
}), /* @__PURE__ */ jsxs("span", {
|
|
350
350
|
style: { color: "var(--stage-muted)" },
|
|
351
351
|
children: [
|
|
352
|
-
"In the buffer region the pH barely moves
|
|
352
|
+
"In the buffer region the pH barely moves, at the half-equivalence point [A⁻] = [HA] so ",
|
|
353
353
|
/* @__PURE__ */ jsxs("strong", {
|
|
354
354
|
style: { color: "var(--stage-fg)" },
|
|
355
355
|
children: ["pH = pKa = ", pKa.toFixed(2)]
|
|
@@ -9,10 +9,10 @@ import { Scene, registerAsset } from "@classytic/stage";
|
|
|
9
9
|
|
|
10
10
|
//#region src/circuits/ac-dc/preset.tsx
|
|
11
11
|
/**
|
|
12
|
-
* AcDcLab
|
|
12
|
+
* AcDcLab, "AC or DC?", now the STANDARD data-driven way: a SceneDoc with one
|
|
13
13
|
* `wave` sim (meta.sims) and one `ac-dc` asset that reads the sim live via simBind.
|
|
14
14
|
* `<Scene>` steps the sim each frame and the pure resolver re-evaluates, so the
|
|
15
|
-
* whole lab is data
|
|
15
|
+
* whole lab is data, the glowing lamp, flowing electrons, water-pipe analogy and
|
|
16
16
|
* live scope are all one sim → three synced skins (see ./asset). Controls write the
|
|
17
17
|
* sim's params; the runtime merges them without restarting the wave (time persists).
|
|
18
18
|
*/
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import { BrownoutLab, BrownoutProps } from "./preset.mjs";
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { LabAskSpec } from "../../kit/ask.mjs";
|
|
2
|
+
import { ReactNode } from "react";
|
|
3
|
+
|
|
4
|
+
//#region src/circuits/brownout/preset.d.ts
|
|
5
|
+
interface BrownoutProps {
|
|
6
|
+
vth?: number;
|
|
7
|
+
vmax?: number;
|
|
8
|
+
title?: string;
|
|
9
|
+
prompt?: string;
|
|
10
|
+
ask?: LabAskSpec;
|
|
11
|
+
activity?: string;
|
|
12
|
+
}
|
|
13
|
+
declare function BrownoutLab({
|
|
14
|
+
vth,
|
|
15
|
+
vmax,
|
|
16
|
+
title,
|
|
17
|
+
prompt,
|
|
18
|
+
ask,
|
|
19
|
+
activity
|
|
20
|
+
}?: BrownoutProps): ReactNode;
|
|
21
|
+
//#endregion
|
|
22
|
+
export { BrownoutLab, BrownoutProps };
|