@classytic/stage 0.2.0 → 0.4.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/LICENSE +1 -1
- package/README.md +5 -1
- package/dist/_virtual/_rolldown/runtime.mjs +18 -0
- package/dist/assets/index.mjs +0 -1
- package/dist/atomic/aufbau.d.mts +144 -0
- package/dist/atomic/aufbau.mjs +384 -0
- package/dist/atomic/elements.d.mts +67 -0
- package/dist/atomic/elements.mjs +785 -0
- package/dist/atomic/emission.d.mts +112 -0
- package/dist/atomic/emission.mjs +179 -0
- package/dist/atomic/index.d.mts +8 -0
- package/dist/atomic/index.mjs +9 -0
- package/dist/atomic/periodic.d.mts +82 -0
- package/dist/atomic/periodic.mjs +231 -0
- package/dist/atomic/properties.d.mts +100 -0
- package/dist/atomic/properties.mjs +574 -0
- package/dist/atomic/shells.d.mts +137 -0
- package/dist/atomic/shells.mjs +170 -0
- package/dist/atomic/trends.d.mts +148 -0
- package/dist/atomic/trends.mjs +225 -0
- package/dist/builder/Palette.mjs +50 -89
- package/dist/builder/SceneBuilder.mjs +15 -73
- package/dist/chem/chromatography.d.mts +66 -0
- package/dist/chem/chromatography.mjs +63 -0
- package/dist/chem/complex.d.mts +114 -0
- package/dist/chem/complex.mjs +234 -0
- package/dist/chem/cycle.d.mts +75 -0
- package/dist/chem/cycle.mjs +145 -0
- package/dist/chem/equation.d.mts +86 -0
- package/dist/chem/equation.mjs +168 -0
- package/dist/chem/formula.d.mts +90 -0
- package/dist/chem/formula.mjs +201 -0
- package/dist/chem/functional-groups.d.mts +31 -0
- package/dist/chem/functional-groups.mjs +187 -0
- package/dist/chem/hazard.d.mts +94 -0
- package/dist/chem/hazard.mjs +329 -0
- package/dist/chem/index.d.mts +34 -33
- package/dist/chem/index.mjs +34 -28
- package/dist/chem/ionic.d.mts +98 -0
- package/dist/chem/ionic.mjs +156 -0
- package/dist/chem/layout.d.mts +46 -0
- package/dist/chem/layout.mjs +342 -0
- package/dist/chem/lewis.d.mts +79 -0
- package/dist/chem/lewis.mjs +163 -0
- package/dist/chem/molecular-orbital.d.mts +114 -0
- package/dist/chem/molecular-orbital.mjs +201 -0
- package/dist/chem/molecule.d.mts +154 -0
- package/dist/chem/molecule.mjs +282 -0
- package/dist/chem/nmr.d.mts +153 -0
- package/dist/chem/nmr.mjs +165 -0
- package/dist/chem/polymer.d.mts +65 -0
- package/dist/chem/polymer.mjs +179 -0
- package/dist/chem/redox.d.mts +138 -0
- package/dist/chem/redox.mjs +328 -0
- package/dist/chem/relations.d.mts +183 -0
- package/dist/chem/relations.mjs +299 -0
- package/dist/chem/skeleton.d.mts +51 -0
- package/dist/chem/skeleton.mjs +186 -0
- package/dist/chem/solution.d.mts +116 -0
- package/dist/chem/solution.mjs +186 -0
- package/dist/chem/species.d.mts +47 -0
- package/dist/chem/species.mjs +128 -0
- package/dist/chem/stereo.d.mts +108 -0
- package/dist/chem/stereo.mjs +286 -0
- package/dist/chem/stoichiometry.d.mts +95 -0
- package/dist/chem/stoichiometry.mjs +145 -0
- package/dist/chem/synthesis.d.mts +113 -0
- package/dist/chem/synthesis.mjs +281 -0
- package/dist/chem/vsepr.d.mts +80 -0
- package/dist/chem/vsepr.mjs +247 -0
- package/dist/circuit/ac.d.mts +163 -0
- package/dist/circuit/ac.mjs +452 -0
- package/dist/circuit/dc.d.mts +92 -0
- package/dist/circuit/dc.mjs +333 -0
- package/dist/circuit/index.d.mts +5 -92
- package/dist/circuit/index.mjs +5 -332
- package/dist/circuit/network.d.mts +99 -0
- package/dist/circuit/network.mjs +440 -0
- package/dist/circuit/topology.d.mts +102 -0
- package/dist/circuit/topology.mjs +143 -0
- package/dist/colour/absorption.d.mts +79 -0
- package/dist/colour/absorption.mjs +137 -0
- package/dist/colour/index.d.mts +6 -0
- package/dist/colour/index.mjs +7 -0
- package/dist/colour/name.d.mts +14 -0
- package/dist/colour/name.mjs +76 -0
- package/dist/colour/observer.d.mts +31 -0
- package/dist/colour/observer.mjs +46 -0
- package/dist/colour/spectrum.d.mts +61 -0
- package/dist/colour/spectrum.mjs +108 -0
- package/dist/colour/srgb.d.mts +49 -0
- package/dist/colour/srgb.mjs +108 -0
- package/dist/core/constants.d.mts +138 -0
- package/dist/core/constants.mjs +139 -0
- package/dist/core/index.d.mts +4 -1
- package/dist/core/index.mjs +4 -1
- package/dist/core/math.d.mts +26 -0
- package/dist/core/math.mjs +37 -0
- package/dist/core/vec3.d.mts +94 -0
- package/dist/core/vec3.mjs +123 -0
- package/dist/core/worked.d.mts +35 -0
- package/dist/core/worked.mjs +44 -0
- package/dist/electro/cell.d.mts +102 -0
- package/dist/electro/cell.mjs +170 -0
- package/dist/electro/conductivity.d.mts +157 -0
- package/dist/electro/conductivity.mjs +156 -0
- package/dist/electro/couples.d.mts +114 -0
- package/dist/electro/couples.mjs +334 -0
- package/dist/electro/electrolysis.d.mts +96 -0
- package/dist/electro/electrolysis.mjs +274 -0
- package/dist/electro/faraday.d.mts +150 -0
- package/dist/electro/faraday.mjs +118 -0
- package/dist/electro/index.d.mts +6 -0
- package/dist/electro/index.mjs +7 -0
- package/dist/finance/accounting/adjustments.d.mts +17 -0
- package/dist/finance/accounting/adjustments.mjs +202 -0
- package/dist/finance/accounting/analysis.d.mts +8 -0
- package/dist/finance/accounting/analysis.mjs +205 -0
- package/dist/finance/accounting/clubs.d.mts +21 -0
- package/dist/finance/accounting/clubs.mjs +217 -0
- package/dist/finance/accounting/company-statements.d.mts +7 -0
- package/dist/finance/accounting/company-statements.mjs +150 -0
- package/dist/finance/accounting/harness.d.mts +7 -0
- package/dist/finance/accounting/harness.mjs +45 -0
- package/dist/finance/accounting/index.d.mts +18 -0
- package/dist/finance/accounting/index.mjs +18 -0
- package/dist/finance/accounting/journalize.d.mts +16 -0
- package/dist/finance/accounting/journalize.mjs +128 -0
- package/dist/finance/accounting/manufacturing.d.mts +8 -0
- package/dist/finance/accounting/manufacturing.mjs +236 -0
- package/dist/finance/accounting/partnership.d.mts +7 -0
- package/dist/finance/accounting/partnership.mjs +152 -0
- package/dist/finance/accounting/period-case.d.mts +6 -0
- package/dist/finance/accounting/period-case.mjs +71 -0
- package/dist/finance/accounting/post.d.mts +9 -0
- package/dist/finance/accounting/post.mjs +84 -0
- package/dist/finance/accounting/precision.d.mts +9 -0
- package/dist/finance/accounting/precision.mjs +15 -0
- package/dist/finance/accounting/rules.d.mts +21 -0
- package/dist/finance/accounting/rules.mjs +37 -0
- package/dist/finance/accounting/solve.d.mts +28 -0
- package/dist/finance/accounting/solve.mjs +92 -0
- package/dist/finance/accounting/statements.d.mts +7 -0
- package/dist/finance/accounting/statements.mjs +142 -0
- package/dist/finance/accounting/types.d.mts +649 -0
- package/dist/finance/accounting/validate.d.mts +7 -0
- package/dist/finance/accounting/validate.mjs +67 -0
- package/dist/finance/accounting/verification.d.mts +24 -0
- package/dist/finance/accounting/verification.mjs +386 -0
- package/dist/finance/bizsim.d.mts +75 -0
- package/dist/finance/bizsim.mjs +296 -0
- package/dist/finance/index.d.mts +95 -0
- package/dist/finance/index.mjs +145 -0
- package/dist/finance/investment-math.d.mts +7 -0
- package/dist/finance/investment-math.mjs +18 -0
- package/dist/finance/management-accounting/budgeting.d.mts +7 -0
- package/dist/finance/management-accounting/budgeting.mjs +189 -0
- package/dist/finance/management-accounting/cash-budget.d.mts +7 -0
- package/dist/finance/management-accounting/cash-budget.mjs +154 -0
- package/dist/finance/management-accounting/costing.d.mts +8 -0
- package/dist/finance/management-accounting/costing.mjs +175 -0
- package/dist/finance/management-accounting/decisions.d.mts +8 -0
- package/dist/finance/management-accounting/decisions.mjs +164 -0
- package/dist/finance/management-accounting/index.d.mts +13 -0
- package/dist/finance/management-accounting/index.mjs +13 -0
- package/dist/finance/management-accounting/integrated-budget.d.mts +8 -0
- package/dist/finance/management-accounting/integrated-budget.mjs +67 -0
- package/dist/finance/management-accounting/inventory-costing.d.mts +7 -0
- package/dist/finance/management-accounting/inventory-costing.mjs +173 -0
- package/dist/finance/management-accounting/investment-appraisal.d.mts +7 -0
- package/dist/finance/management-accounting/investment-appraisal.mjs +148 -0
- package/dist/finance/management-accounting/management-case.d.mts +8 -0
- package/dist/finance/management-accounting/management-case.mjs +91 -0
- package/dist/finance/management-accounting/master-budget.d.mts +7 -0
- package/dist/finance/management-accounting/master-budget.mjs +137 -0
- package/dist/finance/management-accounting/production-costing.d.mts +8 -0
- package/dist/finance/management-accounting/production-costing.mjs +214 -0
- package/dist/finance/management-accounting/types.d.mts +644 -0
- package/dist/finance/management-accounting/variances.d.mts +7 -0
- package/dist/finance/management-accounting/variances.mjs +150 -0
- package/dist/index.d.mts +9 -8
- package/dist/index.mjs +5 -5
- package/dist/interaction/MovableDot.mjs +19 -0
- package/dist/interaction/useDraggable.mjs +24 -4
- package/dist/math/analysis.d.mts +61 -0
- package/dist/math/analysis.mjs +187 -0
- package/dist/math/answer-check.d.mts +50 -0
- package/dist/math/answer-check.mjs +106 -0
- package/dist/math/calculus.d.mts +17 -1
- package/dist/math/calculus.mjs +365 -2
- package/dist/math/complex.d.mts +93 -0
- package/dist/math/complex.mjs +239 -0
- package/dist/math/expr.d.mts +23 -0
- package/dist/math/expr.mjs +36 -0
- package/dist/math/index.d.mts +9 -23
- package/dist/math/index.mjs +9 -38
- package/dist/math/latex.mjs +10 -1
- package/dist/math/parse.mjs +1 -1
- package/dist/math/poly.d.mts +55 -0
- package/dist/math/poly.mjs +273 -0
- package/dist/math/rearrange.d.mts +14 -0
- package/dist/math/rearrange.mjs +125 -0
- package/dist/math/solve.d.mts +21 -0
- package/dist/math/solve.mjs +75 -0
- package/dist/networking/addressing.d.mts +26 -0
- package/dist/networking/addressing.mjs +33 -0
- package/dist/networking/cloud/access.d.mts +36 -0
- package/dist/networking/cloud/access.mjs +95 -0
- package/dist/networking/cloud/containers.d.mts +43 -0
- package/dist/networking/cloud/containers.mjs +54 -0
- package/dist/networking/cloud/edge.d.mts +17 -0
- package/dist/networking/cloud/edge.mjs +31 -0
- package/dist/networking/cloud/failure-domains.d.mts +19 -0
- package/dist/networking/cloud/failure-domains.mjs +22 -0
- package/dist/networking/cloud/geo-routing.d.mts +22 -0
- package/dist/networking/cloud/geo-routing.mjs +64 -0
- package/dist/networking/cloud/index.d.mts +18 -0
- package/dist/networking/cloud/index.mjs +19 -0
- package/dist/networking/cloud/inference-reliability.d.mts +30 -0
- package/dist/networking/cloud/inference-reliability.mjs +76 -0
- package/dist/networking/cloud/inference.d.mts +118 -0
- package/dist/networking/cloud/inference.mjs +179 -0
- package/dist/networking/cloud/infrastructure.d.mts +45 -0
- package/dist/networking/cloud/infrastructure.mjs +96 -0
- package/dist/networking/cloud/observability.d.mts +24 -0
- package/dist/networking/cloud/observability.mjs +34 -0
- package/dist/networking/cloud/orchestration.d.mts +32 -0
- package/dist/networking/cloud/orchestration.mjs +38 -0
- package/dist/networking/cloud/recovery.d.mts +21 -0
- package/dist/networking/cloud/recovery.mjs +27 -0
- package/dist/networking/cloud/releases.d.mts +42 -0
- package/dist/networking/cloud/releases.mjs +135 -0
- package/dist/networking/cloud/scaling.d.mts +25 -0
- package/dist/networking/cloud/scaling.mjs +65 -0
- package/dist/networking/cloud/secrets.d.mts +39 -0
- package/dist/networking/cloud/secrets.mjs +68 -0
- package/dist/networking/cloud/server-deployment.d.mts +29 -0
- package/dist/networking/cloud/server-deployment.mjs +72 -0
- package/dist/networking/cloud/storage.d.mts +16 -0
- package/dist/networking/cloud/storage.mjs +58 -0
- package/dist/networking/cloud/vpc.d.mts +18 -0
- package/dist/networking/cloud/vpc.mjs +100 -0
- package/dist/networking/delivery.d.mts +34 -0
- package/dist/networking/delivery.mjs +52 -0
- package/dist/networking/index.d.mts +47 -0
- package/dist/networking/index.mjs +47 -0
- package/dist/networking/ipv6.d.mts +28 -0
- package/dist/networking/ipv6.mjs +17 -0
- package/dist/networking/journeys.d.mts +83 -0
- package/dist/networking/journeys.mjs +161 -0
- package/dist/networking/models/airtime.d.mts +87 -0
- package/dist/networking/models/airtime.mjs +130 -0
- package/dist/networking/models/cellular.d.mts +157 -0
- package/dist/networking/models/cellular.mjs +252 -0
- package/dist/networking/models/encapsulation.d.mts +98 -0
- package/dist/networking/models/encapsulation.mjs +132 -0
- package/dist/networking/models/handover.d.mts +116 -0
- package/dist/networking/models/handover.mjs +209 -0
- package/dist/networking/models/handshake.d.mts +90 -0
- package/dist/networking/models/handshake.mjs +122 -0
- package/dist/networking/models/index.d.mts +14 -0
- package/dist/networking/models/index.mjs +15 -0
- package/dist/networking/models/media.d.mts +82 -0
- package/dist/networking/models/media.mjs +188 -0
- package/dist/networking/models/satellite.d.mts +86 -0
- package/dist/networking/models/satellite.mjs +121 -0
- package/dist/networking/models/spectrum.d.mts +83 -0
- package/dist/networking/models/spectrum.mjs +235 -0
- package/dist/networking/models/switch.d.mts +80 -0
- package/dist/networking/models/switch.mjs +155 -0
- package/dist/networking/models/vlan.d.mts +62 -0
- package/dist/networking/models/vlan.mjs +100 -0
- package/dist/networking/models/vpn.d.mts +66 -0
- package/dist/networking/models/vpn.mjs +125 -0
- package/dist/networking/models/wifi-privacy.d.mts +82 -0
- package/dist/networking/models/wifi-privacy.mjs +130 -0
- package/dist/networking/models/wifi.d.mts +240 -0
- package/dist/networking/models/wifi.mjs +562 -0
- package/dist/networking/nat-traversal.d.mts +24 -0
- package/dist/networking/nat-traversal.mjs +38 -0
- package/dist/networking/protocols.d.mts +17 -0
- package/dist/networking/protocols.mjs +57 -0
- package/dist/networking/queue.d.mts +12 -0
- package/dist/networking/queue.mjs +18 -0
- package/dist/networking/route-learning.d.mts +23 -0
- package/dist/networking/route-learning.mjs +43 -0
- package/dist/networking/routing.d.mts +11 -0
- package/dist/networking/routing.mjs +25 -0
- package/dist/networking/signals.d.mts +26 -0
- package/dist/networking/signals.mjs +35 -0
- package/dist/networking/subnet.d.mts +49 -0
- package/dist/networking/subnet.mjs +89 -0
- package/dist/networking/tcp-reliability.d.mts +24 -0
- package/dist/networking/tcp-reliability.mjs +38 -0
- package/dist/networking/topology/contract.d.mts +123 -0
- package/dist/networking/topology/index.d.mts +4 -0
- package/dist/networking/topology/index.mjs +4 -0
- package/dist/networking/topology/presets.d.mts +7 -0
- package/dist/networking/topology/presets.mjs +302 -0
- package/dist/networking/topology/simulation.d.mts +8 -0
- package/dist/networking/topology/simulation.mjs +179 -0
- package/dist/networking/wireless.d.mts +11 -0
- package/dist/networking/wireless.mjs +17 -0
- package/dist/optics/imaging.d.mts +218 -0
- package/dist/optics/imaging.mjs +276 -0
- package/dist/optics/index.d.mts +7 -0
- package/dist/optics/index.mjs +8 -0
- package/dist/optics/laws.d.mts +70 -0
- package/dist/optics/laws.mjs +195 -0
- package/dist/optics/prism.d.mts +148 -0
- package/dist/optics/prism.mjs +197 -0
- package/dist/optics/refraction.d.mts +201 -0
- package/dist/optics/refraction.mjs +270 -0
- package/dist/optics/wave-optics.d.mts +171 -0
- package/dist/optics/wave-optics.mjs +259 -0
- package/dist/physics/ac/index.d.mts +183 -0
- package/dist/physics/ac/index.mjs +203 -0
- package/dist/physics/dynamics/forces.d.mts +98 -0
- package/dist/physics/dynamics/forces.mjs +153 -0
- package/dist/physics/dynamics/friction.d.mts +76 -0
- package/dist/physics/dynamics/friction.mjs +119 -0
- package/dist/physics/dynamics/system.d.mts +68 -0
- package/dist/physics/dynamics/system.mjs +125 -0
- package/dist/physics/electrostatics/index.d.mts +169 -0
- package/dist/physics/electrostatics/index.mjs +249 -0
- package/dist/physics/energy/centre-of-mass.d.mts +115 -0
- package/dist/physics/energy/centre-of-mass.mjs +180 -0
- package/dist/physics/energy/conservation.d.mts +81 -0
- package/dist/physics/energy/conservation.mjs +129 -0
- package/dist/physics/energy/power.d.mts +90 -0
- package/dist/physics/energy/power.mjs +167 -0
- package/dist/physics/energy/spring.d.mts +73 -0
- package/dist/physics/energy/spring.mjs +129 -0
- package/dist/physics/energy/store.d.mts +63 -0
- package/dist/physics/energy/store.mjs +108 -0
- package/dist/physics/energy/theorem.d.mts +65 -0
- package/dist/physics/energy/theorem.mjs +113 -0
- package/dist/physics/energy/work.d.mts +114 -0
- package/dist/physics/energy/work.mjs +219 -0
- package/dist/physics/gravitation/body.d.mts +85 -0
- package/dist/physics/gravitation/body.mjs +168 -0
- package/dist/physics/gravitation/kepler.d.mts +127 -0
- package/dist/physics/gravitation/kepler.mjs +216 -0
- package/dist/physics/gravitation/law.d.mts +117 -0
- package/dist/physics/gravitation/law.mjs +175 -0
- package/dist/physics/gravitation/orbit.d.mts +119 -0
- package/dist/physics/gravitation/orbit.mjs +202 -0
- package/dist/physics/gravitation/potential.d.mts +114 -0
- package/dist/physics/gravitation/potential.mjs +202 -0
- package/dist/physics/gravitation/variation.d.mts +97 -0
- package/dist/physics/gravitation/variation.mjs +175 -0
- package/dist/physics/index.d.mts +35 -0
- package/dist/physics/index.mjs +36 -0
- package/dist/physics/integral-sweep.d.mts +63 -0
- package/dist/physics/integral-sweep.mjs +126 -0
- package/dist/physics/kinematics/equations.d.mts +47 -0
- package/dist/physics/kinematics/equations.mjs +126 -0
- package/dist/physics/kinematics/free-fall.d.mts +53 -0
- package/dist/physics/kinematics/free-fall.mjs +71 -0
- package/dist/physics/kinematics/given.d.mts +16 -0
- package/dist/physics/kinematics/given.mjs +55 -0
- package/dist/physics/kinematics/roots.d.mts +41 -0
- package/dist/physics/kinematics/roots.mjs +72 -0
- package/dist/physics/kinematics/solve.d.mts +52 -0
- package/dist/physics/kinematics/solve.mjs +172 -0
- package/dist/physics/magnetism/biot-savart.d.mts +161 -0
- package/dist/physics/magnetism/biot-savart.mjs +353 -0
- package/dist/physics/magnetism/flux.d.mts +94 -0
- package/dist/physics/magnetism/flux.mjs +313 -0
- package/dist/physics/magnetism/geomagnetism.d.mts +151 -0
- package/dist/physics/magnetism/geomagnetism.mjs +184 -0
- package/dist/physics/magnetism/index.d.mts +12 -0
- package/dist/physics/magnetism/index.mjs +74 -0
- package/dist/physics/magnetism/lorentz.d.mts +28 -0
- package/dist/physics/magnetism/lorentz.mjs +88 -0
- package/dist/physics/magnetism/magnetic-force.d.mts +102 -0
- package/dist/physics/magnetism/magnetic-force.mjs +169 -0
- package/dist/physics/momentum/collide.d.mts +77 -0
- package/dist/physics/momentum/collide.mjs +115 -0
- package/dist/physics/momentum/impulse.d.mts +89 -0
- package/dist/physics/momentum/impulse.mjs +159 -0
- package/dist/physics/momentum/planar.d.mts +60 -0
- package/dist/physics/momentum/planar.mjs +110 -0
- package/dist/physics/projectile.d.mts +107 -0
- package/dist/physics/projectile.mjs +185 -0
- package/dist/physics/rotation/angular.d.mts +85 -0
- package/dist/physics/rotation/angular.mjs +130 -0
- package/dist/physics/rotation/circular.d.mts +79 -0
- package/dist/physics/rotation/circular.mjs +131 -0
- package/dist/physics/rotation/inertia.d.mts +164 -0
- package/dist/physics/rotation/inertia.mjs +332 -0
- package/dist/physics/rotation/torque.d.mts +65 -0
- package/dist/physics/rotation/torque.mjs +134 -0
- package/dist/physics/vectors.d.mts +64 -0
- package/dist/physics/vectors.mjs +114 -0
- package/dist/primitives/Dot.d.mts +2 -15
- package/dist/primitives/Dot.mjs +6 -4
- package/dist/primitives/Grid.d.mts +33 -17
- package/dist/primitives/Grid.mjs +89 -17
- package/dist/primitives/Label.d.mts +1 -14
- package/dist/primitives/Label.mjs +3 -2
- package/dist/primitives/Lines.d.mts +4 -32
- package/dist/primitives/Lines.mjs +10 -8
- package/dist/primitives/Shapes.d.mts +5 -43
- package/dist/primitives/Shapes.mjs +12 -10
- package/dist/primitives/index.d.mts +2 -2
- package/dist/primitives/index.mjs +2 -2
- package/dist/primitives/props.mjs +31 -0
- package/dist/quantity/index.d.mts +119 -0
- package/dist/quantity/index.mjs +417 -0
- package/dist/relation/derive.d.mts +74 -0
- package/dist/relation/derive.mjs +73 -0
- package/dist/relation/index.d.mts +56 -0
- package/dist/relation/index.mjs +234 -0
- package/dist/scene/Scene.d.mts +6 -1
- package/dist/scene/Scene.mjs +15 -40
- package/dist/scene/evaluators.mjs +1 -1
- package/dist/sim/thermal.mjs +45 -20
- package/dist/thermo/calorimetry.d.mts +207 -0
- package/dist/thermo/calorimetry.mjs +345 -0
- package/dist/thermo/cycles.d.mts +142 -0
- package/dist/thermo/cycles.mjs +256 -0
- package/dist/thermo/entropy.d.mts +87 -0
- package/dist/thermo/entropy.mjs +140 -0
- package/dist/thermo/expansion.d.mts +130 -0
- package/dist/thermo/expansion.mjs +178 -0
- package/dist/thermo/gas.d.mts +197 -0
- package/dist/thermo/gas.mjs +279 -0
- package/dist/thermo/heat-transfer.d.mts +164 -0
- package/dist/thermo/heat-transfer.mjs +217 -0
- package/dist/thermo/index.d.mts +9 -82
- package/dist/thermo/index.mjs +9 -132
- package/dist/thermo/processes.d.mts +95 -0
- package/dist/thermo/processes.mjs +154 -0
- package/dist/thermo/temperature.d.mts +174 -0
- package/dist/thermo/temperature.mjs +236 -0
- package/dist/view/Stage.mjs +4 -11
- package/dist/waves/damping.d.mts +224 -0
- package/dist/waves/damping.mjs +317 -0
- package/dist/waves/doppler.d.mts +72 -0
- package/dist/waves/doppler.mjs +125 -0
- package/dist/waves/index.d.mts +10 -0
- package/dist/waves/index.mjs +10 -0
- package/dist/waves/pendulum.d.mts +130 -0
- package/dist/waves/pendulum.mjs +211 -0
- package/dist/waves/pitch.d.mts +125 -0
- package/dist/waves/pitch.mjs +158 -0
- package/dist/waves/shm.d.mts +170 -0
- package/dist/waves/shm.mjs +279 -0
- package/dist/waves/springs.d.mts +103 -0
- package/dist/waves/springs.mjs +176 -0
- package/dist/waves/superposition.d.mts +124 -0
- package/dist/waves/superposition.mjs +196 -0
- package/dist/waves/wave.d.mts +154 -0
- package/dist/waves/wave.mjs +178 -0
- package/package.json +103 -23
- package/styles.css +125 -8
- package/dist/assets/kit/index.mjs +0 -4
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
import { relation } from "../../relation/index.mjs";
|
|
2
|
+
|
|
3
|
+
//#region src/physics/kinematics/equations.ts
|
|
4
|
+
/**
|
|
5
|
+
* The five SUVAT equations, declared once with their units.
|
|
6
|
+
*
|
|
7
|
+
* This file is the single source of truth for what the equations ARE. Everything else in this
|
|
8
|
+
* directory reads them: the chooser picks one, the solver rearranges one, the derivation prints
|
|
9
|
+
* one. Nothing rewrites them, which is the property that stops a second, subtly different copy of
|
|
10
|
+
* `s = ut + ½at²` appearing somewhere and being wrong in a way that looks right.
|
|
11
|
+
*/
|
|
12
|
+
const MOTION_VARS = [
|
|
13
|
+
"u",
|
|
14
|
+
"v",
|
|
15
|
+
"a",
|
|
16
|
+
"s",
|
|
17
|
+
"t"
|
|
18
|
+
];
|
|
19
|
+
/** What each symbol means, for a lesson that lists them and for error messages that name them. */
|
|
20
|
+
const MOTION_NAMES = {
|
|
21
|
+
u: "initial velocity",
|
|
22
|
+
v: "final velocity",
|
|
23
|
+
a: "acceleration",
|
|
24
|
+
s: "displacement",
|
|
25
|
+
t: "time"
|
|
26
|
+
};
|
|
27
|
+
/**
|
|
28
|
+
* The unit each quantity is held in, spelled for the UNIT PARSER.
|
|
29
|
+
*
|
|
30
|
+
* These strings are machine input, not display text. `m/s^2` is how `parseUnit` reads metres per
|
|
31
|
+
* second squared; it is not how a physics paper prints it, and putting it on screen is how a
|
|
32
|
+
* derivation ends up with a stray caret in it.
|
|
33
|
+
*/
|
|
34
|
+
const MOTION_UNITS = {
|
|
35
|
+
u: "m/s",
|
|
36
|
+
v: "m/s",
|
|
37
|
+
a: "m/s^2",
|
|
38
|
+
s: "m",
|
|
39
|
+
t: "s"
|
|
40
|
+
};
|
|
41
|
+
/**
|
|
42
|
+
* The same units spelled for DISPLAY, as LaTeX.
|
|
43
|
+
*
|
|
44
|
+
* Index notation (`m s⁻²`) rather than a solidus, because that is the convention in every physics
|
|
45
|
+
* paper these students will sit, and upright roman rather than italic, because an italic `m` is a
|
|
46
|
+
* variable and an upright one is metres. The thin space between the symbols is not decoration: it
|
|
47
|
+
* is what distinguishes `m s` (metre-seconds) from `ms` (milliseconds).
|
|
48
|
+
*/
|
|
49
|
+
const MOTION_UNITS_TEX = {
|
|
50
|
+
u: "\\mathrm{m\\,s^{-1}}",
|
|
51
|
+
v: "\\mathrm{m\\,s^{-1}}",
|
|
52
|
+
a: "\\mathrm{m\\,s^{-2}}",
|
|
53
|
+
s: "\\mathrm{m}",
|
|
54
|
+
t: "\\mathrm{s}"
|
|
55
|
+
};
|
|
56
|
+
const units = MOTION_UNITS;
|
|
57
|
+
/**
|
|
58
|
+
* The five equations.
|
|
59
|
+
*
|
|
60
|
+
* `s = vt − ½at²` is the one most textbooks omit, and then they have to fudge every question that
|
|
61
|
+
* gives the FINAL velocity and asks for the displacement. It is included for the same reason the
|
|
62
|
+
* other four are: leaving it out would mean one of the five choices has no equation behind it, and
|
|
63
|
+
* the method would stop being reliable exactly once per chapter.
|
|
64
|
+
*/
|
|
65
|
+
const MOTION_EQUATIONS = [
|
|
66
|
+
{
|
|
67
|
+
id: "v=u+at",
|
|
68
|
+
relation: relation("v = u + a*t", {
|
|
69
|
+
v: units.v,
|
|
70
|
+
u: units.u,
|
|
71
|
+
a: units.a,
|
|
72
|
+
t: units.t
|
|
73
|
+
}, "v = u + at"),
|
|
74
|
+
omits: "s",
|
|
75
|
+
quadraticInTime: false
|
|
76
|
+
},
|
|
77
|
+
{
|
|
78
|
+
id: "s=(u+v)t/2",
|
|
79
|
+
relation: relation("s = 0.5*(u + v)*t", {
|
|
80
|
+
s: units.s,
|
|
81
|
+
u: units.u,
|
|
82
|
+
v: units.v,
|
|
83
|
+
t: units.t
|
|
84
|
+
}, "s = \\tfrac{1}{2}(u + v)t"),
|
|
85
|
+
omits: "a",
|
|
86
|
+
quadraticInTime: false
|
|
87
|
+
},
|
|
88
|
+
{
|
|
89
|
+
id: "s=ut+at^2/2",
|
|
90
|
+
relation: relation("s = u*t + 0.5*a*t^2", {
|
|
91
|
+
s: units.s,
|
|
92
|
+
u: units.u,
|
|
93
|
+
a: units.a,
|
|
94
|
+
t: units.t
|
|
95
|
+
}, "s = ut + \\tfrac{1}{2}at^2"),
|
|
96
|
+
omits: "v",
|
|
97
|
+
quadraticInTime: true
|
|
98
|
+
},
|
|
99
|
+
{
|
|
100
|
+
id: "v^2=u^2+2as",
|
|
101
|
+
relation: relation("v^2 = u^2 + 2*a*s", {
|
|
102
|
+
v: units.v,
|
|
103
|
+
u: units.u,
|
|
104
|
+
a: units.a,
|
|
105
|
+
s: units.s
|
|
106
|
+
}, "v^2 = u^2 + 2as"),
|
|
107
|
+
omits: "t",
|
|
108
|
+
quadraticInTime: false
|
|
109
|
+
},
|
|
110
|
+
{
|
|
111
|
+
id: "s=vt-at^2/2",
|
|
112
|
+
relation: relation("s = v*t - 0.5*a*t^2", {
|
|
113
|
+
s: units.s,
|
|
114
|
+
v: units.v,
|
|
115
|
+
a: units.a,
|
|
116
|
+
t: units.t
|
|
117
|
+
}, "s = vt - \\tfrac{1}{2}at^2"),
|
|
118
|
+
omits: "u",
|
|
119
|
+
quadraticInTime: true
|
|
120
|
+
}
|
|
121
|
+
];
|
|
122
|
+
/** The equation that leaves out a given quantity. Exactly one does, which is the whole method. */
|
|
123
|
+
const equationWithout = (omitted) => MOTION_EQUATIONS.find((e) => e.omits === omitted);
|
|
124
|
+
|
|
125
|
+
//#endregion
|
|
126
|
+
export { MOTION_EQUATIONS, MOTION_NAMES, MOTION_UNITS, MOTION_UNITS_TEX, MOTION_VARS, equationWithout };
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { SignConvention } from "../vectors.mjs";
|
|
2
|
+
import { MotionGiven } from "./given.mjs";
|
|
3
|
+
|
|
4
|
+
//#region src/physics/kinematics/free-fall.d.ts
|
|
5
|
+
declare const G_EARTH = 9.8;
|
|
6
|
+
interface VerticalMotion {
|
|
7
|
+
/**
|
|
8
|
+
* Initial speed as a MAGNITUDE, always positive. Which way it goes is `direction`, not a sign:
|
|
9
|
+
* asking a caller to pre-sign this is asking them to do the step that goes wrong.
|
|
10
|
+
*/
|
|
11
|
+
readonly speed?: number;
|
|
12
|
+
/** Which way it was launched. Omit `speed` or pass 0 for a body simply released. */
|
|
13
|
+
readonly direction?: 'up' | 'down';
|
|
14
|
+
/**
|
|
15
|
+
* How far the landing point is BELOW the launch point, as a positive distance. A stone thrown
|
|
16
|
+
* from a 58.8 m tower that lands at the foot has `fallsBy: 58.8`; one that returns to the hand
|
|
17
|
+
* has `fallsBy: 0`.
|
|
18
|
+
*/
|
|
19
|
+
readonly fallsBy?: number;
|
|
20
|
+
readonly g?: number;
|
|
21
|
+
/** Which direction the resulting numbers call positive. Defaults to up, the usual choice. */
|
|
22
|
+
readonly convention?: SignConvention;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* The signed `u`, `a` and `s` for a vertical motion, ready for {@link motion}.
|
|
26
|
+
*
|
|
27
|
+
* ```ts
|
|
28
|
+
* // Reference example 18: thrown up at 19.6 m/s from a 58.8 m tower.
|
|
29
|
+
* motion('t', vertical({ speed: 19.6, direction: 'up', fallsBy: 58.8 })); // 6 s
|
|
30
|
+
* // The same flight described the other way up. Same answer.
|
|
31
|
+
* motion('t', vertical({ speed: 19.6, direction: 'up', fallsBy: 58.8, convention: downPositive() }));
|
|
32
|
+
* ```
|
|
33
|
+
*/
|
|
34
|
+
declare function vertical(m: VerticalMotion): MotionGiven & {
|
|
35
|
+
u: number;
|
|
36
|
+
a: number;
|
|
37
|
+
s: number;
|
|
38
|
+
};
|
|
39
|
+
/** A body simply released from rest, falling `distance` metres. */
|
|
40
|
+
declare const dropped: (distance: number, g?: number) => MotionGiven & {
|
|
41
|
+
u: number;
|
|
42
|
+
a: number;
|
|
43
|
+
s: number;
|
|
44
|
+
};
|
|
45
|
+
/**
|
|
46
|
+
* A sentence describing the signs, for a lesson to print above the working.
|
|
47
|
+
*
|
|
48
|
+
* Saying this out loud once is worth more than any number of remembered formula variants, because
|
|
49
|
+
* it is the only step a learner has to get right before the equations take over.
|
|
50
|
+
*/
|
|
51
|
+
declare function describeSigns(m: VerticalMotion): string;
|
|
52
|
+
//#endregion
|
|
53
|
+
export { G_EARTH, VerticalMotion, describeSigns, dropped, vertical };
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import { upPositive } from "../vectors.mjs";
|
|
2
|
+
|
|
3
|
+
//#region src/physics/kinematics/free-fall.ts
|
|
4
|
+
/**
|
|
5
|
+
* Vertical motion under gravity: turning a sentence into signed numbers.
|
|
6
|
+
*
|
|
7
|
+
* THERE ARE NO FREE-FALL EQUATIONS. There is SUVAT with `a = ±g`, and the only new thing a falling
|
|
8
|
+
* body brings is the question of which sign, which is a question about how you chose to describe
|
|
9
|
+
* the motion rather than about the motion.
|
|
10
|
+
*
|
|
11
|
+
* This matters because it is where textbooks multiply. A typical chapter prints three sets:
|
|
12
|
+
*
|
|
13
|
+
* falling: v = u + gt, h = ut + ½gt²
|
|
14
|
+
* thrown upwards: v = u − gt, h = ut − ½gt²
|
|
15
|
+
* thrown up, landing below: v = −u + gt, h = −ut + ½gt²
|
|
16
|
+
*
|
|
17
|
+
* Those are one equation written three times with the signs pre-substituted, and a student is
|
|
18
|
+
* expected to remember which is which. They are all `s = ut + ½at²`. The third is simply the first
|
|
19
|
+
* with down chosen as positive, so an upward launch makes `u` negative. Memorising three is harder
|
|
20
|
+
* than understanding one AND it fails on the fourth case, the one the chapter did not print.
|
|
21
|
+
*
|
|
22
|
+
* So what this module provides is not equations. It is the TRANSLATION: a description in words
|
|
23
|
+
* becomes the signed `u`, `a` and `s` that the one equation set needs, done once, visibly, and in a
|
|
24
|
+
* way that can be flipped to the other convention to show the answer does not depend on it.
|
|
25
|
+
*/
|
|
26
|
+
const G_EARTH = 9.8;
|
|
27
|
+
/**
|
|
28
|
+
* The signed `u`, `a` and `s` for a vertical motion, ready for {@link motion}.
|
|
29
|
+
*
|
|
30
|
+
* ```ts
|
|
31
|
+
* // Reference example 18: thrown up at 19.6 m/s from a 58.8 m tower.
|
|
32
|
+
* motion('t', vertical({ speed: 19.6, direction: 'up', fallsBy: 58.8 })); // 6 s
|
|
33
|
+
* // The same flight described the other way up. Same answer.
|
|
34
|
+
* motion('t', vertical({ speed: 19.6, direction: 'up', fallsBy: 58.8, convention: downPositive() }));
|
|
35
|
+
* ```
|
|
36
|
+
*/
|
|
37
|
+
function vertical(m) {
|
|
38
|
+
const convention = m.convention ?? upPositive();
|
|
39
|
+
const g = m.g ?? 9.8;
|
|
40
|
+
const speed = m.speed ?? 0;
|
|
41
|
+
const direction = m.direction ?? "down";
|
|
42
|
+
return {
|
|
43
|
+
u: speed === 0 ? 0 : convention.signed(speed, direction),
|
|
44
|
+
a: convention.gravity(g),
|
|
45
|
+
s: convention.signed(m.fallsBy ?? 0, "down")
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
/** A body simply released from rest, falling `distance` metres. */
|
|
49
|
+
const dropped = (distance, g = G_EARTH) => vertical({
|
|
50
|
+
fallsBy: distance,
|
|
51
|
+
g
|
|
52
|
+
});
|
|
53
|
+
/**
|
|
54
|
+
* A sentence describing the signs, for a lesson to print above the working.
|
|
55
|
+
*
|
|
56
|
+
* Saying this out loud once is worth more than any number of remembered formula variants, because
|
|
57
|
+
* it is the only step a learner has to get right before the equations take over.
|
|
58
|
+
*/
|
|
59
|
+
function describeSigns(m) {
|
|
60
|
+
const convention = m.convention ?? upPositive();
|
|
61
|
+
const g = m.g ?? 9.8;
|
|
62
|
+
const signed = vertical(m);
|
|
63
|
+
const parts = [`Taking ${convention.positive} as positive`];
|
|
64
|
+
if (signed.u !== 0) parts.push(`it is thrown ${m.direction ?? "down"}, so u = ${signed.u} m/s`);
|
|
65
|
+
parts.push(`gravity acts down, so a = ${convention.gravity(g)} m/s²`);
|
|
66
|
+
if (signed.s !== 0) parts.push(`and it ends ${Math.abs(m.fallsBy ?? 0)} m below the start, so s = ${signed.s} m`);
|
|
67
|
+
return `${parts.join(", ")}.`;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
//#endregion
|
|
71
|
+
export { G_EARTH, describeSigns, dropped, vertical };
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { Given } from "../../relation/index.mjs";
|
|
2
|
+
import { MotionEquation, MotionVar } from "./equations.mjs";
|
|
3
|
+
|
|
4
|
+
//#region src/physics/kinematics/given.d.ts
|
|
5
|
+
/** Values supplied to the solver: bare numbers in SI, or quantities in any compatible unit. */
|
|
6
|
+
type MotionGiven = Partial<Record<MotionVar, Given>>;
|
|
7
|
+
/**
|
|
8
|
+
* Which equation answers this question, and why.
|
|
9
|
+
*
|
|
10
|
+
* Throws with a message naming what is still needed, rather than guessing or returning null. A
|
|
11
|
+
* learner who has given two quantities has not made a type error, they have not finished reading
|
|
12
|
+
* the question, and the message should say which quantity is missing.
|
|
13
|
+
*/
|
|
14
|
+
declare function chooseEquation(target: MotionVar, given: MotionGiven): MotionEquation;
|
|
15
|
+
//#endregion
|
|
16
|
+
export { MotionGiven, chooseEquation };
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { Quantity } from "../../quantity/index.mjs";
|
|
2
|
+
import { MOTION_EQUATIONS, MOTION_NAMES, MOTION_UNITS, MOTION_VARS, equationWithout } from "./equations.mjs";
|
|
3
|
+
|
|
4
|
+
//#region src/physics/kinematics/given.ts
|
|
5
|
+
/**
|
|
6
|
+
* What the caller supplied, and choosing the equation that fits it.
|
|
7
|
+
*
|
|
8
|
+
* The chooser is the part worth reading. Five quantities, four in every equation, so there is
|
|
9
|
+
* exactly one equation that omits any given quantity, and the choice is therefore forced rather
|
|
10
|
+
* than a matter of taste:
|
|
11
|
+
*
|
|
12
|
+
* list what you know, name what you want, and use the equation that leaves out the one
|
|
13
|
+
* quantity you neither know nor want.
|
|
14
|
+
*
|
|
15
|
+
* It is exported on its own because the choice is worth asking a learner to make before the answer
|
|
16
|
+
* is revealed. "Which equation would you use?" is a much better question than "what is the answer",
|
|
17
|
+
* and it is the one a static page of worked examples can never ask.
|
|
18
|
+
*/
|
|
19
|
+
const isGiven = (given, key) => given[key] !== void 0 && given[key] !== null;
|
|
20
|
+
/** The supplied values as plain SI numbers, so they can be substituted and printed. */
|
|
21
|
+
function normalise(given) {
|
|
22
|
+
const out = {};
|
|
23
|
+
for (const key of MOTION_VARS) {
|
|
24
|
+
const raw = given[key];
|
|
25
|
+
if (raw === void 0 || raw === null) continue;
|
|
26
|
+
out[key] = raw instanceof Quantity ? raw.in(MOTION_UNITS[key]) : raw;
|
|
27
|
+
}
|
|
28
|
+
return out;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Which equation answers this question, and why.
|
|
32
|
+
*
|
|
33
|
+
* Throws with a message naming what is still needed, rather than guessing or returning null. A
|
|
34
|
+
* learner who has given two quantities has not made a type error, they have not finished reading
|
|
35
|
+
* the question, and the message should say which quantity is missing.
|
|
36
|
+
*/
|
|
37
|
+
function chooseEquation(target, given) {
|
|
38
|
+
const known = MOTION_VARS.filter((key) => key !== target && isGiven(given, key));
|
|
39
|
+
if (known.length < 3) {
|
|
40
|
+
const missing = MOTION_VARS.filter((key) => key !== target && !isGiven(given, key));
|
|
41
|
+
throw new Error(`To find ${MOTION_NAMES[target]} (${target}) you need three of the other four quantities; ${known.length === 0 ? "none were" : `only ${known.join(", ")} ${known.length === 1 ? "was" : "were"}`} given. Still needed: any ${3 - known.length} of ${missing.join(", ")}.`);
|
|
42
|
+
}
|
|
43
|
+
const absent = MOTION_VARS.filter((key) => key !== target && !isGiven(given, key));
|
|
44
|
+
if (absent.length === 1) {
|
|
45
|
+
const equation = equationWithout(absent[0]);
|
|
46
|
+
if (equation) return equation;
|
|
47
|
+
}
|
|
48
|
+
const candidates = MOTION_EQUATIONS.filter((e) => e.omits !== target && e.relation.variables.every((v) => v === target || isGiven(given, v)));
|
|
49
|
+
const chosen = candidates.find((e) => !(e.quadraticInTime && target === "t")) ?? candidates[0];
|
|
50
|
+
if (!chosen) throw new Error(`No SUVAT equation relates ${target} to the quantities given.`);
|
|
51
|
+
return chosen;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
//#endregion
|
|
55
|
+
export { chooseEquation, isGiven, normalise };
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
//#region src/physics/kinematics/roots.d.ts
|
|
2
|
+
/**
|
|
3
|
+
* Candidate answers, and the argument for keeping or discarding each.
|
|
4
|
+
*
|
|
5
|
+
* A quadratic gives two times and a square root gives two speeds, and in both cases the extra
|
|
6
|
+
* answer is not noise to be filtered out. Which one you keep, and why, is the actual physics: the
|
|
7
|
+
* mathematics is finished and cannot decide it. So a root travels with its reason attached, and a
|
|
8
|
+
* discarded root is still returned so that a lesson can show the discarding rather than a solver
|
|
9
|
+
* doing it silently offstage.
|
|
10
|
+
*/
|
|
11
|
+
/** One candidate value, and whether physics accepts it. */
|
|
12
|
+
interface Root {
|
|
13
|
+
readonly value: number;
|
|
14
|
+
/** A rejected root is still reported: the rejection is the lesson. */
|
|
15
|
+
readonly accepted: boolean;
|
|
16
|
+
/** Why it was accepted or rejected, in a sentence a learner reads. */
|
|
17
|
+
readonly reason: string;
|
|
18
|
+
}
|
|
19
|
+
/** Times smaller than this are the launch instant, not a distinct moment. */
|
|
20
|
+
declare const TIME_EPSILON = 1e-12;
|
|
21
|
+
/**
|
|
22
|
+
* Judge one root of the time quadratic.
|
|
23
|
+
*
|
|
24
|
+
* Three outcomes, not two. A negative time is before the stopwatch started and goes. A positive
|
|
25
|
+
* time stands. Zero is the awkward one: it is real, it is correct, and it is never the answer
|
|
26
|
+
* anybody wanted, because a stone thrown from the ground genuinely IS at ground level at t = 0.
|
|
27
|
+
* Textbooks deal with that by not mentioning it, which leaves a student who solves it by hand
|
|
28
|
+
* holding a root nobody told them about.
|
|
29
|
+
*/
|
|
30
|
+
declare function classifyTime(value: number): Root;
|
|
31
|
+
/** The pair of speeds a square root leaves behind, when the sign is genuinely undetermined. */
|
|
32
|
+
declare function speedRoots(magnitude: number): readonly Root[];
|
|
33
|
+
/**
|
|
34
|
+
* Which root to report as THE answer.
|
|
35
|
+
*
|
|
36
|
+
* The first one strictly after the start. On level ground `s = 0` has roots 0 and T, and returning
|
|
37
|
+
* the launch instant as the time of flight is correct arithmetic and a useless answer.
|
|
38
|
+
*/
|
|
39
|
+
declare const preferredTime: (accepted: readonly Root[]) => Root | undefined;
|
|
40
|
+
//#endregion
|
|
41
|
+
export { Root, TIME_EPSILON, classifyTime, preferredTime, speedRoots };
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import { texSigFigs } from "../../core/worked.mjs";
|
|
2
|
+
|
|
3
|
+
//#region src/physics/kinematics/roots.ts
|
|
4
|
+
/**
|
|
5
|
+
* Candidate answers, and the argument for keeping or discarding each.
|
|
6
|
+
*
|
|
7
|
+
* A quadratic gives two times and a square root gives two speeds, and in both cases the extra
|
|
8
|
+
* answer is not noise to be filtered out. Which one you keep, and why, is the actual physics: the
|
|
9
|
+
* mathematics is finished and cannot decide it. So a root travels with its reason attached, and a
|
|
10
|
+
* discarded root is still returned so that a lesson can show the discarding rather than a solver
|
|
11
|
+
* doing it silently offstage.
|
|
12
|
+
*/
|
|
13
|
+
/** Times smaller than this are the launch instant, not a distinct moment. */
|
|
14
|
+
const TIME_EPSILON = 1e-12;
|
|
15
|
+
/**
|
|
16
|
+
* Judge one root of the time quadratic.
|
|
17
|
+
*
|
|
18
|
+
* Three outcomes, not two. A negative time is before the stopwatch started and goes. A positive
|
|
19
|
+
* time stands. Zero is the awkward one: it is real, it is correct, and it is never the answer
|
|
20
|
+
* anybody wanted, because a stone thrown from the ground genuinely IS at ground level at t = 0.
|
|
21
|
+
* Textbooks deal with that by not mentioning it, which leaves a student who solves it by hand
|
|
22
|
+
* holding a root nobody told them about.
|
|
23
|
+
*/
|
|
24
|
+
function classifyTime(value) {
|
|
25
|
+
if (value < 0) return {
|
|
26
|
+
value,
|
|
27
|
+
accepted: false,
|
|
28
|
+
reason: "negative, so it is a time before the motion started. Reject it."
|
|
29
|
+
};
|
|
30
|
+
if (value <= 1e-12) return {
|
|
31
|
+
value: 0,
|
|
32
|
+
accepted: true,
|
|
33
|
+
reason: "the launch instant itself: it starts at this displacement, so t = 0 solves the equation."
|
|
34
|
+
};
|
|
35
|
+
return {
|
|
36
|
+
value,
|
|
37
|
+
accepted: true,
|
|
38
|
+
reason: "positive, so it is a time after the motion started."
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
/** The pair of speeds a square root leaves behind, when the sign is genuinely undetermined. */
|
|
42
|
+
function speedRoots(magnitude) {
|
|
43
|
+
return [{
|
|
44
|
+
value: magnitude,
|
|
45
|
+
accepted: true,
|
|
46
|
+
reason: "moving in the positive direction."
|
|
47
|
+
}, {
|
|
48
|
+
value: -magnitude,
|
|
49
|
+
accepted: true,
|
|
50
|
+
reason: "the same speed in the negative direction. Choose using the direction of travel, which the equation cannot know."
|
|
51
|
+
}];
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Which root to report as THE answer.
|
|
55
|
+
*
|
|
56
|
+
* The first one strictly after the start. On level ground `s = 0` has roots 0 and T, and returning
|
|
57
|
+
* the launch instant as the time of flight is correct arithmetic and a useless answer.
|
|
58
|
+
*/
|
|
59
|
+
const preferredTime = (accepted) => accepted.find((r) => r.value > 1e-12) ?? accepted[0];
|
|
60
|
+
/**
|
|
61
|
+
* What to say about a pair of roots. Three genuinely different situations, and calling them all
|
|
62
|
+
* "take the positive one" is how students end up discarding a root that was the answer.
|
|
63
|
+
*/
|
|
64
|
+
function rootNote(roots, sf) {
|
|
65
|
+
const rejected = roots.find((r) => !r.accepted);
|
|
66
|
+
if (rejected) return `${texSigFigs(rejected.value, sf)} s is before the motion started, so reject it`;
|
|
67
|
+
if (roots.some((r) => r.value === 0)) return "one root is the launch itself, at t = 0; the other is when it comes back to that level";
|
|
68
|
+
return "both times are real: the body is at this displacement twice, once on the way up and once coming down";
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
//#endregion
|
|
72
|
+
export { TIME_EPSILON, classifyTime, preferredTime, rootNote, speedRoots };
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { Quantity } from "../../quantity/index.mjs";
|
|
2
|
+
import { Worked } from "../../core/worked.mjs";
|
|
3
|
+
import { MotionEquation, MotionVar } from "./equations.mjs";
|
|
4
|
+
import { MotionGiven } from "./given.mjs";
|
|
5
|
+
import { Root } from "./roots.mjs";
|
|
6
|
+
|
|
7
|
+
//#region src/physics/kinematics/solve.d.ts
|
|
8
|
+
interface MotionSolution {
|
|
9
|
+
readonly target: MotionVar;
|
|
10
|
+
/** The answer, in SI. When several roots are accepted this is the first one in time. */
|
|
11
|
+
readonly value: number;
|
|
12
|
+
readonly unit: string;
|
|
13
|
+
readonly quantity: Quantity;
|
|
14
|
+
/** The equation used: the reasoning, not just the result. */
|
|
15
|
+
readonly equation: MotionEquation;
|
|
16
|
+
/** The quantity that was neither known nor wanted, which is what selected the equation. */
|
|
17
|
+
readonly excluded: MotionVar;
|
|
18
|
+
/**
|
|
19
|
+
* Every candidate the mathematics produced, accepted and rejected, when the step was a quadratic
|
|
20
|
+
* or a square root. Absent when the solve was a plain rearrangement with one answer.
|
|
21
|
+
*/
|
|
22
|
+
readonly roots?: readonly Root[];
|
|
23
|
+
/** The derivation, ready for a RuleCard or a lesson. */
|
|
24
|
+
readonly worked: Worked;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Solve for one quantity of a straight-line motion at constant acceleration.
|
|
28
|
+
*
|
|
29
|
+
* ```ts
|
|
30
|
+
* motion('t', { u: 19.6, a: -9.8, s: -58.8 }); // t = 6 s, and −2 s reported as rejected
|
|
31
|
+
* motion('v', { u: 0, a: 9.8, s: 45.9 }); // v = 30 m/s, with −30 reported as the other way
|
|
32
|
+
* motion('s', { u: qty(72, 'km/h'), a: -2, t: 5 });
|
|
33
|
+
* ```
|
|
34
|
+
*/
|
|
35
|
+
declare function motion(target: MotionVar, given: MotionGiven, sf?: number): MotionSolution;
|
|
36
|
+
/**
|
|
37
|
+
* Every time at which the body is at displacement `s`.
|
|
38
|
+
*
|
|
39
|
+
* The direct form of the quadratic case, for a caller that wants the pair rather than one answer:
|
|
40
|
+
* "when is the stone 10 m up?" has two honest answers, and a lab that draws both is teaching
|
|
41
|
+
* something a lab that draws one is not.
|
|
42
|
+
*/
|
|
43
|
+
declare const timeToReach: (s: number | Quantity, given: Omit<MotionGiven, "s" | "t">, sf?: number) => readonly Root[];
|
|
44
|
+
/**
|
|
45
|
+
* Fill in every quantity that follows from the ones given.
|
|
46
|
+
*
|
|
47
|
+
* For a lab's model: move a slider, get the whole consistent picture back, each entry carrying the
|
|
48
|
+
* derivation that produced it.
|
|
49
|
+
*/
|
|
50
|
+
declare function motionTable(given: MotionGiven, sf?: number): Partial<Record<MotionVar, MotionSolution>>;
|
|
51
|
+
//#endregion
|
|
52
|
+
export { MotionSolution, motion, motionTable, timeToReach };
|
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
import { parse } from "../../math/parse.mjs";
|
|
2
|
+
import { solvePoly } from "../../math/solve.mjs";
|
|
3
|
+
import { calc, texSigFigs } from "../../core/worked.mjs";
|
|
4
|
+
import { qty } from "../../quantity/index.mjs";
|
|
5
|
+
import { MOTION_UNITS, MOTION_UNITS_TEX, MOTION_VARS } from "./equations.mjs";
|
|
6
|
+
import { chooseEquation, isGiven, normalise } from "./given.mjs";
|
|
7
|
+
import { classifyTime, preferredTime, rootNote, speedRoots } from "./roots.mjs";
|
|
8
|
+
|
|
9
|
+
//#region src/physics/kinematics/solve.ts
|
|
10
|
+
/**
|
|
11
|
+
* Solving one quantity out of a straight-line motion, and showing the working.
|
|
12
|
+
*
|
|
13
|
+
* Three paths, because three genuinely different things can happen once the equation is chosen:
|
|
14
|
+
*
|
|
15
|
+
* - a plain rearrangement, which `relation` does and which has one answer;
|
|
16
|
+
* - a QUADRATIC, when `t` is wanted from `s = ut + ½at²`, which has two roots that are not
|
|
17
|
+
* interchangeable;
|
|
18
|
+
* - a SQUARE ROOT, when a speed is wanted from `v² = u² + 2as`, where the magnitude is settled
|
|
19
|
+
* and the direction is not, because squaring threw it away.
|
|
20
|
+
*
|
|
21
|
+
* The second and third are where marks are lost, and they are the reason this is a kernel rather
|
|
22
|
+
* than five lines of arithmetic. Neither is allowed to quietly pick an answer.
|
|
23
|
+
*/
|
|
24
|
+
/** `u = 20\ \mathrm{m\,s^{-1}}`, for the substitution line. */
|
|
25
|
+
const sub = (key, value, sf) => `${key} = ${texSigFigs(value, sf)}\\ ${MOTION_UNITS_TEX[key]}`;
|
|
26
|
+
const substitutionLine = (equation, target, values, sf) => MOTION_VARS.filter((v) => v !== target && equation.relation.variables.includes(v)).map((v) => sub(v, values[v], sf)).join(",\\quad ");
|
|
27
|
+
const answerLine = (target, value, sf) => `${target} = ${texSigFigs(value, sf)}\\ ${MOTION_UNITS_TEX[target]}`;
|
|
28
|
+
const finish = (target, value, equation, worked, roots) => ({
|
|
29
|
+
target,
|
|
30
|
+
value,
|
|
31
|
+
unit: MOTION_UNITS[target],
|
|
32
|
+
quantity: qty(value, MOTION_UNITS[target]),
|
|
33
|
+
equation,
|
|
34
|
+
excluded: equation.omits,
|
|
35
|
+
...roots ? { roots } : {},
|
|
36
|
+
worked
|
|
37
|
+
});
|
|
38
|
+
/**
|
|
39
|
+
* Solve for one quantity of a straight-line motion at constant acceleration.
|
|
40
|
+
*
|
|
41
|
+
* ```ts
|
|
42
|
+
* motion('t', { u: 19.6, a: -9.8, s: -58.8 }); // t = 6 s, and −2 s reported as rejected
|
|
43
|
+
* motion('v', { u: 0, a: 9.8, s: 45.9 }); // v = 30 m/s, with −30 reported as the other way
|
|
44
|
+
* motion('s', { u: qty(72, 'km/h'), a: -2, t: 5 });
|
|
45
|
+
* ```
|
|
46
|
+
*/
|
|
47
|
+
function motion(target, given, sf = 3) {
|
|
48
|
+
const equation = chooseEquation(target, given);
|
|
49
|
+
const values = normalise(given);
|
|
50
|
+
const knowns = MOTION_VARS.filter((v) => v !== target && equation.relation.variables.includes(v));
|
|
51
|
+
const w = calc().step(equation.relation.title, `you know ${knowns.join(", ")} and want ${target}, so use the equation without ${equation.omits}`);
|
|
52
|
+
if (equation.quadraticInTime && target === "t") return quadraticTime(equation, values, sf, w);
|
|
53
|
+
if (equation.omits === "t" && (target === "u" || target === "v")) return rootedSpeed(equation, target, values, sf, w);
|
|
54
|
+
const scoped = {};
|
|
55
|
+
for (const v of equation.relation.variables) if (v !== target) scoped[v] = values[v];
|
|
56
|
+
const solved = equation.relation.solveFor(target, scoped);
|
|
57
|
+
w.step(substitutionLine(equation, target, values, sf), "the values from the question");
|
|
58
|
+
w.step(answerLine(target, solved.value, sf), `to ${sf} significant figures`);
|
|
59
|
+
return finish(target, solved.value, equation, w.done(solved.value));
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* The two roots of `a t² + b t + c = 0`, from the closed form, in the numerically stable arrangement.
|
|
63
|
+
*
|
|
64
|
+
* WHY NOT THE GENERAL ROOT FINDER. The polynomial solver behind `solvePoly` is Durand-Kerner, which
|
|
65
|
+
* is iterative and converges to about ten significant figures. That is ample for a printed answer
|
|
66
|
+
* and it was quietly wrong for two other reasons. The first is honesty: the derivation prints
|
|
67
|
+
* `t = (-b ± √(b² − 4ac)) / 2a`, so the number beside it should be what that expression gives, not
|
|
68
|
+
* what an iteration happened to land on. The second is that callers integrate against these times.
|
|
69
|
+
* A landing time out by 4e-10 is invisible in a lesson and is a real error in an animation loop
|
|
70
|
+
* that differences it.
|
|
71
|
+
*
|
|
72
|
+
* The arrangement matters as much as the formula. Computing both roots as `(-b ± √disc) / 2a` loses
|
|
73
|
+
* most of the significant figures of the smaller root whenever `b² >> 4ac`, because one of the two
|
|
74
|
+
* is then a subtraction of nearly equal numbers. Forming `q` with the sign of `b` makes that branch
|
|
75
|
+
* an addition, and the other root comes from `c / q` instead, where nothing cancels.
|
|
76
|
+
*/
|
|
77
|
+
function quadraticRoots(a, b, c) {
|
|
78
|
+
const disc = b * b - 4 * a * c;
|
|
79
|
+
if (disc < 0) return [];
|
|
80
|
+
const sq = Math.sqrt(disc);
|
|
81
|
+
if (sq === 0) return [-b / (2 * a)];
|
|
82
|
+
const q = -.5 * (b + (b >= 0 ? sq : -sq));
|
|
83
|
+
return [q / a, c / q].sort((x, y) => x - y);
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* `s = ut + ½at²` solved for `t`.
|
|
87
|
+
*
|
|
88
|
+
* The coefficients are read off the DECLARED equation rather than written out again here. A second
|
|
89
|
+
* hand-written copy of the same equation is exactly the thing that drifts, and the drift would be
|
|
90
|
+
* invisible, because both copies would still look like the formula.
|
|
91
|
+
*/
|
|
92
|
+
function quadraticTime(equation, values, sf, w) {
|
|
93
|
+
const [lhs, rhs] = equation.relation.equation.split("=");
|
|
94
|
+
const params = {};
|
|
95
|
+
for (const v of equation.relation.variables) if (v !== "t") params[v] = values[v];
|
|
96
|
+
const solution = solvePoly(parse(`(${rhs}) - (${lhs})`), "t", params);
|
|
97
|
+
if (!solution) throw new Error(`Could not read ${equation.relation.equation} as a polynomial in t.`);
|
|
98
|
+
w.step(substitutionLine(equation, "t", values, sf), "the values from the question");
|
|
99
|
+
if (solution.degree < 2) {
|
|
100
|
+
const [k0, k1] = solution.coeffs;
|
|
101
|
+
const only = k1 === void 0 || k1 === 0 ? solution.realRoots[0] : -k0 / k1;
|
|
102
|
+
if (only === void 0 || !Number.isFinite(only)) throw new Error("With a = 0 and this displacement there is no time that satisfies the motion.");
|
|
103
|
+
w.step(answerLine("t", only, sf), "a = 0, so the equation is linear in t");
|
|
104
|
+
return finish("t", only, equation, w.done(only), [{
|
|
105
|
+
value: only,
|
|
106
|
+
accepted: true,
|
|
107
|
+
reason: "the acceleration is zero, so there is one time."
|
|
108
|
+
}]);
|
|
109
|
+
}
|
|
110
|
+
const [c0, c1, c2] = solution.coeffs;
|
|
111
|
+
w.step(`${texSigFigs(c2, sf)}t^2 + ${texSigFigs(c1, sf)}t + ${texSigFigs(c0, sf)} = 0`, "rearranged: this is a quadratic in t, not a rearrangement");
|
|
112
|
+
const disc = solution.discriminant ?? c1 * c1 - 4 * c2 * c0;
|
|
113
|
+
if (disc < 0) throw new Error(`The body never reaches s = ${values.s} m. Solving gives a negative discriminant (${disc.toPrecision(3)}), so no real time satisfies the motion. Check the sign convention, or the displacement is genuinely out of reach.`);
|
|
114
|
+
w.step("t = \\frac{-b \\pm \\sqrt{b^2 - 4ac}}{2a}", "two roots, and they are not interchangeable");
|
|
115
|
+
const exact = quadraticRoots(c2, c1, c0);
|
|
116
|
+
const roots = exact.map(classifyTime);
|
|
117
|
+
const accepted = roots.filter((r) => r.accepted);
|
|
118
|
+
if (accepted.length === 0) throw new Error(`Both roots are negative (${exact.map((r) => r.toPrecision(3)).join(", ")} s), so the body was never at this displacement after t = 0. The sign convention is the usual cause.`);
|
|
119
|
+
w.step(roots.map((r) => answerLine("t", r.value, sf)).join(",\\quad "), rootNote(roots, sf));
|
|
120
|
+
const chosen = preferredTime(accepted);
|
|
121
|
+
w.step(answerLine("t", chosen.value, sf), `to ${sf} significant figures`);
|
|
122
|
+
return finish("t", chosen.value, equation, w.done(chosen.value), roots);
|
|
123
|
+
}
|
|
124
|
+
/**
|
|
125
|
+
* `v² = u² + 2as` solved for a speed.
|
|
126
|
+
*
|
|
127
|
+
* Squaring destroyed the direction, so the equation genuinely cannot say which sign is meant, and a
|
|
128
|
+
* solver that silently returns the positive root teaches a student to lose a mark on every question
|
|
129
|
+
* where the body is coming back down. Both are returned; choosing between them needs something the
|
|
130
|
+
* equation does not contain.
|
|
131
|
+
*/
|
|
132
|
+
function rootedSpeed(equation, target, values, sf, w) {
|
|
133
|
+
const other = target === "v" ? "u" : "v";
|
|
134
|
+
const square = values[other] * values[other] + 2 * values.a * values.s;
|
|
135
|
+
w.step(substitutionLine(equation, target, values, sf), "the values from the question");
|
|
136
|
+
w.step(`${target}^2 = ${texSigFigs(square, sf)}\\ \\mathrm{m^2\\,s^{-2}}`);
|
|
137
|
+
if (square < 0) throw new Error(`${target}² works out negative (${square.toPrecision(3)}), so the body never reaches s = ${values.s} m. It stops and turns back first.`);
|
|
138
|
+
const magnitude = Math.sqrt(square);
|
|
139
|
+
w.step(`${target} = \\pm${texSigFigs(magnitude, sf)}\\ ${MOTION_UNITS_TEX[target]}`, "squaring lost the direction, so both signs solve the equation");
|
|
140
|
+
w.step(answerLine(target, magnitude, sf), `to ${sf} significant figures, taking the positive direction`);
|
|
141
|
+
return finish(target, magnitude, equation, w.done(magnitude), speedRoots(magnitude));
|
|
142
|
+
}
|
|
143
|
+
/**
|
|
144
|
+
* Every time at which the body is at displacement `s`.
|
|
145
|
+
*
|
|
146
|
+
* The direct form of the quadratic case, for a caller that wants the pair rather than one answer:
|
|
147
|
+
* "when is the stone 10 m up?" has two honest answers, and a lab that draws both is teaching
|
|
148
|
+
* something a lab that draws one is not.
|
|
149
|
+
*/
|
|
150
|
+
const timeToReach = (s, given, sf = 3) => motion("t", {
|
|
151
|
+
...given,
|
|
152
|
+
s
|
|
153
|
+
}, sf).roots ?? [];
|
|
154
|
+
/**
|
|
155
|
+
* Fill in every quantity that follows from the ones given.
|
|
156
|
+
*
|
|
157
|
+
* For a lab's model: move a slider, get the whole consistent picture back, each entry carrying the
|
|
158
|
+
* derivation that produced it.
|
|
159
|
+
*/
|
|
160
|
+
function motionTable(given, sf = 3) {
|
|
161
|
+
const out = {};
|
|
162
|
+
for (const target of MOTION_VARS) {
|
|
163
|
+
if (isGiven(given, target)) continue;
|
|
164
|
+
try {
|
|
165
|
+
out[target] = motion(target, given, sf);
|
|
166
|
+
} catch {}
|
|
167
|
+
}
|
|
168
|
+
return out;
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
//#endregion
|
|
172
|
+
export { motion, motionTable, timeToReach };
|