@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
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
//#region \0rolldown/runtime.js
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __exportAll = (all, no_symbols) => {
|
|
4
|
+
let target = {};
|
|
5
|
+
for (var name in all) {
|
|
6
|
+
__defProp(target, name, {
|
|
7
|
+
get: all[name],
|
|
8
|
+
enumerable: true
|
|
9
|
+
});
|
|
10
|
+
}
|
|
11
|
+
if (!no_symbols) {
|
|
12
|
+
__defProp(target, Symbol.toStringTag, { value: "Module" });
|
|
13
|
+
}
|
|
14
|
+
return target;
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
//#endregion
|
|
18
|
+
export { __exportAll };
|
|
@@ -10,16 +10,16 @@ import { Axes, Dot, Label, Polygon, Segment, Stage } from "@classytic/stage";
|
|
|
10
10
|
|
|
11
11
|
//#region src/biology/enzyme-rate/preset.tsx
|
|
12
12
|
/**
|
|
13
|
-
* EnzymeRateLab
|
|
13
|
+
* EnzymeRateLab, the optimum, then the cliff: enzymes denature.
|
|
14
14
|
*
|
|
15
15
|
* Drag temperature: the rate climbs to an optimum (more kinetic energy → more
|
|
16
16
|
* successful enzyme–substrate collisions) then CRASHES as the lock-and-key active
|
|
17
|
-
* site is mangled
|
|
17
|
+
* site is mangled, and crucially, cooling back down does NOT restore it
|
|
18
18
|
* (thermal denaturation is irreversible). The bell is BUILT from plotted dots as
|
|
19
19
|
* you sweep, never pre-drawn. pH mode shows the same optimum but reversibly; a
|
|
20
20
|
* "fresh enzyme" reset is the only way back from a denatured run.
|
|
21
21
|
*
|
|
22
|
-
* Reuses core/util + kit/controls; tokenized; reduced-motion safe (no autoplay
|
|
22
|
+
* Reuses core/util + kit/controls; tokenized; reduced-motion safe (no autoplay ,
|
|
23
23
|
* the learner drags). The collision-theory vs denaturation split → a MathDerivation.
|
|
24
24
|
*/
|
|
25
25
|
const CLIFF = 16;
|
|
@@ -71,7 +71,7 @@ function Enzyme({ denat }) {
|
|
|
71
71
|
]
|
|
72
72
|
});
|
|
73
73
|
}
|
|
74
|
-
function EnzymeRateLab({ factor = "temperature", optimum = 40, factorMin = 0, factorMax = 80, title = "The optimum, then the cliff
|
|
74
|
+
function EnzymeRateLab({ factor = "temperature", optimum = 40, factorMin = 0, factorMax = 80, title = "The optimum, then the cliff: enzymes denature", prompt = "Drag the temperature. Past the optimum the enzyme denatures, and cooling back down won’t fix it.", height = 240, objectives }) {
|
|
75
75
|
const reversible = factor === "pH";
|
|
76
76
|
const [f, setF] = useState(reversible ? optimum - 2 : factorMin + 5);
|
|
77
77
|
const peak = useRef(f);
|
|
@@ -227,7 +227,7 @@ function EnzymeRateLab({ factor = "temperature", optimum = 40, factorMin = 0, fa
|
|
|
227
227
|
]
|
|
228
228
|
}), /* @__PURE__ */ jsx(StatusPill, {
|
|
229
229
|
ok: state === "optimum",
|
|
230
|
-
children: state === "optimum" ? "at the optimum ✓" : state === "denatured" ? "denatured
|
|
230
|
+
children: state === "optimum" ? "at the optimum ✓" : state === "denatured" ? "denatured, no recovery" : state === "falling" ? reversible ? "past optimum" : "denaturing…" : "climbing (more collisions)"
|
|
231
231
|
})]
|
|
232
232
|
}),
|
|
233
233
|
controls: /* @__PURE__ */ jsxs(ControlBar, { children: [/* @__PURE__ */ jsx(Field, {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
//#region src/biology/genetic-cross/core.d.ts
|
|
2
2
|
/**
|
|
3
|
-
* Genetics core
|
|
3
|
+
* Genetics core, a SERIALIZABLE cross model + the rule that turns a genotype into
|
|
4
4
|
* a phenotype. Authored as data (so agents can declare it via JSON), resolved into
|
|
5
5
|
* pure functions for the lab. One model covers simple dominance, multiple alleles,
|
|
6
6
|
* codominance and incomplete dominance:
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
* • an optional `blends` entry overrides a specific heterozygote
|
|
12
12
|
* (INCOMPLETE DOMINANCE → red × white = pink)
|
|
13
13
|
*
|
|
14
|
-
* No reinvented numerics
|
|
14
|
+
* No reinvented numerics, this is just the genetics rule; UI lives in the preset.
|
|
15
15
|
*/
|
|
16
16
|
interface AlleleSpec {
|
|
17
17
|
symbol: string;
|
|
@@ -42,15 +42,15 @@ interface ResolvedModel {
|
|
|
42
42
|
phenotypeColor: (label: string) => string;
|
|
43
43
|
/** every possible genotype as a normalised [a,b] pair (for parent pickers). */
|
|
44
44
|
genotypes: [string, string][];
|
|
45
|
-
/** true if `a` masks `b` here
|
|
45
|
+
/** true if `a` masks `b` here, a dominant over a present lower-rank allele. */
|
|
46
46
|
masks: (a: string, b: string) => boolean;
|
|
47
47
|
}
|
|
48
48
|
declare function resolveModel(spec: CrossModelSpec): ResolvedModel;
|
|
49
|
-
/** Simple dominant/recessive
|
|
49
|
+
/** Simple dominant/recessive, the classic monohybrid (also backs PunnettCross). */
|
|
50
50
|
declare const monohybridSpec: (letter?: string, dominant?: string, recessive?: string) => CrossModelSpec;
|
|
51
|
-
/** ABO blood groups
|
|
51
|
+
/** ABO blood groups, multiple alleles + codominance (Aᴬ Aᴮ → AB). */
|
|
52
52
|
declare const BLOOD_TYPE_SPEC: CrossModelSpec;
|
|
53
|
-
/** Incomplete dominance
|
|
53
|
+
/** Incomplete dominance, red × white = pink (a blended heterozygote). */
|
|
54
54
|
declare const INCOMPLETE_SPEC: CrossModelSpec;
|
|
55
55
|
declare const CROSS_PRESETS: {
|
|
56
56
|
readonly monohybrid: CrossModelSpec;
|
|
@@ -58,7 +58,7 @@ declare const CROSS_PRESETS: {
|
|
|
58
58
|
readonly incomplete: CrossModelSpec;
|
|
59
59
|
};
|
|
60
60
|
type CrossPresetKey = keyof typeof CROSS_PRESETS;
|
|
61
|
-
/** Two independent genes
|
|
61
|
+
/** Two independent genes, the classic dihybrid 9:3:3:1 (height × seed colour). */
|
|
62
62
|
declare const DIHYBRID_LOCI: CrossModelSpec[];
|
|
63
63
|
//#endregion
|
|
64
64
|
export { AlleleSpec, BLOOD_TYPE_SPEC, BlendSpec, CROSS_PRESETS, CrossModelSpec, CrossPresetKey, DIHYBRID_LOCI, INCOMPLETE_SPEC, Phenotype, ResolvedModel, monohybridSpec, resolveModel };
|
|
@@ -45,7 +45,7 @@ function resolveModel(spec) {
|
|
|
45
45
|
masks: (a, b) => !blends.has(blendKey(a, b)) && (rank.get(a) ?? 0) > (rank.get(b) ?? 0)
|
|
46
46
|
};
|
|
47
47
|
}
|
|
48
|
-
/** Simple dominant/recessive
|
|
48
|
+
/** Simple dominant/recessive, the classic monohybrid (also backs PunnettCross). */
|
|
49
49
|
const monohybridSpec = (letter = "A", dominant = "tall", recessive = "short") => ({
|
|
50
50
|
trait: "trait",
|
|
51
51
|
alleles: [{
|
|
@@ -62,7 +62,7 @@ const monohybridSpec = (letter = "A", dominant = "tall", recessive = "short") =>
|
|
|
62
62
|
[recessive]: "var(--stage-muted)"
|
|
63
63
|
}
|
|
64
64
|
});
|
|
65
|
-
/** ABO blood groups
|
|
65
|
+
/** ABO blood groups, multiple alleles + codominance (Aᴬ Aᴮ → AB). */
|
|
66
66
|
const BLOOD_TYPE_SPEC = {
|
|
67
67
|
trait: "blood type",
|
|
68
68
|
alleles: [
|
|
@@ -89,7 +89,7 @@ const BLOOD_TYPE_SPEC = {
|
|
|
89
89
|
O: "var(--stage-muted)"
|
|
90
90
|
}
|
|
91
91
|
};
|
|
92
|
-
/** Incomplete dominance
|
|
92
|
+
/** Incomplete dominance, red × white = pink (a blended heterozygote). */
|
|
93
93
|
const INCOMPLETE_SPEC = {
|
|
94
94
|
trait: "flower colour",
|
|
95
95
|
alleles: [{
|
|
@@ -116,7 +116,7 @@ const CROSS_PRESETS = {
|
|
|
116
116
|
"blood-type": BLOOD_TYPE_SPEC,
|
|
117
117
|
incomplete: INCOMPLETE_SPEC
|
|
118
118
|
};
|
|
119
|
-
/** Two independent genes
|
|
119
|
+
/** Two independent genes, the classic dihybrid 9:3:3:1 (height × seed colour). */
|
|
120
120
|
const DIHYBRID_LOCI = [monohybridSpec("A", "tall", "short"), monohybridSpec("B", "yellow", "green")];
|
|
121
121
|
/** every distinct phenotype label a single-locus model can show (stable order). */
|
|
122
122
|
function phenotypeLabels(m) {
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
|
|
3
3
|
import { CheckButton, StatusPill } from "../../kit/controls.mjs";
|
|
4
|
-
import { LabFrame, LiveRegion } from "../../kit/frame.mjs";
|
|
4
|
+
import { ControlBar, LabFrame, LiveRegion } from "../../kit/frame.mjs";
|
|
5
5
|
import { useEffect, useState } from "react";
|
|
6
6
|
import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
|
|
7
7
|
|
|
8
8
|
//#region src/biology/genetic-cross/grid.tsx
|
|
9
9
|
/**
|
|
10
|
-
* CrossGrid
|
|
10
|
+
* CrossGrid, the shared Punnett-grid UI (single source of truth for every cross
|
|
11
11
|
* lab: monohybrid, dihybrid, sex-linked). It is PRESENTATIONAL: the parent labs
|
|
12
12
|
* compute the gametes + the combine rule and hand them in; this draws the gametes
|
|
13
13
|
* on the edges, fills the N×N grid, runs predict-before-reveal, and reads off the
|
|
@@ -91,6 +91,7 @@ function CrossGrid({ gametes1, gametes2, gameteLabel, combine, traitLabel, reset
|
|
|
91
91
|
});
|
|
92
92
|
};
|
|
93
93
|
const cellBg = (c) => highlight === c.genotype ? `color-mix(in oklab, ${c.phenotype.color} 34%, var(--stage-bg))` : `color-mix(in oklab, ${c.phenotype.color} 13%, var(--stage-bg))`;
|
|
94
|
+
const cellAria = (c, r, ci) => revealed ? `${gameteLabel(gametes1[r])} × ${gameteLabel(gametes2[ci])} → ${c.genotype}, ${c.phenotype.label}` : `${gameteLabel(gametes1[r])} × ${gameteLabel(gametes2[ci])}, hidden until revealed`;
|
|
94
95
|
const figure = /* @__PURE__ */ jsxs(Fragment$1, { children: [legend, /* @__PURE__ */ jsxs("div", {
|
|
95
96
|
style: {
|
|
96
97
|
borderRadius: 14,
|
|
@@ -99,141 +100,149 @@ function CrossGrid({ gametes1, gametes2, gameteLabel, combine, traitLabel, reset
|
|
|
99
100
|
padding: 16,
|
|
100
101
|
overflowX: "auto"
|
|
101
102
|
},
|
|
102
|
-
children: [
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
}) : /* @__PURE__ */ jsxs("div", {
|
|
166
|
-
className: "lab-bar",
|
|
103
|
+
children: [/* @__PURE__ */ jsxs("div", {
|
|
104
|
+
role: "table",
|
|
105
|
+
"aria-label": revealed ? `Punnett grid, ${gametes1.length} by ${gametes2.length}. ${traitLabel} ratio ${phenoTally.map((p) => `${p.n} ${p.label}`).join(", ")}.` : `Punnett grid, ${gametes1.length} by ${gametes2.length}, offspring hidden until you reveal the cross.`,
|
|
106
|
+
style: {
|
|
107
|
+
display: "inline-grid",
|
|
108
|
+
gridTemplateColumns: `${cellSize}px repeat(${gametes2.length}, ${cellSize}px)`,
|
|
109
|
+
gap: 4
|
|
110
|
+
},
|
|
111
|
+
children: [/* @__PURE__ */ jsxs("div", {
|
|
112
|
+
role: "row",
|
|
113
|
+
style: { display: "contents" },
|
|
114
|
+
children: [/* @__PURE__ */ jsx("div", {
|
|
115
|
+
role: "columnheader",
|
|
116
|
+
"aria-hidden": true,
|
|
117
|
+
style: { pointerEvents: "none" }
|
|
118
|
+
}), gametes2.map((g, i) => /* @__PURE__ */ jsx("div", {
|
|
119
|
+
role: "columnheader",
|
|
120
|
+
style: {
|
|
121
|
+
textAlign: "center",
|
|
122
|
+
fontSize,
|
|
123
|
+
fontWeight: 800,
|
|
124
|
+
color: "var(--stage-fg)"
|
|
125
|
+
},
|
|
126
|
+
children: gameteLabel(g)
|
|
127
|
+
}, i))]
|
|
128
|
+
}), cells.map((row, r) => /* @__PURE__ */ jsxs("div", {
|
|
129
|
+
role: "row",
|
|
130
|
+
style: { display: "contents" },
|
|
131
|
+
children: [/* @__PURE__ */ jsx("div", {
|
|
132
|
+
role: "rowheader",
|
|
133
|
+
style: {
|
|
134
|
+
display: "flex",
|
|
135
|
+
alignItems: "center",
|
|
136
|
+
justifyContent: "center",
|
|
137
|
+
fontSize,
|
|
138
|
+
fontWeight: 800,
|
|
139
|
+
color: "var(--stage-fg)"
|
|
140
|
+
},
|
|
141
|
+
children: gameteLabel(gametes1[r])
|
|
142
|
+
}), row.map((c, ci) => /* @__PURE__ */ jsx("button", {
|
|
143
|
+
type: "button",
|
|
144
|
+
role: "cell",
|
|
145
|
+
"aria-label": cellAria(c, r, ci),
|
|
146
|
+
onClick: () => revealed && setHighlight((h) => h === c.genotype ? null : c.genotype),
|
|
147
|
+
title: revealed ? `${c.genotype} → ${c.phenotype.label}` : void 0,
|
|
148
|
+
style: {
|
|
149
|
+
width: cellSize,
|
|
150
|
+
height: cellSize,
|
|
151
|
+
borderRadius: 6,
|
|
152
|
+
border: "1px solid var(--stage-grid)",
|
|
153
|
+
background: revealed ? cellBg(c) : "var(--stage-bg)",
|
|
154
|
+
cursor: revealed ? "pointer" : "default",
|
|
155
|
+
fontSize,
|
|
156
|
+
fontWeight: 700,
|
|
157
|
+
color: "var(--stage-fg)",
|
|
158
|
+
padding: 0
|
|
159
|
+
},
|
|
160
|
+
children: revealed ? c.genotype : "?"
|
|
161
|
+
}, ci))]
|
|
162
|
+
}, r))]
|
|
163
|
+
}), revealed && highlight && (() => {
|
|
164
|
+
const c = flat.find((x) => x.genotype === highlight);
|
|
165
|
+
return /* @__PURE__ */ jsxs("p", {
|
|
167
166
|
style: {
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
167
|
+
fontSize: 12,
|
|
168
|
+
color: "var(--stage-muted)",
|
|
169
|
+
margin: "8px 0 0"
|
|
171
170
|
},
|
|
172
171
|
children: [
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
/* @__PURE__ */ jsx(
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
n: p.n,
|
|
185
|
-
color: p.color,
|
|
186
|
-
tag: p.label
|
|
187
|
-
}))
|
|
172
|
+
highlight,
|
|
173
|
+
": ",
|
|
174
|
+
genoCount(highlight),
|
|
175
|
+
" of ",
|
|
176
|
+
flat.length,
|
|
177
|
+
" (",
|
|
178
|
+
(genoCount(highlight) / flat.length * 100).toFixed(0),
|
|
179
|
+
"%) → ",
|
|
180
|
+
/* @__PURE__ */ jsx("b", {
|
|
181
|
+
style: { color: c.phenotype.color },
|
|
182
|
+
children: c.phenotype.label
|
|
188
183
|
}),
|
|
189
|
-
|
|
190
|
-
ok: true,
|
|
191
|
-
children: [
|
|
192
|
-
phenoTally.map((p) => p.n).join(":"),
|
|
193
|
-
" ",
|
|
194
|
-
phenoTally.map((p) => p.label).join(" : ")
|
|
195
|
-
]
|
|
196
|
-
})
|
|
184
|
+
c.note ?? ""
|
|
197
185
|
]
|
|
198
|
-
})
|
|
199
|
-
|
|
200
|
-
const c = flat.find((x) => x.genotype === highlight);
|
|
201
|
-
return /* @__PURE__ */ jsxs("p", {
|
|
202
|
-
style: {
|
|
203
|
-
fontSize: 12,
|
|
204
|
-
color: "var(--stage-muted)",
|
|
205
|
-
margin: "8px 0 0"
|
|
206
|
-
},
|
|
207
|
-
children: [
|
|
208
|
-
highlight,
|
|
209
|
-
": ",
|
|
210
|
-
genoCount(highlight),
|
|
211
|
-
" of ",
|
|
212
|
-
flat.length,
|
|
213
|
-
" (",
|
|
214
|
-
(genoCount(highlight) / flat.length * 100).toFixed(0),
|
|
215
|
-
"%) → ",
|
|
216
|
-
/* @__PURE__ */ jsx("b", {
|
|
217
|
-
style: { color: c.phenotype.color },
|
|
218
|
-
children: c.phenotype.label
|
|
219
|
-
}),
|
|
220
|
-
c.note ?? ""
|
|
221
|
-
]
|
|
222
|
-
});
|
|
223
|
-
})()
|
|
224
|
-
]
|
|
186
|
+
});
|
|
187
|
+
})()]
|
|
225
188
|
})] });
|
|
226
189
|
return /* @__PURE__ */ jsx(LabFrame, {
|
|
227
190
|
title,
|
|
228
191
|
prompt,
|
|
229
192
|
objectives,
|
|
193
|
+
controls: /* @__PURE__ */ jsxs(ControlBar, { children: [header, !revealed && /* @__PURE__ */ jsxs("div", {
|
|
194
|
+
className: "lab-bar",
|
|
195
|
+
children: [/* @__PURE__ */ jsxs("span", {
|
|
196
|
+
style: { fontWeight: 600 },
|
|
197
|
+
children: [
|
|
198
|
+
"Predict the ",
|
|
199
|
+
traitLabel,
|
|
200
|
+
" ratio, then…"
|
|
201
|
+
]
|
|
202
|
+
}), /* @__PURE__ */ jsx(CheckButton, {
|
|
203
|
+
onClick: reveal,
|
|
204
|
+
children: "Reveal the cross"
|
|
205
|
+
})]
|
|
206
|
+
})] }),
|
|
207
|
+
aside: revealed ? /* @__PURE__ */ jsxs("div", {
|
|
208
|
+
className: "lab-bar",
|
|
209
|
+
style: {
|
|
210
|
+
gap: 16,
|
|
211
|
+
flexWrap: "wrap",
|
|
212
|
+
flexDirection: "column",
|
|
213
|
+
alignItems: "stretch"
|
|
214
|
+
},
|
|
215
|
+
children: [
|
|
216
|
+
showGenotypeTally && /* @__PURE__ */ jsx(Bar, {
|
|
217
|
+
label: "Genotype",
|
|
218
|
+
parts: genotypes.map((g) => ({
|
|
219
|
+
n: genoCount(g),
|
|
220
|
+
color: genoColor(g),
|
|
221
|
+
tag: g
|
|
222
|
+
}))
|
|
223
|
+
}),
|
|
224
|
+
/* @__PURE__ */ jsx(Bar, {
|
|
225
|
+
label: traitLabel,
|
|
226
|
+
parts: phenoTally.map((p) => ({
|
|
227
|
+
n: p.n,
|
|
228
|
+
color: p.color,
|
|
229
|
+
tag: p.label
|
|
230
|
+
}))
|
|
231
|
+
}),
|
|
232
|
+
/* @__PURE__ */ jsxs(StatusPill, {
|
|
233
|
+
ok: true,
|
|
234
|
+
children: [
|
|
235
|
+
phenoTally.map((p) => p.n).join(":"),
|
|
236
|
+
" ",
|
|
237
|
+
phenoTally.map((p) => p.label).join(" : ")
|
|
238
|
+
]
|
|
239
|
+
})
|
|
240
|
+
]
|
|
241
|
+
}) : void 0,
|
|
230
242
|
footer: /* @__PURE__ */ jsx(LiveRegion, { children: revealed ? `${traitLabel} ratio ${phenoTally.map((p) => `${p.n} ${p.label}`).join(", ")}.` : "Predict, then reveal." }),
|
|
231
243
|
children: figure
|
|
232
244
|
});
|
|
233
245
|
}
|
|
234
|
-
function Frag({ children }) {
|
|
235
|
-
return /* @__PURE__ */ jsx(Fragment$1, { children });
|
|
236
|
-
}
|
|
237
246
|
|
|
238
247
|
//#endregion
|
|
239
248
|
export { CrossGrid };
|
|
@@ -8,7 +8,7 @@ import { useLearner } from "@classytic/stage";
|
|
|
8
8
|
|
|
9
9
|
//#region src/biology/genetic-cross/preset.tsx
|
|
10
10
|
/**
|
|
11
|
-
* GeneticCrossLab
|
|
11
|
+
* GeneticCrossLab, ONE authorable cross tool for every Mendelian pattern, now
|
|
12
12
|
* MULTI-LOCUS. The creator declares one model per gene; the lab derives gametes by
|
|
13
13
|
* independent assortment (one allele per locus → 2ⁿ gametes), fills the Punnett
|
|
14
14
|
* grid via the shared CrossGrid, and reads off the genotype + phenotype ratios.
|
|
@@ -53,7 +53,7 @@ function GeneticCrossLab({ spec, loci, parent1, parent2, predictFirst = true, ti
|
|
|
53
53
|
const [a, b] = perLocus[0].geno;
|
|
54
54
|
if (a !== b) {
|
|
55
55
|
const [hi, lo] = models[0].masks(a, b) ? [a, b] : models[0].masks(b, a) ? [b, a] : ["", ""];
|
|
56
|
-
if (hi) note =
|
|
56
|
+
if (hi) note = `, the recessive ${lo} is still there, masked`;
|
|
57
57
|
}
|
|
58
58
|
}
|
|
59
59
|
return {
|
|
@@ -159,8 +159,8 @@ function GeneticCrossLab({ spec, loci, parent1, parent2, predictFirst = true, ti
|
|
|
159
159
|
predictFirst,
|
|
160
160
|
header,
|
|
161
161
|
legend,
|
|
162
|
-
title: title ?? (multi ? "Dihybrid cross
|
|
163
|
-
prompt: prompt ?? (multi ? "Two genes assort independently
|
|
162
|
+
title: title ?? (multi ? "Dihybrid cross, 9 : 3 : 3 : 1" : "The cross you can count"),
|
|
163
|
+
prompt: prompt ?? (multi ? "Two genes assort independently, four gametes each, sixteen boxes, four phenotype classes." : "Alleles segregate into gametes, recombine, and the ratio falls out."),
|
|
164
164
|
objectives,
|
|
165
165
|
showGenotypeTally: !multi,
|
|
166
166
|
onReveal: () => {
|
|
@@ -7,9 +7,9 @@ import { useLearner } from "@classytic/stage";
|
|
|
7
7
|
|
|
8
8
|
//#region src/biology/genetic-cross/sex-linked.tsx
|
|
9
9
|
/**
|
|
10
|
-
* SexLinkedCrossLab
|
|
11
|
-
* the shared CrossGrid. The biology that's special
|
|
12
|
-
* males are HEMIZYGOUS (a single recessive X shows)
|
|
10
|
+
* SexLinkedCrossLab, an X-linked gene cross (colour blindness, haemophilia…) on
|
|
11
|
+
* the shared CrossGrid. The biology that's special, the Y carries no allele, so
|
|
12
|
+
* males are HEMIZYGOUS (a single recessive X shows), lives here; the grid/tally/
|
|
13
13
|
* predict UI is reused. The payoff: affected sons from a carrier mother, while
|
|
14
14
|
* daughters are carriers, not affected.
|
|
15
15
|
*/
|
|
@@ -60,7 +60,7 @@ function SexLinkedCrossLab({ allele = "B", dominant = "normal", recessive = "col
|
|
|
60
60
|
label: `${affected ? recessive : dominant} ♂`,
|
|
61
61
|
color: affected ? COL.recM : COL.domM
|
|
62
62
|
},
|
|
63
|
-
note:
|
|
63
|
+
note: `: males are hemizygous: one ${Xr} is enough to show ${recessive}`
|
|
64
64
|
};
|
|
65
65
|
}
|
|
66
66
|
const xs = [mx, fx].sort((a, b) => (isDom(a) ? -1 : 1) - (isDom(b) ? -1 : 1));
|
|
@@ -72,7 +72,7 @@ function SexLinkedCrossLab({ allele = "B", dominant = "normal", recessive = "col
|
|
|
72
72
|
label: `${domPresent ? dominant : recessive} ♀`,
|
|
73
73
|
color: domPresent ? COL.domF : COL.recF
|
|
74
74
|
},
|
|
75
|
-
note: carrier ?
|
|
75
|
+
note: carrier ? `: a carrier (one ${Xr}), ${dominant} herself but can pass it on` : ""
|
|
76
76
|
};
|
|
77
77
|
};
|
|
78
78
|
const cycleMom = (i) => setMom((m) => m.map((t, j) => j === i ? t === XD ? Xr : XD : t));
|
|
@@ -201,8 +201,8 @@ function SexLinkedCrossLab({ allele = "B", dominant = "normal", recessive = "col
|
|
|
201
201
|
predictFirst,
|
|
202
202
|
header,
|
|
203
203
|
legend,
|
|
204
|
-
title: title ?? "Sex linkage
|
|
205
|
-
prompt: prompt ?? "The gene rides on the X. A carrier mother passes it to half her sons
|
|
204
|
+
title: title ?? "Sex linkage, why mostly sons are affected",
|
|
205
|
+
prompt: prompt ?? "The gene rides on the X. A carrier mother passes it to half her sons, who, with no second X, show it.",
|
|
206
206
|
objectives,
|
|
207
207
|
showGenotypeTally: true,
|
|
208
208
|
onReveal: () => {
|
|
@@ -11,10 +11,10 @@ import { Axes, Dot, Label, Polyline, Segment, Stage } from "@classytic/stage";
|
|
|
11
11
|
|
|
12
12
|
//#region src/biology/photosynthesis-factors/preset.tsx
|
|
13
13
|
/**
|
|
14
|
-
* PhotosynthesisFactorsLab
|
|
14
|
+
* PhotosynthesisFactorsLab, limiting factors: the slowest worker sets the pace.
|
|
15
15
|
*
|
|
16
16
|
* Sliders for light, CO₂ and temperature. The rate climbs with light then
|
|
17
|
-
* PLATEAUS at whichever factor is in shortest supply
|
|
17
|
+
* PLATEAUS at whichever factor is in shortest supply, raise CO₂ and the SAME
|
|
18
18
|
* light curve climbs to a higher plateau, proving light was no longer limiting.
|
|
19
19
|
* Temperature is different: it gives a PEAK (optimum) not a plateau, because past
|
|
20
20
|
* the optimum enzymes denature. "Freeze curve" overlays a faint copy so two CO₂
|
|
@@ -26,7 +26,7 @@ import { Axes, Dot, Label, Polyline, Segment, Stage } from "@classytic/stage";
|
|
|
26
26
|
const CLIFF = 14;
|
|
27
27
|
const FACTORS_CHALLENGE = [{
|
|
28
28
|
id: "plateau",
|
|
29
|
-
prompt: "Raising light further does nothing
|
|
29
|
+
prompt: "Raising light further does nothing, the rate-vs-light curve has flattened. What sets the height of that plateau?",
|
|
30
30
|
choices: [
|
|
31
31
|
{
|
|
32
32
|
value: "factor",
|
|
@@ -38,14 +38,14 @@ const FACTORS_CHALLENGE = [{
|
|
|
38
38
|
},
|
|
39
39
|
{
|
|
40
40
|
value: "random",
|
|
41
|
-
label: "nothing
|
|
41
|
+
label: "nothing: it’s random"
|
|
42
42
|
}
|
|
43
43
|
],
|
|
44
44
|
answer: "factor",
|
|
45
|
-
explain: "Where the curve flattens, some OTHER factor (CO₂ supply or temperature) is now the bottleneck
|
|
45
|
+
explain: "Where the curve flattens, some OTHER factor (CO₂ supply or temperature) is now the bottleneck, the slowest worker sets the pace."
|
|
46
46
|
}, {
|
|
47
47
|
id: "cliff",
|
|
48
|
-
prompt: "Push temperature well ABOVE the optimum and the rate CRASHES
|
|
48
|
+
prompt: "Push temperature well ABOVE the optimum and the rate CRASHES, not just plateaus. Why?",
|
|
49
49
|
choices: [
|
|
50
50
|
{
|
|
51
51
|
value: "denature",
|
|
@@ -61,9 +61,9 @@ const FACTORS_CHALLENGE = [{
|
|
|
61
61
|
}
|
|
62
62
|
],
|
|
63
63
|
answer: "denature",
|
|
64
|
-
explain: "Past the optimum the enzymes lose their shape (denature)
|
|
64
|
+
explain: "Past the optimum the enzymes lose their shape (denature), that destroys capacity, unlike a mere limiting factor."
|
|
65
65
|
}];
|
|
66
|
-
function PhotosynthesisFactorsLab({ light = 70, co2 = 50, temperature = 25, tempOptimum = 28, title = "Limiting factors
|
|
66
|
+
function PhotosynthesisFactorsLab({ light = 70, co2 = 50, temperature = 25, tempOptimum = 28, title = "Limiting factors: the slowest worker sets the pace", prompt = "Raise light: the rate plateaus where another factor (CO₂ or temperature) takes over.", height = 240, objectives }) {
|
|
67
67
|
const [l, setL] = useState(light);
|
|
68
68
|
const [c, setC] = useState(co2);
|
|
69
69
|
const [t, setT] = useState(temperature);
|
|
@@ -9,12 +9,12 @@ import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
|
|
|
9
9
|
|
|
10
10
|
//#region src/biology/respiration/preset.tsx
|
|
11
11
|
/**
|
|
12
|
-
* RespirationLab
|
|
12
|
+
* RespirationLab, photosynthesis ⇌ respiration: one runs the other backwards.
|
|
13
13
|
*
|
|
14
14
|
* Two reaction flows, stacked, drawn with the SHARED MoleculeGlyph + ReactionFlow
|
|
15
15
|
* engine: photosynthesis (6CO₂ + 6H₂O + light → glucose + 6O₂) and respiration
|
|
16
16
|
* (glucose + 6O₂ → 6CO₂ + 6H₂O + ATP). The products of one are literally the
|
|
17
|
-
* reactants of the other
|
|
17
|
+
* reactants of the other, the closed loop is impossible to forget. A day/night
|
|
18
18
|
* toggle shows the NET gas exchange: by day photosynthesis outpaces respiration
|
|
19
19
|
* (net O₂ out); at night only respiration runs (net CO₂ out).
|
|
20
20
|
*
|
|
@@ -79,7 +79,7 @@ const RESP_CHALLENGE = [{
|
|
|
79
79
|
answer: "o2",
|
|
80
80
|
explain: "Photosynthesis fixes more CO₂ than respiration makes, and releases more O₂ than it uses."
|
|
81
81
|
}];
|
|
82
|
-
function RespirationLab({ mode = "day", title = "Photosynthesis ⇌ Respiration
|
|
82
|
+
function RespirationLab({ mode = "day", title = "Photosynthesis ⇌ Respiration: one runs the other backwards", prompt = "The products of one are the reactants of the other. Flip day/night to see the net gas exchange.", objectives }) {
|
|
83
83
|
const [when, setWhen] = useState(mode);
|
|
84
84
|
const day = when === "day";
|
|
85
85
|
const challenge = useChallenge(RESP_CHALLENGE);
|
|
@@ -138,7 +138,7 @@ function RespirationLab({ mode = "day", title = "Photosynthesis ⇌ Respiration
|
|
|
138
138
|
color: "var(--stage-muted)",
|
|
139
139
|
fontWeight: 600
|
|
140
140
|
},
|
|
141
|
-
children: "↑ products feed ↓ reactants
|
|
141
|
+
children: "↑ products feed ↓ reactants, the same six molecules loop ↑"
|
|
142
142
|
}),
|
|
143
143
|
flowCard("Respiration", "mitochondrion (always)", RESP, true, "var(--stage-accent-2)")
|
|
144
144
|
]
|
|
@@ -9,12 +9,12 @@ import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
|
|
|
9
9
|
|
|
10
10
|
//#region src/biology/sequence/central-dogma.tsx
|
|
11
11
|
/**
|
|
12
|
-
* CentralDogmaLab
|
|
12
|
+
* CentralDogmaLab, the whole central dogma in one flow: DNA → (transcription) →
|
|
13
13
|
* mRNA → (translation) → protein. The learner does BOTH steps on one starting
|
|
14
14
|
* strand: first pair the DNA template into mRNA (T→U), then read each 3-base codon
|
|
15
15
|
* to its amino acid. Translation unlocks only once the mRNA is correct, so the
|
|
16
16
|
* dependency (you can't translate what isn't transcribed) is felt. Reuses the
|
|
17
|
-
* sequence core (TRANSCRIBE + CODON_TABLE)
|
|
17
|
+
* sequence core (TRANSCRIBE + CODON_TABLE), no new pairing logic.
|
|
18
18
|
*/
|
|
19
19
|
const hash = (s) => {
|
|
20
20
|
let h = 0;
|
|
@@ -44,7 +44,7 @@ function CentralDogmaLab({ dna = [
|
|
|
44
44
|
"A",
|
|
45
45
|
"T",
|
|
46
46
|
"T"
|
|
47
|
-
], title = "The central dogma
|
|
47
|
+
], title = "The central dogma: DNA → mRNA → protein", prompt = "Transcribe the DNA into mRNA (T→U), then translate each codon into an amino acid.", objectives }) {
|
|
48
48
|
const nCodons = Math.floor(dna.length / 3);
|
|
49
49
|
const [mrna, setMrna] = useState(() => dna.map(() => null));
|
|
50
50
|
const [protein, setProtein] = useState(() => Array.from({ length: nCodons }, () => null));
|
|
@@ -154,7 +154,7 @@ function CentralDogmaLab({ dna = [
|
|
|
154
154
|
children: b
|
|
155
155
|
}, i))]
|
|
156
156
|
}),
|
|
157
|
-
arrow("transcription
|
|
157
|
+
arrow("transcription, copy the template, T → U"),
|
|
158
158
|
/* @__PURE__ */ jsxs("div", {
|
|
159
159
|
style: {
|
|
160
160
|
display: "flex",
|
|
@@ -194,7 +194,7 @@ function CentralDogmaLab({ dna = [
|
|
|
194
194
|
}, i);
|
|
195
195
|
})]
|
|
196
196
|
}),
|
|
197
|
-
arrow(transcribed ? "translation
|
|
197
|
+
arrow(transcribed ? "translation, read each codon off the genetic code" : "translation, locked until the mRNA is complete"),
|
|
198
198
|
/* @__PURE__ */ jsxs("div", {
|
|
199
199
|
style: {
|
|
200
200
|
display: "flex",
|