@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
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
import { clamp } from "../../core/util.mjs";
|
|
4
4
|
import { CheckButton, Chip, Slider } from "../../kit/controls.mjs";
|
|
5
5
|
import { Callout, ControlBar, Field, LabFrame, LiveRegion } from "../../kit/frame.mjs";
|
|
6
|
+
import { ChallengeCard, useChallenge, useCheckpoint } from "../../kit/pedagogy.mjs";
|
|
6
7
|
import { useFrameTick } from "../../kit/anim.mjs";
|
|
7
8
|
import { PlayWrap, usePlayGate } from "../../kit/play.mjs";
|
|
8
9
|
import { useRef, useState } from "react";
|
|
@@ -11,24 +12,49 @@ import { Circle, Dot, Label, Segment, Stage, Vector } from "@classytic/stage";
|
|
|
11
12
|
|
|
12
13
|
//#region src/physics/circular-motion/preset.tsx
|
|
13
14
|
/**
|
|
14
|
-
* CircularMotionLab
|
|
15
|
+
* CircularMotionLab, "Whirl & cut", where centripetal force points and where the
|
|
15
16
|
* ball REALLY goes when you let go.
|
|
16
17
|
*
|
|
17
18
|
* A ball on a string whirls at constant speed. The velocity arrow is always
|
|
18
|
-
* TANGENT; the tension (centripetal force F = mv²/r) always points to the centre
|
|
19
|
+
* TANGENT; the tension (centripetal force F = mv²/r) always points to the centre ,
|
|
19
20
|
* it changes the direction of v, never its size. Then CUT THE STRING: the ball
|
|
20
|
-
* flies off along the tangent in a straight line
|
|
21
|
+
* flies off along the tangent in a straight line, NOT radially outward, the
|
|
21
22
|
* single most common misconception. Tune v, r, m and read F live (hammer throw,
|
|
22
23
|
* a car cornering, the spin cycle).
|
|
23
24
|
*
|
|
24
25
|
* Uses the ambient PlayWrap gate (pause to study the vectors). Tokenized SVG.
|
|
25
26
|
*/
|
|
26
|
-
|
|
27
|
+
const PREDICT = [{
|
|
28
|
+
id: "release",
|
|
29
|
+
prompt: "You’re whirling a ball on a string in a circle. At the instant you LET GO, which way does the ball fly?",
|
|
30
|
+
choices: [
|
|
31
|
+
{
|
|
32
|
+
value: "tangent",
|
|
33
|
+
label: "straight, along the tangent (the way it was moving)"
|
|
34
|
+
},
|
|
35
|
+
{
|
|
36
|
+
value: "radial",
|
|
37
|
+
label: "straight outward, away from the centre"
|
|
38
|
+
},
|
|
39
|
+
{
|
|
40
|
+
value: "curve",
|
|
41
|
+
label: "it keeps curving for a bit"
|
|
42
|
+
}
|
|
43
|
+
],
|
|
44
|
+
answer: "tangent",
|
|
45
|
+
explain: "No force acts after release, so by Newton’s first law it travels in a straight line along its velocity — the tangent. It does NOT fly radially outward (that’s the common misconception) and does not keep curving."
|
|
46
|
+
}];
|
|
47
|
+
function CircularMotionLab({ speed = 6, radius = 3, mass = 1, title = "Whirl & cut: where does it really go?", prompt = "The string’s tension is the centripetal force F = mv²/r, always toward the centre, bending the path without changing the speed. Cut the string and the ball leaves along the tangent, not outward.", objectives, controlConfig }) {
|
|
27
48
|
const [v, setV] = useState(speed);
|
|
28
49
|
const [r, setR] = useState(radius);
|
|
29
50
|
const [m, setM] = useState(mass);
|
|
30
51
|
const [cut, setCut] = useState(false);
|
|
31
52
|
const gate = usePlayGate();
|
|
53
|
+
const ch = useChallenge(PREDICT);
|
|
54
|
+
useCheckpoint({
|
|
55
|
+
solved: ch.allCorrect,
|
|
56
|
+
activity: "circular-motion-predict"
|
|
57
|
+
});
|
|
32
58
|
const ang = useRef(0);
|
|
33
59
|
const fly = useRef(null);
|
|
34
60
|
const omega = v / r;
|
|
@@ -231,7 +257,7 @@ function CircularMotionLab({ speed = 6, radius = 3, mass = 1, title = "Whirl & c
|
|
|
231
257
|
" points to the centre. Cut the string → no inward pull → straight-line tangent flight (Newton’s 1st law). Hammer throw, a car cornering, the spin cycle."
|
|
232
258
|
]
|
|
233
259
|
}),
|
|
234
|
-
/* @__PURE__ */ jsx(LiveRegion, { children: cut ? "String cut
|
|
260
|
+
/* @__PURE__ */ jsx(LiveRegion, { children: cut ? "String cut, the ball travels in a straight line along the tangent." : `Centripetal force ${F.toFixed(0)} newtons toward the centre.` })
|
|
235
261
|
]
|
|
236
262
|
}),
|
|
237
263
|
controls: /* @__PURE__ */ jsxs(ControlBar, { children: [
|
|
@@ -284,6 +310,11 @@ function CircularMotionLab({ speed = 6, radius = 3, mass = 1, title = "Whirl & c
|
|
|
284
310
|
})
|
|
285
311
|
})
|
|
286
312
|
] }),
|
|
313
|
+
footer: /* @__PURE__ */ jsx(ChallengeCard, {
|
|
314
|
+
questions: PREDICT,
|
|
315
|
+
state: ch,
|
|
316
|
+
title: "Predict first"
|
|
317
|
+
}),
|
|
287
318
|
controlConfig,
|
|
288
319
|
children: figure
|
|
289
320
|
});
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
import { CheckButton, Slider, StatusPill } from "../../kit/controls.mjs";
|
|
4
4
|
import { ControlBar, Field, LabFrame, LiveRegion, MeterBar } from "../../kit/frame.mjs";
|
|
5
|
-
import { useCheckpoint } from "../../kit/pedagogy.mjs";
|
|
5
|
+
import { ChallengeCard, useChallenge, useCheckpoint } from "../../kit/pedagogy.mjs";
|
|
6
6
|
import { useFrameTick, useReducedMotion } from "../../kit/anim.mjs";
|
|
7
7
|
import { useRef, useState } from "react";
|
|
8
8
|
import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
|
|
@@ -10,19 +10,43 @@ import { Dot, Label, Polygon, Segment, Stage, Vector, useInView } from "@classyt
|
|
|
10
10
|
|
|
11
11
|
//#region src/physics/collision-track/preset.tsx
|
|
12
12
|
/**
|
|
13
|
-
* CollisionTrackLab
|
|
13
|
+
* CollisionTrackLab, "Sticky or Bouncy?", momentum always survives, KE doesn't.
|
|
14
14
|
*
|
|
15
15
|
* Two carts collide on a frictionless track. ONE elasticity slider morphs
|
|
16
16
|
* continuously from perfectly inelastic (e=0, stick + KE drops) to perfectly
|
|
17
17
|
* elastic (e=1, bounce, KE held). A momentum bar stays FULL through the collision
|
|
18
18
|
* while the KE bar visibly leaks when e<1, and a constant-velocity centre-of-mass
|
|
19
|
-
* marker sails dead-straight through the impact
|
|
19
|
+
* marker sails dead-straight through the impact, the single-image proof that
|
|
20
20
|
* momentum is conserved no matter what. Kills the "momentum is lost" misconception.
|
|
21
21
|
*
|
|
22
22
|
* Tokenized SVG; time-dependent so the integrator lives here; honours reduced-motion.
|
|
23
23
|
*/
|
|
24
24
|
const CART_W = 1.8, X0 = -9, X1 = 9;
|
|
25
|
-
|
|
25
|
+
const PREDICT_Q = [{
|
|
26
|
+
id: "collision-track-conserved",
|
|
27
|
+
prompt: "These carts collide and BOUNCE apart (elastic, e = 1). After the crash, which is conserved — total momentum, total kinetic energy, both, or neither?",
|
|
28
|
+
choices: [
|
|
29
|
+
{
|
|
30
|
+
value: "momentum",
|
|
31
|
+
label: "momentum only"
|
|
32
|
+
},
|
|
33
|
+
{
|
|
34
|
+
value: "both",
|
|
35
|
+
label: "both"
|
|
36
|
+
},
|
|
37
|
+
{
|
|
38
|
+
value: "ke",
|
|
39
|
+
label: "kinetic energy only"
|
|
40
|
+
},
|
|
41
|
+
{
|
|
42
|
+
value: "neither",
|
|
43
|
+
label: "neither"
|
|
44
|
+
}
|
|
45
|
+
],
|
|
46
|
+
answer: "both",
|
|
47
|
+
explain: "Momentum is always conserved in a collision (no external force). In a perfectly elastic collision (e = 1) the carts bounce with no energy lost to heat or deformation, so kinetic energy is conserved too — hence both. Slide elasticity below 1 and the KE bar will start to leak."
|
|
48
|
+
}];
|
|
49
|
+
function CollisionTrackLab({ m1 = 1, m2 = 1, u1 = 4, u2 = -2, elasticity = 1, showCenterOfMass = true, title = "Sticky or Bouncy?: momentum always survives", prompt = "Set the elasticity, launch, and watch: the momentum bar stays full; the KE bar leaks when sticky.", objectives }) {
|
|
26
50
|
const [ma, setMa] = useState(m1);
|
|
27
51
|
const [mb, setMb] = useState(m2);
|
|
28
52
|
const [ua, setUa] = useState(u1);
|
|
@@ -36,8 +60,9 @@ function CollisionTrackLab({ m1 = 1, m2 = 1, u1 = 4, u2 = -2, elasticity = 1, sh
|
|
|
36
60
|
const startedRef = useRef(false);
|
|
37
61
|
const reduce = useReducedMotion();
|
|
38
62
|
const { ref: viewRef, inView } = useInView();
|
|
63
|
+
const ch = useChallenge(PREDICT_Q);
|
|
39
64
|
useCheckpoint({
|
|
40
|
-
solved: stopped,
|
|
65
|
+
solved: ch.allCorrect && stopped,
|
|
41
66
|
activity: "collision-track"
|
|
42
67
|
});
|
|
43
68
|
const M = ma + mb;
|
|
@@ -344,6 +369,11 @@ function CollisionTrackLab({ m1 = 1, m2 = 1, u1 = 4, u2 = -2, elasticity = 1, sh
|
|
|
344
369
|
})
|
|
345
370
|
})
|
|
346
371
|
] }),
|
|
372
|
+
footer: /* @__PURE__ */ jsx(ChallengeCard, {
|
|
373
|
+
questions: PREDICT_Q,
|
|
374
|
+
state: ch,
|
|
375
|
+
title: "Predict first"
|
|
376
|
+
}),
|
|
347
377
|
children: figure
|
|
348
378
|
});
|
|
349
379
|
}
|
|
@@ -12,9 +12,9 @@ interface EfficiencyProps {
|
|
|
12
12
|
/** Built-in device preset (ignored if `streams` is given). */
|
|
13
13
|
device?: 'incandescent' | 'led' | 'petrol-engine' | 'electric-motor' | 'power-station' | 'human';
|
|
14
14
|
deviceName?: string;
|
|
15
|
-
/** Energy supplied, J (default 100
|
|
15
|
+
/** Energy supplied, J (default 100, so shares read as percentages). */
|
|
16
16
|
inputJoules?: number;
|
|
17
|
-
/** Author your own breakdown
|
|
17
|
+
/** Author your own breakdown, overrides the preset entirely. */
|
|
18
18
|
streams?: EffStream[];
|
|
19
19
|
title?: string;
|
|
20
20
|
prompt?: string;
|
|
@@ -10,12 +10,12 @@ import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
|
|
|
10
10
|
|
|
11
11
|
//#region src/physics/efficiency/preset.tsx
|
|
12
12
|
/**
|
|
13
|
-
* EfficiencyLab
|
|
13
|
+
* EfficiencyLab, efficiency as the input→output RATIO you can see. Energy flows in
|
|
14
14
|
* on the left and splits into a USEFUL output stream and WASTED streams (usually
|
|
15
15
|
* heat), drawn as a Sankey: each ribbon's thickness is its share of the energy, so
|
|
16
16
|
* efficiency η = useful / input is literally the fraction of the flow that stays
|
|
17
17
|
* green. Compare an incandescent bulb (≈5%) with an LED (≈45%), a petrol engine
|
|
18
|
-
* (≈25%) with an electric motor (≈90%)
|
|
18
|
+
* (≈25%) with an electric motor (≈90%), and feel why "wasted as heat" matters.
|
|
19
19
|
*
|
|
20
20
|
* The device is AUTHORABLE: a creator declares the streams (label, share, useful or
|
|
21
21
|
* waste) so the same lab draws any energy-flow / efficiency diagram. Interactive
|
|
@@ -106,9 +106,9 @@ const ORDER = [
|
|
|
106
106
|
"power-station",
|
|
107
107
|
"human"
|
|
108
108
|
];
|
|
109
|
-
function EfficiencyLab({ device: device0 = "incandescent", deviceName, inputJoules = 100, streams: streamsProp, title = "Efficiency
|
|
109
|
+
function EfficiencyLab({ device: device0 = "incandescent", deviceName, inputJoules = 100, streams: streamsProp, title = "Efficiency: how much of the energy is useful?", prompt = "Energy in splits into useful output and wasted energy (mostly heat). Efficiency is the fraction that comes out useful: η = useful ÷ input. Compare the devices.", objectives = [
|
|
110
110
|
"Define efficiency as the input→output ratio η = useful energy ÷ total input",
|
|
111
|
-
"Read a Sankey diagram
|
|
111
|
+
"Read a Sankey diagram, ribbon thickness is energy share",
|
|
112
112
|
"Compare real devices and see where energy is wasted (heat)"
|
|
113
113
|
] } = {}) {
|
|
114
114
|
const [device, setDevice] = useState(device0);
|
|
@@ -319,7 +319,7 @@ function EfficiencyLab({ device: device0 = "incandescent", deviceName, inputJoul
|
|
|
319
319
|
style: { color: HEAT },
|
|
320
320
|
children: [(inputJoules - usefulJ).toFixed(0), " J"]
|
|
321
321
|
}),
|
|
322
|
-
" is wasted (mostly heat). Energy is conserved
|
|
322
|
+
" is wasted (mostly heat). Energy is conserved, efficiency is about how much ends up where you want it."
|
|
323
323
|
]
|
|
324
324
|
})]
|
|
325
325
|
})] }),
|
|
@@ -10,10 +10,10 @@ import { fieldAt, fieldLines } from "@classytic/stage/field";
|
|
|
10
10
|
|
|
11
11
|
//#region src/physics/electric-field/preset.tsx
|
|
12
12
|
/**
|
|
13
|
-
* ElectricFieldLab
|
|
13
|
+
* ElectricFieldLab, Coulomb's field you can see and probe, on the same
|
|
14
14
|
* @classytic/stage `field` kernel that draws magnetism (one kernel → both). Drag
|
|
15
15
|
* two charges (flip either +/−); field lines retrace live, flowing OUT of + into −.
|
|
16
|
-
* Drop the test charge anywhere and a force arrow F = qE appears
|
|
16
|
+
* Drop the test charge anywhere and a force arrow F = qE appears, toward + or away,
|
|
17
17
|
* depending on its sign. Interactive (recomputed on drag), not a timed sim.
|
|
18
18
|
*/
|
|
19
19
|
const VIEW = {
|
|
@@ -58,7 +58,7 @@ const POS = "var(--stage-danger, #e03131)";
|
|
|
58
58
|
const NEG = "var(--stage-accent, #3b82f6)";
|
|
59
59
|
const FORCE = "var(--stage-good)";
|
|
60
60
|
const mag = (v) => Math.hypot(v.x, v.y) || 1;
|
|
61
|
-
function ChargeFigure({ sources, lines,
|
|
61
|
+
function ChargeFigure({ sources, lines, test, testSign }) {
|
|
62
62
|
const c = useCoords();
|
|
63
63
|
const P = (v) => c.toPx(v.x, v.y);
|
|
64
64
|
const arrow = (a, b, key, color) => {
|
|
@@ -118,23 +118,6 @@ function ChargeFigure({ sources, lines, charges, test, testSign }) {
|
|
|
118
118
|
]
|
|
119
119
|
});
|
|
120
120
|
})(),
|
|
121
|
-
charges.map((ch, i) => {
|
|
122
|
-
const [x, y] = P(ch.at);
|
|
123
|
-
return /* @__PURE__ */ jsxs("g", { children: [/* @__PURE__ */ jsx("circle", {
|
|
124
|
-
cx: x,
|
|
125
|
-
cy: y,
|
|
126
|
-
r: 15,
|
|
127
|
-
fill: ch.q > 0 ? POS : NEG
|
|
128
|
-
}), /* @__PURE__ */ jsx("text", {
|
|
129
|
-
x,
|
|
130
|
-
y: y + 5,
|
|
131
|
-
textAnchor: "middle",
|
|
132
|
-
fontSize: 18,
|
|
133
|
-
fontWeight: 800,
|
|
134
|
-
fill: "white",
|
|
135
|
-
children: ch.q > 0 ? "+" : "−"
|
|
136
|
-
})] }, `c${i}`);
|
|
137
|
-
}),
|
|
138
121
|
(() => {
|
|
139
122
|
const [x, y] = P(test);
|
|
140
123
|
return /* @__PURE__ */ jsxs("g", {
|
|
@@ -159,7 +142,33 @@ function ChargeFigure({ sources, lines, charges, test, testSign }) {
|
|
|
159
142
|
})()
|
|
160
143
|
] });
|
|
161
144
|
}
|
|
162
|
-
|
|
145
|
+
/** The charge discs with their ± sign, drawn ON TOP so the drag handles never hide them. */
|
|
146
|
+
function ChargeSymbols({ charges }) {
|
|
147
|
+
const c = useCoords();
|
|
148
|
+
return /* @__PURE__ */ jsx("g", {
|
|
149
|
+
style: { pointerEvents: "none" },
|
|
150
|
+
children: charges.map((ch, i) => {
|
|
151
|
+
const [x, y] = c.toPx(ch.at.x, ch.at.y);
|
|
152
|
+
return /* @__PURE__ */ jsxs("g", { children: [/* @__PURE__ */ jsx("circle", {
|
|
153
|
+
cx: x,
|
|
154
|
+
cy: y,
|
|
155
|
+
r: 15,
|
|
156
|
+
fill: ch.q > 0 ? POS : NEG,
|
|
157
|
+
stroke: "var(--stage-bg)",
|
|
158
|
+
strokeWidth: 2
|
|
159
|
+
}), /* @__PURE__ */ jsx("text", {
|
|
160
|
+
x,
|
|
161
|
+
y: y + 5,
|
|
162
|
+
textAnchor: "middle",
|
|
163
|
+
fontSize: 18,
|
|
164
|
+
fontWeight: 800,
|
|
165
|
+
fill: "white",
|
|
166
|
+
children: ch.q > 0 ? "+" : "−"
|
|
167
|
+
})] }, i);
|
|
168
|
+
})
|
|
169
|
+
});
|
|
170
|
+
}
|
|
171
|
+
function ElectricFieldLab({ title = "Electric field: charges & the force you feel", prompt = "Drag the two charges and flip their signs; field lines flow out of + into −. Drop the test charge and watch the force F = qE.", objectives = [
|
|
163
172
|
"Read an electric field as field lines (out of +, into −)",
|
|
164
173
|
"See like charges repel, opposites attract",
|
|
165
174
|
"Feel the force on a test charge: F = qE"
|
|
@@ -215,7 +224,6 @@ function ElectricFieldLab({ title = "Electric field — charges & the force you
|
|
|
215
224
|
bounds: VIEW,
|
|
216
225
|
seed: .35
|
|
217
226
|
}), [sources]),
|
|
218
|
-
charges,
|
|
219
227
|
test,
|
|
220
228
|
testSign
|
|
221
229
|
}),
|
|
@@ -239,7 +247,8 @@ function ElectricFieldLab({ title = "Electric field — charges & the force you
|
|
|
239
247
|
color: FORCE,
|
|
240
248
|
ariaLabel: "test charge",
|
|
241
249
|
r: 8
|
|
242
|
-
})
|
|
250
|
+
}),
|
|
251
|
+
/* @__PURE__ */ jsx(ChargeSymbols, { charges })
|
|
243
252
|
]
|
|
244
253
|
});
|
|
245
254
|
return /* @__PURE__ */ jsx(LabFrame, {
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import { ElectricFluxLab, ElectricFluxProps } from "./preset.mjs";
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { LabAskSpec } from "../../kit/ask.mjs";
|
|
2
|
+
import { ReactNode } from "react";
|
|
3
|
+
|
|
4
|
+
//#region src/physics/electric-flux/preset.d.ts
|
|
5
|
+
interface ElectricFluxProps {
|
|
6
|
+
/** Field strength in vacuum (arbitrary units). */
|
|
7
|
+
field?: number;
|
|
8
|
+
/** Area (length of the flat window, in scene units). */
|
|
9
|
+
area?: number;
|
|
10
|
+
/** Initial angle between the area's normal and the field, in degrees. */
|
|
11
|
+
angleDeg?: number;
|
|
12
|
+
title?: string;
|
|
13
|
+
prompt?: string;
|
|
14
|
+
ask?: LabAskSpec;
|
|
15
|
+
height?: number;
|
|
16
|
+
activity?: string;
|
|
17
|
+
}
|
|
18
|
+
declare function ElectricFluxLab({
|
|
19
|
+
field,
|
|
20
|
+
area,
|
|
21
|
+
angleDeg,
|
|
22
|
+
title,
|
|
23
|
+
prompt,
|
|
24
|
+
ask,
|
|
25
|
+
height,
|
|
26
|
+
activity
|
|
27
|
+
}?: ElectricFluxProps): ReactNode;
|
|
28
|
+
//#endregion
|
|
29
|
+
export { ElectricFluxLab, ElectricFluxProps };
|
|
@@ -0,0 +1,264 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
import { Chip, Slider } from "../../kit/controls.mjs";
|
|
4
|
+
import { Callout, ControlBar, Field, LabFrame } from "../../kit/frame.mjs";
|
|
5
|
+
import { AngleArc } from "../../kit/diagram.mjs";
|
|
6
|
+
import { LabAsk } from "../../kit/ask.mjs";
|
|
7
|
+
import { useState } from "react";
|
|
8
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
9
|
+
import { Label, MovableDot, Segment, Stage, Vector } from "@classytic/stage";
|
|
10
|
+
|
|
11
|
+
//#region src/physics/electric-flux/preset.tsx
|
|
12
|
+
/**
|
|
13
|
+
* ElectricFluxLab, the concept of flux (Φ) made literal: flux is just HOW MANY
|
|
14
|
+
* field lines thread through your area. A uniform field points to the right as a
|
|
15
|
+
* set of evenly spaced lines (denser = stronger E). Drop a flat "area" into it and
|
|
16
|
+
* the lines that actually pass through it light up green; that count IS the flux.
|
|
17
|
+
*
|
|
18
|
+
* • rotate the area: edge-on to the field, nothing threads it (Φ = 0); face-on,
|
|
19
|
+
* the maximum threads it (Φ = E·A). In between, Φ = E·A·cosθ, where θ is the
|
|
20
|
+
* angle between the area's NORMAL and the field.
|
|
21
|
+
* • resize the area A: a bigger window catches more lines.
|
|
22
|
+
* • change the medium (permittivity εr): a dielectric weakens the field to
|
|
23
|
+
* E = E₀/εr, so there are fewer lines to thread, and Φ falls. This is the
|
|
24
|
+
* Gauss-law statement Φ = Q/(ε₀εr) seen as line-counting.
|
|
25
|
+
*
|
|
26
|
+
* Built from stage primitives; the analogy (lines through a hoop) is the point,
|
|
27
|
+
* not a timed simulation. Authorable via props + an optional checked question.
|
|
28
|
+
*/
|
|
29
|
+
const VIEW = {
|
|
30
|
+
xMin: -6,
|
|
31
|
+
xMax: 6,
|
|
32
|
+
yMin: -4,
|
|
33
|
+
yMax: 4
|
|
34
|
+
};
|
|
35
|
+
const C_THREAD = "var(--stage-good)";
|
|
36
|
+
const C_FAINT = "color-mix(in oklab, var(--stage-accent) 35%, transparent)";
|
|
37
|
+
const C_AREA = "var(--stage-accent-2)";
|
|
38
|
+
const C_NORMAL = "var(--stage-fg)";
|
|
39
|
+
const MEDIA = [
|
|
40
|
+
{
|
|
41
|
+
name: "vacuum",
|
|
42
|
+
er: 1
|
|
43
|
+
},
|
|
44
|
+
{
|
|
45
|
+
name: "glass",
|
|
46
|
+
er: 5
|
|
47
|
+
},
|
|
48
|
+
{
|
|
49
|
+
name: "water",
|
|
50
|
+
er: 80
|
|
51
|
+
}
|
|
52
|
+
];
|
|
53
|
+
const fmt$1 = (n) => Math.abs(n) < .05 ? "0" : n.toFixed(1);
|
|
54
|
+
function ElectricFluxLab({ field = 6, area = 3, angleDeg = 0, title = "Electric flux: how many lines thread the area", prompt = "Rotate the area and resize it. The lines that pass through light up: that count is the flux Φ = E·A·cosθ.", ask, height = 420, activity = "electric-flux" } = {}) {
|
|
55
|
+
const [E0, setE0] = useState(field);
|
|
56
|
+
const [A, setA] = useState(area);
|
|
57
|
+
const [theta, setTheta] = useState(angleDeg * Math.PI / 180);
|
|
58
|
+
const [er, setEr] = useState(1);
|
|
59
|
+
const Eeff = E0 / er;
|
|
60
|
+
const cos = Math.cos(theta);
|
|
61
|
+
const phi = Eeff * A * cos;
|
|
62
|
+
const deg = Math.round(theta * 180 / Math.PI);
|
|
63
|
+
const C = {
|
|
64
|
+
x: 0,
|
|
65
|
+
y: 0
|
|
66
|
+
};
|
|
67
|
+
const n = {
|
|
68
|
+
x: Math.cos(theta),
|
|
69
|
+
y: Math.sin(theta)
|
|
70
|
+
};
|
|
71
|
+
const dir = {
|
|
72
|
+
x: -Math.sin(theta),
|
|
73
|
+
y: Math.cos(theta)
|
|
74
|
+
};
|
|
75
|
+
const p1 = {
|
|
76
|
+
x: C.x + dir.x * A / 2,
|
|
77
|
+
y: C.y + dir.y * A / 2
|
|
78
|
+
};
|
|
79
|
+
const p2 = {
|
|
80
|
+
x: C.x - dir.x * A / 2,
|
|
81
|
+
y: C.y - dir.y * A / 2
|
|
82
|
+
};
|
|
83
|
+
const halfSpan = A / 2 * Math.abs(cos);
|
|
84
|
+
const nLines = Math.max(4, Math.min(40, Math.round(Eeff * 3)));
|
|
85
|
+
const y0 = VIEW.yMin + .4, y1 = VIEW.yMax - .4;
|
|
86
|
+
const ys = Array.from({ length: nLines }, (_, i) => y0 + (y1 - y0) * i / Math.max(1, nLines - 1));
|
|
87
|
+
const threads = ys.filter((y) => Math.abs(y - C.y) <= halfSpan + 1e-6).length;
|
|
88
|
+
const rotTip = {
|
|
89
|
+
x: C.x + n.x * 2.2,
|
|
90
|
+
y: C.y + n.y * 2.2
|
|
91
|
+
};
|
|
92
|
+
const figure = /* @__PURE__ */ jsxs(Stage, {
|
|
93
|
+
view: VIEW,
|
|
94
|
+
height,
|
|
95
|
+
ariaLabel: `Uniform field with a flat area at ${deg} degrees; ${threads} field lines thread it`,
|
|
96
|
+
children: [
|
|
97
|
+
ys.map((y, i) => {
|
|
98
|
+
const on = Math.abs(y - C.y) <= halfSpan + 1e-6;
|
|
99
|
+
return /* @__PURE__ */ jsx(Segment, {
|
|
100
|
+
from: {
|
|
101
|
+
x: VIEW.xMin,
|
|
102
|
+
y
|
|
103
|
+
},
|
|
104
|
+
to: {
|
|
105
|
+
x: VIEW.xMax,
|
|
106
|
+
y
|
|
107
|
+
},
|
|
108
|
+
color: on ? C_THREAD : C_FAINT,
|
|
109
|
+
weight: on ? 2.4 : 1.4
|
|
110
|
+
}, i);
|
|
111
|
+
}),
|
|
112
|
+
/* @__PURE__ */ jsx(Vector, {
|
|
113
|
+
tail: {
|
|
114
|
+
x: 3.6,
|
|
115
|
+
y: y1 - .2
|
|
116
|
+
},
|
|
117
|
+
tip: {
|
|
118
|
+
x: 4.7,
|
|
119
|
+
y: y1 - .2
|
|
120
|
+
},
|
|
121
|
+
color: "var(--stage-accent)"
|
|
122
|
+
}),
|
|
123
|
+
/* @__PURE__ */ jsx(Label, {
|
|
124
|
+
x: 4.9,
|
|
125
|
+
y: y1 - .2,
|
|
126
|
+
text: "E",
|
|
127
|
+
color: "var(--stage-accent)",
|
|
128
|
+
size: 13,
|
|
129
|
+
anchor: "start"
|
|
130
|
+
}),
|
|
131
|
+
/* @__PURE__ */ jsx(Segment, {
|
|
132
|
+
from: p1,
|
|
133
|
+
to: p2,
|
|
134
|
+
color: C_AREA,
|
|
135
|
+
weight: 7
|
|
136
|
+
}),
|
|
137
|
+
/* @__PURE__ */ jsx(Label, {
|
|
138
|
+
x: p1.x,
|
|
139
|
+
y: p1.y,
|
|
140
|
+
text: "area A",
|
|
141
|
+
color: C_AREA,
|
|
142
|
+
size: 12,
|
|
143
|
+
weight: 700,
|
|
144
|
+
dx: 8,
|
|
145
|
+
dy: -4,
|
|
146
|
+
anchor: "start"
|
|
147
|
+
}),
|
|
148
|
+
/* @__PURE__ */ jsx(Vector, {
|
|
149
|
+
tail: C,
|
|
150
|
+
tip: {
|
|
151
|
+
x: C.x + n.x * 1.5,
|
|
152
|
+
y: C.y + n.y * 1.5
|
|
153
|
+
},
|
|
154
|
+
color: C_NORMAL
|
|
155
|
+
}),
|
|
156
|
+
/* @__PURE__ */ jsx(AngleArc, {
|
|
157
|
+
at: C,
|
|
158
|
+
from: {
|
|
159
|
+
x: 1,
|
|
160
|
+
y: 0
|
|
161
|
+
},
|
|
162
|
+
to: n,
|
|
163
|
+
rPx: 38,
|
|
164
|
+
label: `θ=${Math.abs(deg)}°`
|
|
165
|
+
}),
|
|
166
|
+
/* @__PURE__ */ jsx(MovableDot, {
|
|
167
|
+
value: rotTip,
|
|
168
|
+
onMove: (p) => setTheta(Math.atan2(p.y - C.y, p.x - C.x)),
|
|
169
|
+
color: "var(--stage-accent)",
|
|
170
|
+
ariaLabel: "rotate the area",
|
|
171
|
+
r: 7
|
|
172
|
+
})
|
|
173
|
+
]
|
|
174
|
+
});
|
|
175
|
+
return /* @__PURE__ */ jsx(LabFrame, {
|
|
176
|
+
title,
|
|
177
|
+
prompt,
|
|
178
|
+
controls: /* @__PURE__ */ jsxs(ControlBar, { children: [
|
|
179
|
+
/* @__PURE__ */ jsx(Field, {
|
|
180
|
+
label: "field E₀",
|
|
181
|
+
value: fmt$1(E0),
|
|
182
|
+
children: /* @__PURE__ */ jsx(Slider, {
|
|
183
|
+
value: E0,
|
|
184
|
+
min: 1,
|
|
185
|
+
max: 12,
|
|
186
|
+
step: 1,
|
|
187
|
+
onChange: setE0,
|
|
188
|
+
ariaLabel: "field strength"
|
|
189
|
+
})
|
|
190
|
+
}),
|
|
191
|
+
/* @__PURE__ */ jsx(Field, {
|
|
192
|
+
label: "area A",
|
|
193
|
+
value: fmt$1(A),
|
|
194
|
+
children: /* @__PURE__ */ jsx(Slider, {
|
|
195
|
+
value: A,
|
|
196
|
+
min: 1,
|
|
197
|
+
max: 6,
|
|
198
|
+
step: .5,
|
|
199
|
+
onChange: setA,
|
|
200
|
+
ariaLabel: "area size"
|
|
201
|
+
})
|
|
202
|
+
}),
|
|
203
|
+
/* @__PURE__ */ jsx(Field, {
|
|
204
|
+
label: "angle θ",
|
|
205
|
+
value: `${Math.abs(deg)}°`,
|
|
206
|
+
children: /* @__PURE__ */ jsx(Slider, {
|
|
207
|
+
value: deg,
|
|
208
|
+
min: -90,
|
|
209
|
+
max: 90,
|
|
210
|
+
step: 5,
|
|
211
|
+
onChange: (v) => setTheta(v * Math.PI / 180),
|
|
212
|
+
ariaLabel: "angle of the area"
|
|
213
|
+
})
|
|
214
|
+
}),
|
|
215
|
+
/* @__PURE__ */ jsx(Field, {
|
|
216
|
+
label: "medium",
|
|
217
|
+
children: /* @__PURE__ */ jsx("span", {
|
|
218
|
+
className: "lab-field-row",
|
|
219
|
+
children: MEDIA.map((m) => /* @__PURE__ */ jsx(Chip, {
|
|
220
|
+
selected: er === m.er,
|
|
221
|
+
onClick: () => setEr(m.er),
|
|
222
|
+
children: m.name
|
|
223
|
+
}, m.name))
|
|
224
|
+
})
|
|
225
|
+
})
|
|
226
|
+
] }),
|
|
227
|
+
aside: /* @__PURE__ */ jsx(Callout, {
|
|
228
|
+
tone: "result",
|
|
229
|
+
children: /* @__PURE__ */ jsxs("div", {
|
|
230
|
+
style: {
|
|
231
|
+
display: "grid",
|
|
232
|
+
gap: 6,
|
|
233
|
+
fontVariantNumeric: "tabular-nums",
|
|
234
|
+
fontSize: 13
|
|
235
|
+
},
|
|
236
|
+
children: [
|
|
237
|
+
/* @__PURE__ */ jsxs("span", { children: ["lines threading the area: ", /* @__PURE__ */ jsx("strong", {
|
|
238
|
+
style: { color: C_THREAD },
|
|
239
|
+
children: threads
|
|
240
|
+
})] }),
|
|
241
|
+
/* @__PURE__ */ jsxs("span", { children: [
|
|
242
|
+
"E = E₀/εr = ",
|
|
243
|
+
/* @__PURE__ */ jsx("strong", { children: fmt$1(Eeff) }),
|
|
244
|
+
" ",
|
|
245
|
+
er > 1 ? `(÷${er} in ${MEDIA.find((m) => m.er === er)?.name})` : ""
|
|
246
|
+
] }),
|
|
247
|
+
/* @__PURE__ */ jsxs("span", { children: ["Φ = E·A·cosθ = ", /* @__PURE__ */ jsx("strong", { children: fmt$1(phi) })] }),
|
|
248
|
+
/* @__PURE__ */ jsx("span", {
|
|
249
|
+
style: { color: "var(--stage-muted)" },
|
|
250
|
+
children: Math.abs(deg) >= 88 ? "edge-on: nothing threads it, Φ = 0" : Math.abs(deg) < 2 ? "face-on: maximum flux, Φ = E·A" : "tilted: Φ falls with cosθ"
|
|
251
|
+
})
|
|
252
|
+
]
|
|
253
|
+
})
|
|
254
|
+
}),
|
|
255
|
+
footer: ask ? /* @__PURE__ */ jsx(LabAsk, {
|
|
256
|
+
ask,
|
|
257
|
+
activity
|
|
258
|
+
}) : void 0,
|
|
259
|
+
children: figure
|
|
260
|
+
});
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
//#endregion
|
|
264
|
+
export { ElectricFluxLab };
|
|
@@ -10,14 +10,14 @@ import { Label, Polyline, Segment, Stage, useInView } from "@classytic/stage";
|
|
|
10
10
|
|
|
11
11
|
//#region src/physics/energy-skate/preset.tsx
|
|
12
12
|
/**
|
|
13
|
-
* EnergySkateLab
|
|
13
|
+
* EnergySkateLab, "Where did the energy go?", KE ⇄ PE on a ramp, with friction
|
|
14
14
|
* bleeding the total into heat.
|
|
15
15
|
*
|
|
16
|
-
* A skater is released from a height on a parabolic ramp. Three stacked bars
|
|
17
|
-
* potential, kinetic, and thermal
|
|
16
|
+
* A skater is released from a height on a parabolic ramp. Three stacked bars ,
|
|
17
|
+
* potential, kinetic, and thermal, ALWAYS sum to the same total: as the skater
|
|
18
18
|
* drops, the PE bar empties into the KE bar and back on the way up. Turn friction
|
|
19
19
|
* on and a THERMAL bar grows each pass, so the skater can never climb as high
|
|
20
|
-
* again
|
|
20
|
+
* again, mechanical energy isn't destroyed, it's moved to heat. (The "LOL" energy
|
|
21
21
|
* bar chart, animated.)
|
|
22
22
|
*
|
|
23
23
|
* This complements WorkEnergyLab (work = area under F–x): here the spotlight is
|
|
@@ -30,7 +30,7 @@ const X = 6;
|
|
|
30
30
|
const H = 5;
|
|
31
31
|
const MU = .08;
|
|
32
32
|
const yAt = (x) => H * (x / X) * (x / X);
|
|
33
|
-
function EnergySkateLab({ startHeight = 4, friction = false, mass = 1, title = "Where did the energy go
|
|
33
|
+
function EnergySkateLab({ startHeight = 4, friction = false, mass = 1, title = "Where did the energy go?: KE ⇄ PE (and heat)", prompt = "Release the skater and watch potential energy pour into kinetic and back. The three bars always add to the same total, unless friction is on, then a heat bar grows and the skater can’t climb as high again.", objectives, controlConfig }) {
|
|
34
34
|
const [h0, setH0] = useState(clamp(startHeight, 1, H));
|
|
35
35
|
const [fric, setFric] = useState(friction);
|
|
36
36
|
const [m] = useState(mass);
|