@classytic/stage 0.3.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/dist/_virtual/_rolldown/runtime.mjs +18 -0
- 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/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 +3 -1
- package/dist/core/index.mjs +3 -1
- 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 +21 -39
- package/dist/finance/bizsim.mjs +276 -97
- package/dist/finance/index.d.mts +20 -43
- package/dist/finance/index.mjs +19 -77
- 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 +6 -6
- package/dist/index.mjs +1 -1
- 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 +4 -9
- package/dist/math/calculus.mjs +216 -7
- 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 +8 -22
- package/dist/math/index.mjs +8 -37
- package/dist/math/latex.mjs +2 -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/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/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/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 +74 -2
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
import { fromMinor, toMinor } from "../accounting/precision.mjs";
|
|
2
|
+
|
|
3
|
+
//#region src/finance/management-accounting/variances.ts
|
|
4
|
+
const DEFAULT_POLICY = { decimalPlaces: 2 };
|
|
5
|
+
function analyzeCostVariances(facts, policy = DEFAULT_POLICY) {
|
|
6
|
+
const diagnostics = [];
|
|
7
|
+
if ([
|
|
8
|
+
facts.actualOutputUnits,
|
|
9
|
+
facts.material.standardQuantityPerUnit,
|
|
10
|
+
facts.material.standardPricePerUnit,
|
|
11
|
+
facts.material.actualQuantity,
|
|
12
|
+
facts.material.actualPricePerUnit,
|
|
13
|
+
facts.labour.standardHoursPerUnit,
|
|
14
|
+
facts.labour.standardRatePerHour,
|
|
15
|
+
facts.labour.actualHours,
|
|
16
|
+
facts.labour.actualRatePerHour,
|
|
17
|
+
facts.variableOverhead.standardRatePerHour,
|
|
18
|
+
facts.variableOverhead.actualRatePerHour,
|
|
19
|
+
facts.fixedOverhead.budgeted,
|
|
20
|
+
facts.fixedOverhead.actual
|
|
21
|
+
].some((value) => !Number.isFinite(value) || value < 0)) diagnostics.push({
|
|
22
|
+
code: "invalid-input",
|
|
23
|
+
severity: "error",
|
|
24
|
+
message: "Variance inputs must be finite and non-negative."
|
|
25
|
+
});
|
|
26
|
+
if (!Number.isFinite(facts.fixedOverhead.normalCapacityHours) || facts.fixedOverhead.normalCapacityHours <= 0) diagnostics.push({
|
|
27
|
+
code: "invalid-input",
|
|
28
|
+
severity: "error",
|
|
29
|
+
message: "Normal capacity hours must be finite and positive."
|
|
30
|
+
});
|
|
31
|
+
if (diagnostics.length > 0) return emptyResult(diagnostics);
|
|
32
|
+
const standardQuantity = facts.actualOutputUnits * facts.material.standardQuantityPerUnit;
|
|
33
|
+
const standardHours = facts.actualOutputUnits * facts.labour.standardHoursPerUnit;
|
|
34
|
+
const variance = (amount) => {
|
|
35
|
+
const rounded = money(amount, policy);
|
|
36
|
+
return {
|
|
37
|
+
amount: Math.abs(rounded),
|
|
38
|
+
outcome: rounded > 0 ? "favorable" : rounded < 0 ? "adverse" : "none"
|
|
39
|
+
};
|
|
40
|
+
};
|
|
41
|
+
const signed = (item) => item.outcome === "favorable" ? item.amount : item.outcome === "adverse" ? -item.amount : 0;
|
|
42
|
+
const combine = (...items) => variance(items.reduce((sum, item) => sum + signed(item), 0));
|
|
43
|
+
const materialPrice = variance(facts.material.actualQuantity * (facts.material.standardPricePerUnit - facts.material.actualPricePerUnit));
|
|
44
|
+
const materialUsage = variance(facts.material.standardPricePerUnit * (standardQuantity - facts.material.actualQuantity));
|
|
45
|
+
const labourRate = variance(facts.labour.actualHours * (facts.labour.standardRatePerHour - facts.labour.actualRatePerHour));
|
|
46
|
+
const labourEfficiency = variance(facts.labour.standardRatePerHour * (standardHours - facts.labour.actualHours));
|
|
47
|
+
const variableExpenditure = variance(facts.labour.actualHours * (facts.variableOverhead.standardRatePerHour - facts.variableOverhead.actualRatePerHour));
|
|
48
|
+
const variableEfficiency = variance(facts.variableOverhead.standardRatePerHour * (standardHours - facts.labour.actualHours));
|
|
49
|
+
const fixedExpenditure = variance(facts.fixedOverhead.budgeted - facts.fixedOverhead.actual);
|
|
50
|
+
const fixedVolume = variance(standardHours * (facts.fixedOverhead.budgeted / facts.fixedOverhead.normalCapacityHours) - facts.fixedOverhead.budgeted);
|
|
51
|
+
const materialTotal = combine(materialPrice, materialUsage);
|
|
52
|
+
const labourTotal = combine(labourRate, labourEfficiency);
|
|
53
|
+
const variableTotal = combine(variableExpenditure, variableEfficiency);
|
|
54
|
+
const fixedTotal = combine(fixedExpenditure, fixedVolume);
|
|
55
|
+
const totalCostVariance = combine(materialTotal, labourTotal, variableTotal, fixedTotal);
|
|
56
|
+
const trace = [
|
|
57
|
+
{
|
|
58
|
+
id: "variance:material-price",
|
|
59
|
+
kind: "derive",
|
|
60
|
+
rule: "Material price variance = actual quantity × (standard price − actual price). Positive is favorable.",
|
|
61
|
+
working: `${facts.material.actualQuantity} × (${facts.material.standardPricePerUnit} − ${facts.material.actualPricePerUnit})`,
|
|
62
|
+
result: signed(materialPrice)
|
|
63
|
+
},
|
|
64
|
+
{
|
|
65
|
+
id: "variance:material-usage",
|
|
66
|
+
kind: "derive",
|
|
67
|
+
rule: "Material usage variance = standard price × (standard quantity for output − actual quantity). Positive is favorable.",
|
|
68
|
+
working: `${facts.material.standardPricePerUnit} × (${standardQuantity} − ${facts.material.actualQuantity})`,
|
|
69
|
+
result: signed(materialUsage)
|
|
70
|
+
},
|
|
71
|
+
{
|
|
72
|
+
id: "variance:labour-rate",
|
|
73
|
+
kind: "derive",
|
|
74
|
+
rule: "Labour rate variance = actual hours × (standard rate − actual rate). Positive is favorable.",
|
|
75
|
+
working: `${facts.labour.actualHours} × (${facts.labour.standardRatePerHour} − ${facts.labour.actualRatePerHour})`,
|
|
76
|
+
result: signed(labourRate)
|
|
77
|
+
},
|
|
78
|
+
{
|
|
79
|
+
id: "variance:labour-efficiency",
|
|
80
|
+
kind: "derive",
|
|
81
|
+
rule: "Labour efficiency variance = standard rate × (standard hours for output − actual hours). Positive is favorable.",
|
|
82
|
+
working: `${facts.labour.standardRatePerHour} × (${standardHours} − ${facts.labour.actualHours})`,
|
|
83
|
+
result: signed(labourEfficiency)
|
|
84
|
+
}
|
|
85
|
+
];
|
|
86
|
+
return {
|
|
87
|
+
completed: true,
|
|
88
|
+
standardQuantity,
|
|
89
|
+
standardHours,
|
|
90
|
+
material: {
|
|
91
|
+
price: materialPrice,
|
|
92
|
+
usage: materialUsage,
|
|
93
|
+
total: materialTotal
|
|
94
|
+
},
|
|
95
|
+
labour: {
|
|
96
|
+
rate: labourRate,
|
|
97
|
+
efficiency: labourEfficiency,
|
|
98
|
+
total: labourTotal
|
|
99
|
+
},
|
|
100
|
+
variableOverhead: {
|
|
101
|
+
expenditure: variableExpenditure,
|
|
102
|
+
efficiency: variableEfficiency,
|
|
103
|
+
total: variableTotal
|
|
104
|
+
},
|
|
105
|
+
fixedOverhead: {
|
|
106
|
+
expenditure: fixedExpenditure,
|
|
107
|
+
volume: fixedVolume,
|
|
108
|
+
total: fixedTotal
|
|
109
|
+
},
|
|
110
|
+
totalCostVariance,
|
|
111
|
+
diagnostics,
|
|
112
|
+
trace
|
|
113
|
+
};
|
|
114
|
+
}
|
|
115
|
+
const money = (value, policy) => fromMinor(toMinor(value, policy), policy);
|
|
116
|
+
const zero = {
|
|
117
|
+
amount: 0,
|
|
118
|
+
outcome: "none"
|
|
119
|
+
};
|
|
120
|
+
const emptyResult = (diagnostics) => ({
|
|
121
|
+
completed: false,
|
|
122
|
+
standardQuantity: 0,
|
|
123
|
+
standardHours: 0,
|
|
124
|
+
material: {
|
|
125
|
+
price: zero,
|
|
126
|
+
usage: zero,
|
|
127
|
+
total: zero
|
|
128
|
+
},
|
|
129
|
+
labour: {
|
|
130
|
+
rate: zero,
|
|
131
|
+
efficiency: zero,
|
|
132
|
+
total: zero
|
|
133
|
+
},
|
|
134
|
+
variableOverhead: {
|
|
135
|
+
expenditure: zero,
|
|
136
|
+
efficiency: zero,
|
|
137
|
+
total: zero
|
|
138
|
+
},
|
|
139
|
+
fixedOverhead: {
|
|
140
|
+
expenditure: zero,
|
|
141
|
+
volume: zero,
|
|
142
|
+
total: zero
|
|
143
|
+
},
|
|
144
|
+
totalCostVariance: zero,
|
|
145
|
+
diagnostics,
|
|
146
|
+
trace: []
|
|
147
|
+
});
|
|
148
|
+
|
|
149
|
+
//#endregion
|
|
150
|
+
export { analyzeCostVariances };
|
package/dist/index.d.mts
CHANGED
|
@@ -12,6 +12,12 @@ import { IconName, ToolIcon } from "./builder/icons.mjs";
|
|
|
12
12
|
import { AUTHORING_TOOLS, CIRCLE, DELETE, GEOMETRY_TOOLS, INTERSECT, LINE, MEASURE, MIDPOINT, NOTE, POINT, SCALAR, SEGMENT, SELECT, Tool, ToolCtx } from "./builder/tools.mjs";
|
|
13
13
|
import { SceneBuilder, SceneBuilderProps } from "./builder/SceneBuilder.mjs";
|
|
14
14
|
import { Palette, PaletteProps } from "./builder/Palette.mjs";
|
|
15
|
+
import { BinOp, Node, compileNode, evaluate, freeVars } from "./math/ast.mjs";
|
|
16
|
+
import { parse as parse$1 } from "./math/parse.mjs";
|
|
17
|
+
import { definiteIntegral, differentiate, integrate, simplify } from "./math/calculus.mjs";
|
|
18
|
+
import { CompiledFn, compile } from "./math/compile.mjs";
|
|
19
|
+
import { toLatex as toLatex$1 } from "./math/latex.mjs";
|
|
20
|
+
import { CompiledExpr, ExprError, ExprResult, compileExpr } from "./math/expr.mjs";
|
|
15
21
|
import { CoordsContext, DragOverlayContext, StageRefContext, useCoords, useDragOverlay, useStageRef } from "./core/context.mjs";
|
|
16
22
|
import { ClockProvider, ClockProviderProps, FrameDriver, FrameInfo, useFrameLoop } from "./core/clock.mjs";
|
|
17
23
|
import { Learner, LearnerProvider, LearnerResult, PriorAttempts, useLearner } from "./core/learner.mjs";
|
|
@@ -41,12 +47,6 @@ import { CURRENT_SCHEMA_VERSION, emptyDoc, migrate, parse, serialize } from "./s
|
|
|
41
47
|
import { InstanceState, SceneStore } from "./scene/store.mjs";
|
|
42
48
|
import { Scene, SceneProps } from "./scene/Scene.mjs";
|
|
43
49
|
import { RenderOpts, renderElements } from "./scene/render.mjs";
|
|
44
|
-
import { BinOp, Node, compileNode, evaluate, freeVars } from "./math/ast.mjs";
|
|
45
|
-
import { parse as parse$1 } from "./math/parse.mjs";
|
|
46
|
-
import { definiteIntegral, differentiate, integrate, simplify } from "./math/calculus.mjs";
|
|
47
|
-
import { CompiledFn, compile } from "./math/compile.mjs";
|
|
48
|
-
import { toLatex as toLatex$1 } from "./math/latex.mjs";
|
|
49
|
-
import { CompiledExpr, ExprError, ExprResult, compileExpr } from "./math/index.mjs";
|
|
50
50
|
import { BinOp as BinOp$1, LNode, evalBool, freeVars as freeVars$1 } from "./logic/ast.mjs";
|
|
51
51
|
import { parseLogic } from "./logic/parse.mjs";
|
|
52
52
|
import { Classification, TruthRow, TruthTable, classify, equivalent, toCNF, toDNF, truthTable } from "./logic/table.mjs";
|
package/dist/index.mjs
CHANGED
|
@@ -31,7 +31,7 @@ import { parse as parse$1 } from "./math/parse.mjs";
|
|
|
31
31
|
import { definiteIntegral, differentiate, integrate, simplify } from "./math/calculus.mjs";
|
|
32
32
|
import { compile } from "./math/compile.mjs";
|
|
33
33
|
import { toLatex as toLatex$1 } from "./math/latex.mjs";
|
|
34
|
-
import { compileExpr } from "./math/
|
|
34
|
+
import { compileExpr } from "./math/expr.mjs";
|
|
35
35
|
import { EVALUATORS } from "./scene/evaluators.mjs";
|
|
36
36
|
import { resolve } from "./scene/resolve.mjs";
|
|
37
37
|
import { applyCommand, collectRemoved, inverse } from "./scene/commands.mjs";
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { Node } from "./ast.mjs";
|
|
2
|
+
|
|
3
|
+
//#region src/math/analysis.d.ts
|
|
4
|
+
type Fn1 = (x: number) => number;
|
|
5
|
+
/** A straight line y = m·x + c, with the point it was taken at and an evaluator. */
|
|
6
|
+
interface Line {
|
|
7
|
+
m: number;
|
|
8
|
+
c: number;
|
|
9
|
+
at: {
|
|
10
|
+
x: number;
|
|
11
|
+
y: number;
|
|
12
|
+
};
|
|
13
|
+
f: Fn1;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Real roots of f on [a,b]. Two passes so it doesn't miss the roots students do:
|
|
17
|
+
* 1. sign-change brackets refined by BISECTION (odd-multiplicity / crossings);
|
|
18
|
+
* 2. local minima of |f| polished by NEWTON, accepted only if |f| really drops
|
|
19
|
+
* to ~0 — this recovers TANGENT / double roots (e.g. x² at 0) that never
|
|
20
|
+
* change sign. False minima (a parabola that never reaches 0) are rejected
|
|
21
|
+
* by the accept tolerance, so no phantom roots.
|
|
22
|
+
*/
|
|
23
|
+
declare function roots(f: Fn1, a: number, b: number, opts?: {
|
|
24
|
+
steps?: number;
|
|
25
|
+
tol?: number;
|
|
26
|
+
}): number[];
|
|
27
|
+
/** Points where f and g meet on [a,b]. */
|
|
28
|
+
declare function intersections(f: Fn1, g: Fn1, a: number, b: number, opts?: {
|
|
29
|
+
steps?: number;
|
|
30
|
+
tol?: number;
|
|
31
|
+
}): {
|
|
32
|
+
x: number;
|
|
33
|
+
y: number;
|
|
34
|
+
}[];
|
|
35
|
+
/** Exact tangent line to `ast` at x = x0 (params baked in via `scope`). */
|
|
36
|
+
declare function tangentAt(ast: Node, x0: number, varName?: string, params?: Record<string, number>): Line | null;
|
|
37
|
+
/** Normal line to `ast` at x = x0 (⟂ the tangent). Null if the tangent is horizontal. */
|
|
38
|
+
declare function normalAt(ast: Node, x0: number, varName?: string, params?: Record<string, number>): Line | null;
|
|
39
|
+
/**
|
|
40
|
+
* Composite-Simpson definite integral ∫_a^b f dx, on a NUMERIC function.
|
|
41
|
+
*
|
|
42
|
+
* Error O(h⁴) against O(h) for a Riemann sum, so at n≈1000 it is accurate to near machine
|
|
43
|
+
* precision for a smooth integrand and serves as the reference value a Riemann sum converges
|
|
44
|
+
* toward. `n` is forced even, as the rule requires. Not adaptive: a singularity inside [a, b] is
|
|
45
|
+
* not detected, which is why the callers in this file (`areaBetween`) split at the crossings first.
|
|
46
|
+
*
|
|
47
|
+
* Named `quadrature` because `calculus.ts` beside it exports `integrate`, which integrates an AST
|
|
48
|
+
* SYMBOLICALLY: different argument type, different return type, different meaning. (`simpson`
|
|
49
|
+
* would become a lie the moment the rule changed.) The single implementation, after two copies of
|
|
50
|
+
* it were found in labs; see `KERNEL-CONTRACT.md` §7.
|
|
51
|
+
*/
|
|
52
|
+
declare function quadrature(f: Fn1, a: number, b: number, n?: number): number;
|
|
53
|
+
/**
|
|
54
|
+
* Geometric area between f and g over [a,b]. SPLITS at every crossing so the
|
|
55
|
+
* pieces where g > f don't cancel the pieces where f > g (which a single
|
|
56
|
+
* |∫(f−g)| would). Sums |∫| over each sub-interval — the area an exam actually
|
|
57
|
+
* wants.
|
|
58
|
+
*/
|
|
59
|
+
declare function areaBetween(f: Fn1, g: Fn1, a: number, b: number, n?: number): number;
|
|
60
|
+
//#endregion
|
|
61
|
+
export { Fn1, Line, areaBetween, intersections, normalAt, quadrature, roots, tangentAt };
|
|
@@ -0,0 +1,187 @@
|
|
|
1
|
+
import { evaluate } from "./ast.mjs";
|
|
2
|
+
import { differentiate } from "./calculus.mjs";
|
|
3
|
+
|
|
4
|
+
//#region src/math/analysis.ts
|
|
5
|
+
/**
|
|
6
|
+
* analysis, the NUMERIC layer over this package's symbolic engine: the half of calculus that needs
|
|
7
|
+
* a number rather than an expression. `calculus.ts` differentiates and integrates an AST exactly;
|
|
8
|
+
* this file finds roots, intersections, tangents, normals and areas, which in general have no
|
|
9
|
+
* closed form at all.
|
|
10
|
+
*
|
|
11
|
+
* Everything works on a compiled scalar `Fn1 = (x) => number` (params already baked into the
|
|
12
|
+
* closure) plus, for exact tangents, the parsed `Node` AST. Pure: no React, no pixels.
|
|
13
|
+
*
|
|
14
|
+
* Methods, and why each is safe:
|
|
15
|
+
* • roots, bisection on sign changes PLUS Newton at local minima of |f|, so tangent (even
|
|
16
|
+
* multiplicity) roots are found and poles are rejected. See the docblock on `roots`.
|
|
17
|
+
* • tangents/normals, EXACT: the AST is differentiated symbolically, then evaluated. No
|
|
18
|
+
* finite-difference error in the gradient a lesson shows.
|
|
19
|
+
* • quadrature, composite Simpson, error O(h⁴).
|
|
20
|
+
*
|
|
21
|
+
* Units: none. These are pure numbers on a pure function.
|
|
22
|
+
*/
|
|
23
|
+
function pushUnique(out, x, tol) {
|
|
24
|
+
if (!out.some((p) => Math.abs(p - x) <= tol)) out.push(x);
|
|
25
|
+
}
|
|
26
|
+
/** Newton's method from x0 using a central-difference derivative (we only hold
|
|
27
|
+
* the numeric f, not its AST). Returns the polished root, or null on a flat
|
|
28
|
+
* derivative / divergence. Used to recover tangent (even-multiplicity) roots a
|
|
29
|
+
* sign-change scan can't see. */
|
|
30
|
+
function newton(f, x0, tol) {
|
|
31
|
+
let x = x0;
|
|
32
|
+
for (let k = 0; k < 40; k++) {
|
|
33
|
+
const fx = f(x);
|
|
34
|
+
if (!Number.isFinite(fx)) return null;
|
|
35
|
+
if (Math.abs(fx) <= tol) return x;
|
|
36
|
+
const h = Math.max(1e-7, Math.abs(x) * 1e-7);
|
|
37
|
+
const d = (f(x + h) - f(x - h)) / (2 * h);
|
|
38
|
+
if (!Number.isFinite(d) || Math.abs(d) < 1e-13) return null;
|
|
39
|
+
const nx = x - fx / d;
|
|
40
|
+
if (!Number.isFinite(nx)) return null;
|
|
41
|
+
if (Math.abs(nx - x) <= tol) return nx;
|
|
42
|
+
x = nx;
|
|
43
|
+
}
|
|
44
|
+
return Math.abs(f(x)) <= tol ? x : null;
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Real roots of f on [a,b]. Two passes so it doesn't miss the roots students do:
|
|
48
|
+
* 1. sign-change brackets refined by BISECTION (odd-multiplicity / crossings);
|
|
49
|
+
* 2. local minima of |f| polished by NEWTON, accepted only if |f| really drops
|
|
50
|
+
* to ~0 — this recovers TANGENT / double roots (e.g. x² at 0) that never
|
|
51
|
+
* change sign. False minima (a parabola that never reaches 0) are rejected
|
|
52
|
+
* by the accept tolerance, so no phantom roots.
|
|
53
|
+
*/
|
|
54
|
+
function roots(f, a, b, opts = {}) {
|
|
55
|
+
const steps = opts.steps ?? 1e3;
|
|
56
|
+
const tol = opts.tol ?? 1e-9;
|
|
57
|
+
const grid = (b - a) / steps;
|
|
58
|
+
const out = [];
|
|
59
|
+
const xs = [], fs = [];
|
|
60
|
+
for (let i = 0; i <= steps; i++) {
|
|
61
|
+
const x = a + grid * i;
|
|
62
|
+
xs.push(x);
|
|
63
|
+
fs.push(f(x));
|
|
64
|
+
}
|
|
65
|
+
let maxAbs = 0;
|
|
66
|
+
for (const v of fs) if (Number.isFinite(v)) maxAbs = Math.max(maxAbs, Math.abs(v));
|
|
67
|
+
const acceptTol = 1e-7 * (1 + maxAbs);
|
|
68
|
+
for (let i = 1; i <= steps; i++) {
|
|
69
|
+
const fPrev = fs[i - 1], fx = fs[i];
|
|
70
|
+
if (!Number.isFinite(fPrev) || !Number.isFinite(fx)) continue;
|
|
71
|
+
if (fPrev === 0) {
|
|
72
|
+
pushUnique(out, xs[i - 1], grid);
|
|
73
|
+
continue;
|
|
74
|
+
}
|
|
75
|
+
if (fPrev * fx < 0) {
|
|
76
|
+
let lo = xs[i - 1], hi = xs[i], flo = fPrev;
|
|
77
|
+
for (let k = 0; k < 80 && hi - lo > tol; k++) {
|
|
78
|
+
const mid = (lo + hi) / 2;
|
|
79
|
+
const fm = f(mid);
|
|
80
|
+
if (!Number.isFinite(fm)) break;
|
|
81
|
+
if (flo * fm <= 0) hi = mid;
|
|
82
|
+
else {
|
|
83
|
+
lo = mid;
|
|
84
|
+
flo = fm;
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
const mid = (lo + hi) / 2;
|
|
88
|
+
if (Math.abs(f(mid)) <= acceptTol) pushUnique(out, mid, grid);
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
for (let i = 1; i < steps; i++) {
|
|
92
|
+
const p = fs[i - 1], c = fs[i], q = fs[i + 1];
|
|
93
|
+
if (!Number.isFinite(p) || !Number.isFinite(c) || !Number.isFinite(q)) continue;
|
|
94
|
+
if (Math.abs(c) <= Math.abs(p) && Math.abs(c) <= Math.abs(q) && Math.abs(c) < .05 * (1 + maxAbs)) {
|
|
95
|
+
const r = newton(f, xs[i], tol);
|
|
96
|
+
if (r != null && r >= a - grid && r <= b + grid && Math.abs(f(r)) <= acceptTol) pushUnique(out, r, grid);
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
out.sort((u, v) => u - v);
|
|
100
|
+
return out;
|
|
101
|
+
}
|
|
102
|
+
/** Points where f and g meet on [a,b]. */
|
|
103
|
+
function intersections(f, g, a, b, opts) {
|
|
104
|
+
return roots((x) => f(x) - g(x), a, b, opts).map((x) => ({
|
|
105
|
+
x,
|
|
106
|
+
y: f(x)
|
|
107
|
+
}));
|
|
108
|
+
}
|
|
109
|
+
/** Exact tangent line to `ast` at x = x0 (params baked in via `scope`). */
|
|
110
|
+
function tangentAt(ast, x0, varName = "x", params = {}) {
|
|
111
|
+
const d = differentiate(ast, varName);
|
|
112
|
+
if (!d) return null;
|
|
113
|
+
const m = evaluate(d, {
|
|
114
|
+
...params,
|
|
115
|
+
[varName]: x0
|
|
116
|
+
});
|
|
117
|
+
const y0 = evaluate(ast, {
|
|
118
|
+
...params,
|
|
119
|
+
[varName]: x0
|
|
120
|
+
});
|
|
121
|
+
if (!Number.isFinite(m) || !Number.isFinite(y0)) return null;
|
|
122
|
+
const c = y0 - m * x0;
|
|
123
|
+
return {
|
|
124
|
+
m,
|
|
125
|
+
c,
|
|
126
|
+
at: {
|
|
127
|
+
x: x0,
|
|
128
|
+
y: y0
|
|
129
|
+
},
|
|
130
|
+
f: (x) => m * x + c
|
|
131
|
+
};
|
|
132
|
+
}
|
|
133
|
+
/** Normal line to `ast` at x = x0 (⟂ the tangent). Null if the tangent is horizontal. */
|
|
134
|
+
function normalAt(ast, x0, varName = "x", params = {}) {
|
|
135
|
+
const t = tangentAt(ast, x0, varName, params);
|
|
136
|
+
if (!t || t.m === 0) return null;
|
|
137
|
+
const m = -1 / t.m;
|
|
138
|
+
const c = t.at.y - m * t.at.x;
|
|
139
|
+
return {
|
|
140
|
+
m,
|
|
141
|
+
c,
|
|
142
|
+
at: t.at,
|
|
143
|
+
f: (x) => m * x + c
|
|
144
|
+
};
|
|
145
|
+
}
|
|
146
|
+
/**
|
|
147
|
+
* Composite-Simpson definite integral ∫_a^b f dx, on a NUMERIC function.
|
|
148
|
+
*
|
|
149
|
+
* Error O(h⁴) against O(h) for a Riemann sum, so at n≈1000 it is accurate to near machine
|
|
150
|
+
* precision for a smooth integrand and serves as the reference value a Riemann sum converges
|
|
151
|
+
* toward. `n` is forced even, as the rule requires. Not adaptive: a singularity inside [a, b] is
|
|
152
|
+
* not detected, which is why the callers in this file (`areaBetween`) split at the crossings first.
|
|
153
|
+
*
|
|
154
|
+
* Named `quadrature` because `calculus.ts` beside it exports `integrate`, which integrates an AST
|
|
155
|
+
* SYMBOLICALLY: different argument type, different return type, different meaning. (`simpson`
|
|
156
|
+
* would become a lie the moment the rule changed.) The single implementation, after two copies of
|
|
157
|
+
* it were found in labs; see `KERNEL-CONTRACT.md` §7.
|
|
158
|
+
*/
|
|
159
|
+
function quadrature(f, a, b, n = 1e3) {
|
|
160
|
+
if (a === b) return 0;
|
|
161
|
+
const m = Math.max(2, Math.ceil(n / 2) * 2);
|
|
162
|
+
const h = (b - a) / m;
|
|
163
|
+
let sum = f(a) + f(b);
|
|
164
|
+
for (let i = 1; i < m; i++) sum += (i % 2 === 1 ? 4 : 2) * f(a + i * h);
|
|
165
|
+
return sum * h / 3;
|
|
166
|
+
}
|
|
167
|
+
/**
|
|
168
|
+
* Geometric area between f and g over [a,b]. SPLITS at every crossing so the
|
|
169
|
+
* pieces where g > f don't cancel the pieces where f > g (which a single
|
|
170
|
+
* |∫(f−g)| would). Sums |∫| over each sub-interval — the area an exam actually
|
|
171
|
+
* wants.
|
|
172
|
+
*/
|
|
173
|
+
function areaBetween(f, g, a, b, n = 1e3) {
|
|
174
|
+
const d = (x) => f(x) - g(x);
|
|
175
|
+
const cuts = [
|
|
176
|
+
a,
|
|
177
|
+
...roots(d, a, b).filter((x) => x > a + 1e-9 && x < b - 1e-9).sort((u, v) => u - v),
|
|
178
|
+
b
|
|
179
|
+
];
|
|
180
|
+
const per = Math.max(20, Math.round(n / Math.max(1, cuts.length - 1)));
|
|
181
|
+
let area = 0;
|
|
182
|
+
for (let i = 0; i < cuts.length - 1; i++) area += Math.abs(quadrature(d, cuts[i], cuts[i + 1], per));
|
|
183
|
+
return area;
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
//#endregion
|
|
187
|
+
export { areaBetween, intersections, normalAt, quadrature, roots, tangentAt };
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
//#region src/math/answer-check.d.ts
|
|
2
|
+
/**
|
|
3
|
+
* answer-check, the "is the student right?" layer, built on the expr engine beside it. Two modes,
|
|
4
|
+
* the ones exams need:
|
|
5
|
+
*
|
|
6
|
+
* • NUMBER — value within tolerance, parsed so `pi/2` and `2*sqrt(5)` count.
|
|
7
|
+
* • EXPRESSION — any algebraically EQUIVALENT form accepted, checked BOTH symbolically
|
|
8
|
+
* (simplify(student − answer) → 0) AND numerically by sampling, so
|
|
9
|
+
* `(x+1)(x+2)` ≡ `x^2+3x+2`.
|
|
10
|
+
*
|
|
11
|
+
* Both passes run because neither is sufficient alone: the simplifier cannot collapse every
|
|
12
|
+
* equivalent pair, and sampling alone would accept two expressions that happen to agree on the
|
|
13
|
+
* sample points. Symbolic first, numeric as the fallback, and a minimum count of agreeing FINITE
|
|
14
|
+
* samples so a pair that is undefined everywhere in the window cannot pass by default.
|
|
15
|
+
*
|
|
16
|
+
* Tolerances are relative, not absolute: a 1% window on a quantity of order 10⁵ is not the same
|
|
17
|
+
* marking scheme as a 1% window on 0.3, and only one of those is what an exam means.
|
|
18
|
+
*
|
|
19
|
+
* Pure: no React, no pixels.
|
|
20
|
+
*/
|
|
21
|
+
/** Evaluate a numeric answer string (`3.14`, `pi/2`, `2*sqrt(5)`) → number (NaN if invalid). */
|
|
22
|
+
declare function parseValue(raw: string): number;
|
|
23
|
+
declare function normalizeMathInput(raw: string): string;
|
|
24
|
+
/** Numeric match with a relative-ish tolerance (default ~1% of scale). */
|
|
25
|
+
declare function checkNumber(student: number, value: number, tol?: number): boolean;
|
|
26
|
+
interface ExprCheckOpts {
|
|
27
|
+
/** Variables to sample (defaults to the union of both sides' free vars). */
|
|
28
|
+
vars?: string[];
|
|
29
|
+
/** Sampling domain for the numeric pass. */
|
|
30
|
+
domain?: [number, number];
|
|
31
|
+
tol?: number;
|
|
32
|
+
samples?: number;
|
|
33
|
+
}
|
|
34
|
+
/** True if `student` is algebraically equivalent to `answer` (symbolic OR numeric). */
|
|
35
|
+
declare function checkExpression(student: string, answer: string, opts?: ExprCheckOpts): boolean;
|
|
36
|
+
type AnswerSpec = {
|
|
37
|
+
kind: 'number';
|
|
38
|
+
value: number;
|
|
39
|
+
tol?: number;
|
|
40
|
+
} | {
|
|
41
|
+
kind: 'expression';
|
|
42
|
+
value: string;
|
|
43
|
+
vars?: string[];
|
|
44
|
+
domain?: [number, number];
|
|
45
|
+
tol?: number;
|
|
46
|
+
};
|
|
47
|
+
/** Check a raw student string against an authored answer spec. */
|
|
48
|
+
declare function checkAnswer(spec: AnswerSpec, raw: string): boolean;
|
|
49
|
+
//#endregion
|
|
50
|
+
export { AnswerSpec, ExprCheckOpts, checkAnswer, checkExpression, checkNumber, normalizeMathInput, parseValue };
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
import { parse } from "./parse.mjs";
|
|
2
|
+
import { simplify } from "./calculus.mjs";
|
|
3
|
+
import { compileExpr } from "./expr.mjs";
|
|
4
|
+
|
|
5
|
+
//#region src/math/answer-check.ts
|
|
6
|
+
/**
|
|
7
|
+
* answer-check, the "is the student right?" layer, built on the expr engine beside it. Two modes,
|
|
8
|
+
* the ones exams need:
|
|
9
|
+
*
|
|
10
|
+
* • NUMBER — value within tolerance, parsed so `pi/2` and `2*sqrt(5)` count.
|
|
11
|
+
* • EXPRESSION — any algebraically EQUIVALENT form accepted, checked BOTH symbolically
|
|
12
|
+
* (simplify(student − answer) → 0) AND numerically by sampling, so
|
|
13
|
+
* `(x+1)(x+2)` ≡ `x^2+3x+2`.
|
|
14
|
+
*
|
|
15
|
+
* Both passes run because neither is sufficient alone: the simplifier cannot collapse every
|
|
16
|
+
* equivalent pair, and sampling alone would accept two expressions that happen to agree on the
|
|
17
|
+
* sample points. Symbolic first, numeric as the fallback, and a minimum count of agreeing FINITE
|
|
18
|
+
* samples so a pair that is undefined everywhere in the window cannot pass by default.
|
|
19
|
+
*
|
|
20
|
+
* Tolerances are relative, not absolute: a 1% window on a quantity of order 10⁵ is not the same
|
|
21
|
+
* marking scheme as a 1% window on 0.3, and only one of those is what an exam means.
|
|
22
|
+
*
|
|
23
|
+
* Pure: no React, no pixels.
|
|
24
|
+
*/
|
|
25
|
+
/** Compile, returning the usable form or null (never the error union). */
|
|
26
|
+
function tryCompile(src) {
|
|
27
|
+
const c = compileExpr(src);
|
|
28
|
+
if (c.error !== void 0) return null;
|
|
29
|
+
return c;
|
|
30
|
+
}
|
|
31
|
+
/** Evaluate a numeric answer string (`3.14`, `pi/2`, `2*sqrt(5)`) → number (NaN if invalid). */
|
|
32
|
+
function parseValue(raw) {
|
|
33
|
+
const c = tryCompile(normalizeMathInput(raw));
|
|
34
|
+
return c ? c.fn({}) : NaN;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Make exam-natural input parse: accept implicit multiplication (`2x` → `2*x`,
|
|
38
|
+
* `)(` → `)*(`) and a leading `y =` (`y = 2x − 3` → `2*x - 3`). Conservative ,
|
|
39
|
+
* never inserts `*` before `(` after a letter, so function calls like `sin(x)`
|
|
40
|
+
* survive. Unicode minus → ascii.
|
|
41
|
+
*/
|
|
42
|
+
const SUPERSCRIPT = {
|
|
43
|
+
"⁰": "0",
|
|
44
|
+
"¹": "1",
|
|
45
|
+
"²": "2",
|
|
46
|
+
"³": "3",
|
|
47
|
+
"⁴": "4",
|
|
48
|
+
"⁵": "5",
|
|
49
|
+
"⁶": "6",
|
|
50
|
+
"⁷": "7",
|
|
51
|
+
"⁸": "8",
|
|
52
|
+
"⁹": "9"
|
|
53
|
+
};
|
|
54
|
+
function normalizeMathInput(raw) {
|
|
55
|
+
let s = raw.trim().replace(/−/g, "-").replace(/×/g, "*").replace(/÷/g, "/");
|
|
56
|
+
s = s.replace(/[⁰¹²³⁴⁵⁶⁷⁸⁹]+/g, (m) => "^" + [...m].map((ch) => SUPERSCRIPT[ch]).join(""));
|
|
57
|
+
s = s.replace(/\*\*/g, "^");
|
|
58
|
+
s = s.replace(/\s+/g, "");
|
|
59
|
+
s = s.replace(/^y=/i, "");
|
|
60
|
+
s = s.replace(/(\d)(?![eE][+-]?\d)([a-zA-Z(])/g, "$1*$2");
|
|
61
|
+
s = s.replace(/\)([a-zA-Z0-9(])/g, ")*$1");
|
|
62
|
+
return s;
|
|
63
|
+
}
|
|
64
|
+
/** Numeric match with a relative-ish tolerance (default ~1% of scale). */
|
|
65
|
+
function checkNumber(student, value, tol = .01) {
|
|
66
|
+
if (!Number.isFinite(student) || !Number.isFinite(value)) return false;
|
|
67
|
+
return Math.abs(student - value) <= tol * Math.max(1, Math.abs(value));
|
|
68
|
+
}
|
|
69
|
+
const isZeroNode = (n, eps = 1e-9) => n.type === "num" && Math.abs(n.value) < eps;
|
|
70
|
+
/** True if `student` is algebraically equivalent to `answer` (symbolic OR numeric). */
|
|
71
|
+
function checkExpression(student, answer, opts = {}) {
|
|
72
|
+
const a = tryCompile(normalizeMathInput(student));
|
|
73
|
+
const b = tryCompile(normalizeMathInput(answer));
|
|
74
|
+
if (!a || !b) return false;
|
|
75
|
+
try {
|
|
76
|
+
if (isZeroNode(simplify(parse(`(${normalizeMathInput(student)}) - (${normalizeMathInput(answer)})`)), opts.tol ?? 1e-9)) return true;
|
|
77
|
+
} catch {}
|
|
78
|
+
const vars = opts.vars ?? [...new Set([...a.vars, ...b.vars])];
|
|
79
|
+
const [lo, hi] = opts.domain ?? [-3.3, 3.7];
|
|
80
|
+
const tol = opts.tol ?? 1e-6;
|
|
81
|
+
const samples = opts.samples ?? 32;
|
|
82
|
+
const PHI = .6180339887498949;
|
|
83
|
+
const R2 = .4142135623730951;
|
|
84
|
+
let finite = 0;
|
|
85
|
+
for (let i = 0; i < samples; i++) {
|
|
86
|
+
const scope = {};
|
|
87
|
+
vars.forEach((v, j) => {
|
|
88
|
+
scope[v] = lo + (hi - lo) * (((i + 1) * PHI + (j + 1) * R2) % 1);
|
|
89
|
+
});
|
|
90
|
+
const ya = a.fn(scope);
|
|
91
|
+
const yb = b.fn(scope);
|
|
92
|
+
if (!Number.isFinite(ya) || !Number.isFinite(yb)) continue;
|
|
93
|
+
finite++;
|
|
94
|
+
if (Math.abs(ya - yb) > tol * Math.max(1, Math.abs(ya), Math.abs(yb))) return false;
|
|
95
|
+
}
|
|
96
|
+
return finite >= 5;
|
|
97
|
+
}
|
|
98
|
+
/** Check a raw student string against an authored answer spec. */
|
|
99
|
+
function checkAnswer(spec, raw) {
|
|
100
|
+
if (!raw || !raw.trim()) return false;
|
|
101
|
+
if (spec.kind === "number") return checkNumber(parseValue(raw), spec.value, spec.tol);
|
|
102
|
+
return checkExpression(raw, spec.value, spec);
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
//#endregion
|
|
106
|
+
export { checkAnswer, checkExpression, checkNumber, normalizeMathInput, parseValue };
|
package/dist/math/calculus.d.mts
CHANGED
|
@@ -4,16 +4,11 @@ import { Node } from "./ast.mjs";
|
|
|
4
4
|
/** Exact symbolic derivative, or `null` if a non-differentiable node is present. */
|
|
5
5
|
declare function differentiate(node: Node, x: string): Node | null;
|
|
6
6
|
/**
|
|
7
|
-
* Exact symbolic antiderivative
|
|
7
|
+
* Exact symbolic antiderivative, trying the expression as written and then multiplied out.
|
|
8
8
|
*
|
|
9
|
-
* The
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
* Covers the Cambridge P1/P3 toolkit: linearity, the power rule including the `1/x → ln|x|`
|
|
14
|
-
* exception, and any of the above composed with a LINEAR inner function. Returns null for
|
|
15
|
-
* integration by parts, by non-linear substitution, and partial fractions, so a caller can fall
|
|
16
|
-
* back to the numerical `integrate` in `core/numeric` and show area rather than a wrong formula.
|
|
9
|
+
* The second attempt is what makes `∫x(x+1)dx` and `∫(R²−x²)²dx` work: expand distributes, collect
|
|
10
|
+
* turns the resulting repeated factors back into powers, and then the ordinary power rule applies
|
|
11
|
+
* term by term. A single retry, because both passes are idempotent on their own output.
|
|
17
12
|
*/
|
|
18
13
|
declare function integrate(node: Node, x: string): Node | null;
|
|
19
14
|
/**
|