@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,14 @@
|
|
|
1
|
+
import { AirtimeResult, Client, ClientShare, HOUSEHOLD, PAYLOAD_BITS, TURN_OVERHEAD_US, rateFromRssi, shareAirtime, signalWord } from "./airtime.mjs";
|
|
2
|
+
import { Blocker, EIRP_DBM, GENERATIONS, Generation, GenerationId, HANDSET_SENSITIVITY_DBM, MAX_PATH_LOSS_DB, TASKS, TERRAIN, Task, Terrain, TerrainSpec, blockedBy, canServe, cellAreaKm2, cellRadiusKm, firstGenerationFor, generationById, pathLossDb, rssiFromMast, towersFor } from "./cellular.mjs";
|
|
3
|
+
import { DEFAULT_PATH, Encapsulation, EncapsulationSegment, HEADERS, Header, LayerKind, NodeKind, OVERHEAD_BYTES, PathNode, WireFrame, decapsulate, encapsulate, frameOn, journey, opensTo, segmentsOf } from "./encapsulation.mjs";
|
|
4
|
+
import { DEFAULT_DRIVE, DRIVE_WINDOW, DROP_AFTER_KM, DriveOptions, DriveResult, DriveSample, HandoverEvent, MarginVerdict, Mast, TWO_MAST_ROAD, drive, judgeMargin } from "./handover.mjs";
|
|
5
|
+
import { DEFAULT_RTO_MS, DROPS, DropSpec, DropWhich, HandshakeOptions, HandshakeResult, Side, TcpSegment, firstResponseMs, handshake } from "./handshake.mjs";
|
|
6
|
+
import { MEDIA, Medium, MediumId, PAIRS, PINOUTS, PinoutCheck, PinoutStandard, SCENARIOS, Scenario, WIRE_INK, WIRE_LABEL, WireColor, cableKind, checkPinout, isSplitPair, isStriped, pairOf, pairPins, ruleOut } from "./media.mjs";
|
|
7
|
+
import { C_KM_S, EARTH_AREA_KM2, EARTH_RADIUS_KM, MU_EARTH, ORBITS, Orbit, centralAngleRad, footprintAreaKm2, footprintRadiusKm, oneWayMs, orbitById, orbitalPeriodMin, passMinutes, roundTripMs, satellitesForCoverage } from "./satellite.mjs";
|
|
8
|
+
import { C, PENETRATION, Penetration, PenetrationSpec, SPECTRUM, SpectrumBand, bandById, decades, humanFrequency, humanLength, logPosition, quarterWaveM, wavelengthM } from "./spectrum.mjs";
|
|
9
|
+
import { FrameResult, MacEntry, SwitchDevice, SwitchEvent, SwitchPort, SwitchState, clearTable, linkUp, makeSwitch, sendFrame, setPortEnabled } from "./switch.mjs";
|
|
10
|
+
import { BroadcastResult, DeliveryResult, Vlan, VlanPort, VlanState, broadcastFrom, domainCount, domainOf, isLive, makeVlanSwitch, sendBetween, setPortVlan, setRouting } from "./vlan.mjs";
|
|
11
|
+
import { Field, OBSERVERS, Observer, ObserverId, Setup, Sighting, TUNNEL_OVERHEAD_BYTES, canReadContents, canSeeDestination, observe, observersFor, surveyOf, usableBytes } from "./vpn.mjs";
|
|
12
|
+
import { ADVICE, Exposure, LISTENERS, Listener, PROTECTIONS, PrivacyVerdict, Protection, ProtectionSpec, Transport, judgePrivacy, linkReadable, whatTheySee } from "./wifi-privacy.mjs";
|
|
13
|
+
import { BANDS, Band, BandSpec, FLOOR_PLANS, FloorPlan, GRADES, Grade, GradeSpec, MATERIALS, MaterialSpec, NOISE_FLOOR_DBM, PATH_LOSS_EXPONENT, Point, Reading, Room, RoomVerdict, Spot, TX_POWER_DBM, Wall, WallMaterial, bestPlacement, coverageGrid, coverageScore, grade, referenceLossDb, roomVerdicts, signalAt, throughputMbps, wallsBetween } from "./wifi.mjs";
|
|
14
|
+
export { ADVICE, AirtimeResult, BANDS, Band, BandSpec, Blocker, BroadcastResult, C, C_KM_S, Client, ClientShare, DEFAULT_DRIVE, DEFAULT_PATH, DEFAULT_RTO_MS, DRIVE_WINDOW, DROPS, DROP_AFTER_KM, DeliveryResult, DriveOptions, DriveResult, DriveSample, DropSpec, DropWhich, EARTH_AREA_KM2, EARTH_RADIUS_KM, EIRP_DBM, Encapsulation, EncapsulationSegment, Exposure, FLOOR_PLANS, Field, FloorPlan, FrameResult, GENERATIONS, GRADES, Generation, GenerationId, Grade, GradeSpec, HANDSET_SENSITIVITY_DBM, HEADERS, HOUSEHOLD, HandoverEvent, HandshakeOptions, HandshakeResult, Header, LISTENERS, LayerKind, Listener, MATERIALS, MAX_PATH_LOSS_DB, MEDIA, MU_EARTH, MacEntry, MarginVerdict, Mast, MaterialSpec, Medium, MediumId, NOISE_FLOOR_DBM, NodeKind, OBSERVERS, ORBITS, OVERHEAD_BYTES, Observer, ObserverId, Orbit, PAIRS, PATH_LOSS_EXPONENT, PAYLOAD_BITS, PENETRATION, PINOUTS, PROTECTIONS, PathNode, Penetration, PenetrationSpec, PinoutCheck, PinoutStandard, Point, PrivacyVerdict, Protection, ProtectionSpec, Reading, Room, RoomVerdict, SCENARIOS, SPECTRUM, Scenario, Setup, Side, Sighting, SpectrumBand, Spot, SwitchDevice, SwitchEvent, SwitchPort, SwitchState, TASKS, TERRAIN, TUNNEL_OVERHEAD_BYTES, TURN_OVERHEAD_US, TWO_MAST_ROAD, TX_POWER_DBM, Task, TcpSegment, Terrain, TerrainSpec, Transport, Vlan, VlanPort, VlanState, WIRE_INK, WIRE_LABEL, Wall, WallMaterial, WireColor, WireFrame, bandById, bestPlacement, blockedBy, broadcastFrom, cableKind, canReadContents, canSeeDestination, canServe, cellAreaKm2, cellRadiusKm, centralAngleRad, checkPinout, clearTable, coverageGrid, coverageScore, decades, decapsulate, domainCount, domainOf, drive, encapsulate, firstGenerationFor, firstResponseMs, footprintAreaKm2, footprintRadiusKm, frameOn, generationById, grade, handshake, humanFrequency, humanLength, isLive, isSplitPair, isStriped, journey, judgeMargin, judgePrivacy, linkReadable, linkUp, logPosition, makeSwitch, makeVlanSwitch, observe, observersFor, oneWayMs, opensTo, orbitById, orbitalPeriodMin, pairOf, pairPins, passMinutes, pathLossDb, quarterWaveM, rateFromRssi, referenceLossDb, roomVerdicts, roundTripMs, rssiFromMast, ruleOut, satellitesForCoverage, segmentsOf, sendBetween, sendFrame, setPortEnabled, setPortVlan, setRouting, shareAirtime, signalAt, signalWord, surveyOf, throughputMbps, towersFor, usableBytes, wallsBetween, wavelengthM, whatTheySee };
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { HOUSEHOLD, PAYLOAD_BITS, TURN_OVERHEAD_US, rateFromRssi, shareAirtime, signalWord } from "./airtime.mjs";
|
|
2
|
+
import { EIRP_DBM, GENERATIONS, HANDSET_SENSITIVITY_DBM, MAX_PATH_LOSS_DB, TASKS, TERRAIN, blockedBy, canServe, cellAreaKm2, cellRadiusKm, firstGenerationFor, generationById, pathLossDb, rssiFromMast, towersFor } from "./cellular.mjs";
|
|
3
|
+
import { DEFAULT_PATH, HEADERS, OVERHEAD_BYTES, decapsulate, encapsulate, frameOn, journey, opensTo, segmentsOf } from "./encapsulation.mjs";
|
|
4
|
+
import { DEFAULT_DRIVE, DRIVE_WINDOW, DROP_AFTER_KM, TWO_MAST_ROAD, drive, judgeMargin } from "./handover.mjs";
|
|
5
|
+
import { DEFAULT_RTO_MS, DROPS, firstResponseMs, handshake } from "./handshake.mjs";
|
|
6
|
+
import { MEDIA, PAIRS, PINOUTS, SCENARIOS, WIRE_INK, WIRE_LABEL, cableKind, checkPinout, isSplitPair, isStriped, pairOf, pairPins, ruleOut } from "./media.mjs";
|
|
7
|
+
import { C_KM_S, EARTH_AREA_KM2, EARTH_RADIUS_KM, MU_EARTH, ORBITS, centralAngleRad, footprintAreaKm2, footprintRadiusKm, oneWayMs, orbitById, orbitalPeriodMin, passMinutes, roundTripMs, satellitesForCoverage } from "./satellite.mjs";
|
|
8
|
+
import { C, PENETRATION, SPECTRUM, bandById, decades, humanFrequency, humanLength, logPosition, quarterWaveM, wavelengthM } from "./spectrum.mjs";
|
|
9
|
+
import { clearTable, linkUp, makeSwitch, sendFrame, setPortEnabled } from "./switch.mjs";
|
|
10
|
+
import { broadcastFrom, domainCount, domainOf, isLive, makeVlanSwitch, sendBetween, setPortVlan, setRouting } from "./vlan.mjs";
|
|
11
|
+
import { OBSERVERS, TUNNEL_OVERHEAD_BYTES, canReadContents, canSeeDestination, observe, observersFor, surveyOf, usableBytes } from "./vpn.mjs";
|
|
12
|
+
import { ADVICE, LISTENERS, PROTECTIONS, judgePrivacy, linkReadable, whatTheySee } from "./wifi-privacy.mjs";
|
|
13
|
+
import { BANDS, FLOOR_PLANS, GRADES, MATERIALS, NOISE_FLOOR_DBM, PATH_LOSS_EXPONENT, TX_POWER_DBM, bestPlacement, coverageGrid, coverageScore, grade, referenceLossDb, roomVerdicts, signalAt, throughputMbps, wallsBetween } from "./wifi.mjs";
|
|
14
|
+
|
|
15
|
+
export { ADVICE, BANDS, C, C_KM_S, DEFAULT_DRIVE, DEFAULT_PATH, DEFAULT_RTO_MS, DRIVE_WINDOW, DROPS, DROP_AFTER_KM, EARTH_AREA_KM2, EARTH_RADIUS_KM, EIRP_DBM, FLOOR_PLANS, GENERATIONS, GRADES, HANDSET_SENSITIVITY_DBM, HEADERS, HOUSEHOLD, LISTENERS, MATERIALS, MAX_PATH_LOSS_DB, MEDIA, MU_EARTH, NOISE_FLOOR_DBM, OBSERVERS, ORBITS, OVERHEAD_BYTES, PAIRS, PATH_LOSS_EXPONENT, PAYLOAD_BITS, PENETRATION, PINOUTS, PROTECTIONS, SCENARIOS, SPECTRUM, TASKS, TERRAIN, TUNNEL_OVERHEAD_BYTES, TURN_OVERHEAD_US, TWO_MAST_ROAD, TX_POWER_DBM, WIRE_INK, WIRE_LABEL, bandById, bestPlacement, blockedBy, broadcastFrom, cableKind, canReadContents, canSeeDestination, canServe, cellAreaKm2, cellRadiusKm, centralAngleRad, checkPinout, clearTable, coverageGrid, coverageScore, decades, decapsulate, domainCount, domainOf, drive, encapsulate, firstGenerationFor, firstResponseMs, footprintAreaKm2, footprintRadiusKm, frameOn, generationById, grade, handshake, humanFrequency, humanLength, isLive, isSplitPair, isStriped, journey, judgeMargin, judgePrivacy, linkReadable, linkUp, logPosition, makeSwitch, makeVlanSwitch, observe, observersFor, oneWayMs, opensTo, orbitById, orbitalPeriodMin, pairOf, pairPins, passMinutes, pathLossDb, quarterWaveM, rateFromRssi, referenceLossDb, roomVerdicts, roundTripMs, rssiFromMast, ruleOut, satellitesForCoverage, segmentsOf, sendBetween, sendFrame, setPortEnabled, setPortVlan, setRouting, shareAirtime, signalAt, signalWord, surveyOf, throughputMbps, towersFor, usableBytes, wallsBetween, wavelengthM, whatTheySee };
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
//#region src/networking/models/media.d.ts
|
|
2
|
+
/**
|
|
3
|
+
* The physical layer: what the signal actually travels through, and how the eight wires are ordered.
|
|
4
|
+
*
|
|
5
|
+
* Two things get memorised without being understood. The first is the T568B colour order, which
|
|
6
|
+
* students chant and cannot reconstruct. The second is that "the cable" is one thing, when copper,
|
|
7
|
+
* fibre and radio carry a signal by three different physical mechanisms with three different limits.
|
|
8
|
+
*
|
|
9
|
+
* The order is reconstructable once you see the PAIRS. Four twisted pairs go into eight pins, and
|
|
10
|
+
* the blue pair sits in the middle at 4 and 5 so an RJ45 socket stays compatible with an older
|
|
11
|
+
* two-wire telephone plug. That single constraint pushes the green pair apart, which is why pin 3
|
|
12
|
+
* is white-green and pin 6 is green with two other wires between them. It looks arbitrary and is not.
|
|
13
|
+
*/
|
|
14
|
+
type WireColor = "white-orange" | "orange" | "white-green" | "green" | "white-blue" | "blue" | "white-brown" | "brown";
|
|
15
|
+
/**
|
|
16
|
+
* Real wire colours, so they are fixed rather than themed. A green wire is green in both themes
|
|
17
|
+
* for the same reason the link LED is green: the colour IS the information, and a student matching
|
|
18
|
+
* this against a cable in their hand needs it to agree.
|
|
19
|
+
*/
|
|
20
|
+
declare const WIRE_INK: Record<WireColor, string>;
|
|
21
|
+
/** A striped wire is the pale half of its pair. */
|
|
22
|
+
declare const isStriped: (wire: WireColor) => boolean;
|
|
23
|
+
declare const WIRE_LABEL: Record<WireColor, string>;
|
|
24
|
+
type PinoutStandard = "T568A" | "T568B";
|
|
25
|
+
/** Pin 1 to pin 8, left to right with the clip facing away from you. */
|
|
26
|
+
declare const PINOUTS: Record<PinoutStandard, WireColor[]>;
|
|
27
|
+
/** The four twisted pairs, by the colour they are named after. */
|
|
28
|
+
declare const PAIRS: {
|
|
29
|
+
name: string;
|
|
30
|
+
wires: [WireColor, WireColor];
|
|
31
|
+
}[];
|
|
32
|
+
/** Which pair a wire belongs to, 0-based, or -1 if the colour is not a pair member. */
|
|
33
|
+
declare const pairOf: (wire: WireColor) => number;
|
|
34
|
+
/** The pin positions (1-based) each pair occupies under a standard. */
|
|
35
|
+
declare function pairPins(standard: PinoutStandard, pairName: string): number[];
|
|
36
|
+
/** True when a pair sits on two pins that are not next to each other. */
|
|
37
|
+
declare const isSplitPair: (standard: PinoutStandard, pairName: string) => boolean;
|
|
38
|
+
interface PinoutCheck {
|
|
39
|
+
correct: boolean;
|
|
40
|
+
/** 1-based pins that do not match the standard. */
|
|
41
|
+
wrong: number[];
|
|
42
|
+
placed: number;
|
|
43
|
+
}
|
|
44
|
+
/** Compare an attempt against a standard. Empty slots count as not yet placed, not as wrong. */
|
|
45
|
+
declare function checkPinout(attempt: readonly (WireColor | undefined)[], standard: PinoutStandard): PinoutCheck;
|
|
46
|
+
/**
|
|
47
|
+
* A cable with the same standard at both ends is straight-through; different ends make a crossover.
|
|
48
|
+
* Modern gear auto-detects, which is worth saying, because it is why crossover cables have
|
|
49
|
+
* essentially disappeared and why the distinction still appears in every exam.
|
|
50
|
+
*/
|
|
51
|
+
declare const cableKind: (endA: PinoutStandard, endB: PinoutStandard) => "straight-through" | "crossover";
|
|
52
|
+
type MediumId = "copper" | "fibre" | "radio";
|
|
53
|
+
interface Medium {
|
|
54
|
+
id: MediumId;
|
|
55
|
+
label: string;
|
|
56
|
+
/** What physically carries the signal. */
|
|
57
|
+
carrier: string;
|
|
58
|
+
/** Practical maximum for one run, in metres. Radio is a typical indoor figure. */
|
|
59
|
+
maxMetres: number;
|
|
60
|
+
typicalGbps: number;
|
|
61
|
+
/** Survives electrical noise from motors, lighting and power cable runs. */
|
|
62
|
+
emiImmune: boolean;
|
|
63
|
+
/** Can anyone within range receive the signal without touching anything. */
|
|
64
|
+
broadcast: boolean;
|
|
65
|
+
note: string;
|
|
66
|
+
}
|
|
67
|
+
declare const MEDIA: Medium[];
|
|
68
|
+
interface Scenario {
|
|
69
|
+
id: string;
|
|
70
|
+
need: string;
|
|
71
|
+
metres: number;
|
|
72
|
+
/** True when the run passes heavy electrical machinery. */
|
|
73
|
+
noisy: boolean;
|
|
74
|
+
mustMove: boolean;
|
|
75
|
+
best: MediumId;
|
|
76
|
+
why: string;
|
|
77
|
+
}
|
|
78
|
+
declare const SCENARIOS: Scenario[];
|
|
79
|
+
/** Is a medium usable for a scenario at all, and if not, why not. */
|
|
80
|
+
declare function ruleOut(medium: Medium, scenario: Scenario): string | null;
|
|
81
|
+
//#endregion
|
|
82
|
+
export { MEDIA, Medium, MediumId, PAIRS, PINOUTS, PinoutCheck, PinoutStandard, SCENARIOS, Scenario, WIRE_INK, WIRE_LABEL, WireColor, cableKind, checkPinout, isSplitPair, isStriped, pairOf, pairPins, ruleOut };
|
|
@@ -0,0 +1,188 @@
|
|
|
1
|
+
//#region src/networking/models/media.ts
|
|
2
|
+
/**
|
|
3
|
+
* Real wire colours, so they are fixed rather than themed. A green wire is green in both themes
|
|
4
|
+
* for the same reason the link LED is green: the colour IS the information, and a student matching
|
|
5
|
+
* this against a cable in their hand needs it to agree.
|
|
6
|
+
*/
|
|
7
|
+
const WIRE_INK = {
|
|
8
|
+
"white-orange": "oklch(0.72 0.16 55)",
|
|
9
|
+
orange: "oklch(0.68 0.19 48)",
|
|
10
|
+
"white-green": "oklch(0.70 0.15 150)",
|
|
11
|
+
green: "oklch(0.58 0.17 148)",
|
|
12
|
+
"white-blue": "oklch(0.70 0.13 250)",
|
|
13
|
+
blue: "oklch(0.55 0.18 255)",
|
|
14
|
+
"white-brown": "oklch(0.62 0.07 60)",
|
|
15
|
+
brown: "oklch(0.45 0.08 55)"
|
|
16
|
+
};
|
|
17
|
+
/** A striped wire is the pale half of its pair. */
|
|
18
|
+
const isStriped = (wire) => wire.startsWith("white-");
|
|
19
|
+
const WIRE_LABEL = {
|
|
20
|
+
"white-orange": "white / orange",
|
|
21
|
+
orange: "orange",
|
|
22
|
+
"white-green": "white / green",
|
|
23
|
+
green: "green",
|
|
24
|
+
"white-blue": "white / blue",
|
|
25
|
+
blue: "blue",
|
|
26
|
+
"white-brown": "white / brown",
|
|
27
|
+
brown: "brown"
|
|
28
|
+
};
|
|
29
|
+
/** Pin 1 to pin 8, left to right with the clip facing away from you. */
|
|
30
|
+
const PINOUTS = {
|
|
31
|
+
T568B: [
|
|
32
|
+
"white-orange",
|
|
33
|
+
"orange",
|
|
34
|
+
"white-green",
|
|
35
|
+
"blue",
|
|
36
|
+
"white-blue",
|
|
37
|
+
"green",
|
|
38
|
+
"white-brown",
|
|
39
|
+
"brown"
|
|
40
|
+
],
|
|
41
|
+
T568A: [
|
|
42
|
+
"white-green",
|
|
43
|
+
"green",
|
|
44
|
+
"white-orange",
|
|
45
|
+
"blue",
|
|
46
|
+
"white-blue",
|
|
47
|
+
"orange",
|
|
48
|
+
"white-brown",
|
|
49
|
+
"brown"
|
|
50
|
+
]
|
|
51
|
+
};
|
|
52
|
+
/** The four twisted pairs, by the colour they are named after. */
|
|
53
|
+
const PAIRS = [
|
|
54
|
+
{
|
|
55
|
+
name: "orange",
|
|
56
|
+
wires: ["white-orange", "orange"]
|
|
57
|
+
},
|
|
58
|
+
{
|
|
59
|
+
name: "green",
|
|
60
|
+
wires: ["white-green", "green"]
|
|
61
|
+
},
|
|
62
|
+
{
|
|
63
|
+
name: "blue",
|
|
64
|
+
wires: ["white-blue", "blue"]
|
|
65
|
+
},
|
|
66
|
+
{
|
|
67
|
+
name: "brown",
|
|
68
|
+
wires: ["white-brown", "brown"]
|
|
69
|
+
}
|
|
70
|
+
];
|
|
71
|
+
/** Which pair a wire belongs to, 0-based, or -1 if the colour is not a pair member. */
|
|
72
|
+
const pairOf = (wire) => PAIRS.findIndex((pair) => pair.wires.includes(wire));
|
|
73
|
+
/** The pin positions (1-based) each pair occupies under a standard. */
|
|
74
|
+
function pairPins(standard, pairName) {
|
|
75
|
+
const order = PINOUTS[standard];
|
|
76
|
+
const pair = PAIRS.find((item) => item.name === pairName);
|
|
77
|
+
if (!pair) return [];
|
|
78
|
+
return order.map((wire, index) => pair.wires.includes(wire) ? index + 1 : 0).filter((pin) => pin > 0);
|
|
79
|
+
}
|
|
80
|
+
/** True when a pair sits on two pins that are not next to each other. */
|
|
81
|
+
const isSplitPair = (standard, pairName) => {
|
|
82
|
+
const pins = pairPins(standard, pairName);
|
|
83
|
+
return pins.length === 2 && pins[1] - pins[0] !== 1;
|
|
84
|
+
};
|
|
85
|
+
/** Compare an attempt against a standard. Empty slots count as not yet placed, not as wrong. */
|
|
86
|
+
function checkPinout(attempt, standard) {
|
|
87
|
+
const target = PINOUTS[standard];
|
|
88
|
+
const wrong = [];
|
|
89
|
+
let placed = 0;
|
|
90
|
+
target.forEach((wire, index) => {
|
|
91
|
+
const got = attempt[index];
|
|
92
|
+
if (!got) return;
|
|
93
|
+
placed++;
|
|
94
|
+
if (got !== wire) wrong.push(index + 1);
|
|
95
|
+
});
|
|
96
|
+
return {
|
|
97
|
+
correct: placed === 8 && wrong.length === 0,
|
|
98
|
+
wrong,
|
|
99
|
+
placed
|
|
100
|
+
};
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* A cable with the same standard at both ends is straight-through; different ends make a crossover.
|
|
104
|
+
* Modern gear auto-detects, which is worth saying, because it is why crossover cables have
|
|
105
|
+
* essentially disappeared and why the distinction still appears in every exam.
|
|
106
|
+
*/
|
|
107
|
+
const cableKind = (endA, endB) => endA === endB ? "straight-through" : "crossover";
|
|
108
|
+
const MEDIA = [
|
|
109
|
+
{
|
|
110
|
+
id: "copper",
|
|
111
|
+
label: "Twisted pair copper",
|
|
112
|
+
carrier: "a changing voltage along a wire",
|
|
113
|
+
maxMetres: 100,
|
|
114
|
+
typicalGbps: 1,
|
|
115
|
+
emiImmune: false,
|
|
116
|
+
broadcast: false,
|
|
117
|
+
note: "Cheap, and every device already has the socket. The 100 m limit is the reason wiring closets exist."
|
|
118
|
+
},
|
|
119
|
+
{
|
|
120
|
+
id: "fibre",
|
|
121
|
+
label: "Optical fibre",
|
|
122
|
+
carrier: "pulses of light in a glass core",
|
|
123
|
+
maxMetres: 4e4,
|
|
124
|
+
typicalGbps: 10,
|
|
125
|
+
emiImmune: true,
|
|
126
|
+
broadcast: false,
|
|
127
|
+
note: "Light carries no current, so it ignores electrical noise entirely and can cross a city."
|
|
128
|
+
},
|
|
129
|
+
{
|
|
130
|
+
id: "radio",
|
|
131
|
+
label: "Radio (Wi-Fi)",
|
|
132
|
+
carrier: "radio waves through open air",
|
|
133
|
+
maxMetres: 40,
|
|
134
|
+
typicalGbps: 1,
|
|
135
|
+
emiImmune: false,
|
|
136
|
+
broadcast: true,
|
|
137
|
+
note: "No cable at all, and the medium is shared: everyone in range competes for it and can hear it."
|
|
138
|
+
}
|
|
139
|
+
];
|
|
140
|
+
const SCENARIOS = [
|
|
141
|
+
{
|
|
142
|
+
id: "desk",
|
|
143
|
+
need: "A desktop to the switch in the same room",
|
|
144
|
+
metres: 15,
|
|
145
|
+
noisy: false,
|
|
146
|
+
mustMove: false,
|
|
147
|
+
best: "copper",
|
|
148
|
+
why: "Short, fixed and cheap. Copper is already on both ends and there is nothing to gain by paying for anything else."
|
|
149
|
+
},
|
|
150
|
+
{
|
|
151
|
+
id: "buildings",
|
|
152
|
+
need: "Between two buildings 800 m apart",
|
|
153
|
+
metres: 800,
|
|
154
|
+
noisy: false,
|
|
155
|
+
mustMove: false,
|
|
156
|
+
best: "fibre",
|
|
157
|
+
why: "Copper stops working at about 100 m. Distance alone rules it out before any other argument."
|
|
158
|
+
},
|
|
159
|
+
{
|
|
160
|
+
id: "factory",
|
|
161
|
+
need: "Across a factory floor beside large motors",
|
|
162
|
+
metres: 60,
|
|
163
|
+
noisy: true,
|
|
164
|
+
mustMove: false,
|
|
165
|
+
best: "fibre",
|
|
166
|
+
why: "The distance suits copper, but motors throw electrical noise into it. Light carries no current, so the interference cannot reach the signal."
|
|
167
|
+
},
|
|
168
|
+
{
|
|
169
|
+
id: "phone",
|
|
170
|
+
need: "A phone carried around a café",
|
|
171
|
+
metres: 20,
|
|
172
|
+
noisy: false,
|
|
173
|
+
mustMove: true,
|
|
174
|
+
best: "radio",
|
|
175
|
+
why: "Nothing that moves can stay plugged in. That decides it before speed or cost are even considered."
|
|
176
|
+
}
|
|
177
|
+
];
|
|
178
|
+
/** Is a medium usable for a scenario at all, and if not, why not. */
|
|
179
|
+
function ruleOut(medium, scenario) {
|
|
180
|
+
if (scenario.mustMove && !scenario.metres) return null;
|
|
181
|
+
if (scenario.mustMove && medium.id !== "radio") return "a moving device cannot stay plugged into a cable";
|
|
182
|
+
if (scenario.metres > medium.maxMetres) return `the run is longer than ${medium.maxMetres} m`;
|
|
183
|
+
if (scenario.noisy && !medium.emiImmune) return "electrical noise from the machinery would corrupt the signal";
|
|
184
|
+
return null;
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
//#endregion
|
|
188
|
+
export { MEDIA, PAIRS, PINOUTS, SCENARIOS, WIRE_INK, WIRE_LABEL, cableKind, checkPinout, isSplitPair, isStriped, pairOf, pairPins, ruleOut };
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
//#region src/networking/models/satellite.d.ts
|
|
2
|
+
/**
|
|
3
|
+
* Satellite links: the one delay nobody can engineer away.
|
|
4
|
+
*
|
|
5
|
+
* Every other limit in this course yields to money. A weak room gets a second access point, a city
|
|
6
|
+
* gets more masts, a slow band gets refarmed. Distance does not yield to anything, because the signal
|
|
7
|
+
* travels at the speed of light and that is the end of the discussion.
|
|
8
|
+
*
|
|
9
|
+
* A geostationary satellite sits 35,786 km up. The signal has to climb that, come back down, and then
|
|
10
|
+
* do it again for the reply, so a round trip is roughly half a second before a single byte is
|
|
11
|
+
* processed. No better modem, no wider band and no amount of capital changes it. That is why
|
|
12
|
+
* satellite television, which is one-way and buffered, has always worked beautifully, and why a video
|
|
13
|
+
* call over the same link has always been unbearable.
|
|
14
|
+
*
|
|
15
|
+
* It is also the whole reason low orbit was worth the trouble. Flying at 550 km instead cuts the
|
|
16
|
+
* round trip by a factor of about sixty and brings interactive use back within reach. The price is
|
|
17
|
+
* paid twice over: a low satellite covers a tiny patch of ground so you need hundreds of them, and it
|
|
18
|
+
* crosses the sky in minutes, so the link must be handed from one satellite to the next exactly as a
|
|
19
|
+
* moving phone is handed between masts. Chapters 2 and 3 are the bill for this chapter's fix.
|
|
20
|
+
*/
|
|
21
|
+
/** Speed of light in vacuum, km/s. Every number in this file is a consequence of it. */
|
|
22
|
+
declare const C_KM_S: number;
|
|
23
|
+
/** Mean radius of the Earth, km. */
|
|
24
|
+
declare const EARTH_RADIUS_KM = 6371;
|
|
25
|
+
/** Standard gravitational parameter of the Earth, km³/s². */
|
|
26
|
+
declare const MU_EARTH = 398600.4418;
|
|
27
|
+
interface Orbit {
|
|
28
|
+
id: string;
|
|
29
|
+
label: string;
|
|
30
|
+
altitudeKm: number;
|
|
31
|
+
/** Lowest angle above the horizon at which a ground terminal can still work, in degrees. */
|
|
32
|
+
minElevationDeg: number;
|
|
33
|
+
use: string;
|
|
34
|
+
note: string;
|
|
35
|
+
}
|
|
36
|
+
declare const ORBITS: Orbit[];
|
|
37
|
+
/**
|
|
38
|
+
* Round trip in ms for a request and its reply, from propagation alone.
|
|
39
|
+
*
|
|
40
|
+
* Four times the altitude: up, down, up and down again. Deliberately propagation only, with nothing
|
|
41
|
+
* added for the modem, the gateway or the server. A learner should see the number that cannot be
|
|
42
|
+
* argued with first, and meet the extra overheads afterwards as things engineers can actually attack.
|
|
43
|
+
*/
|
|
44
|
+
declare const roundTripMs: (altitudeKm: number) => number;
|
|
45
|
+
/** One hop, ground to satellite to ground, in ms. What a one-way broadcast costs. */
|
|
46
|
+
declare const oneWayMs: (altitudeKm: number) => number;
|
|
47
|
+
/**
|
|
48
|
+
* Orbital period in minutes, from Kepler's third law.
|
|
49
|
+
*
|
|
50
|
+
* Worth computing rather than quoting, because it explains the two things about geostationary orbit
|
|
51
|
+
* that look like coincidences. It sits at exactly the altitude where one orbit takes a day, which is
|
|
52
|
+
* why it appears motionless, which is why a dish never has to move. There is only one such altitude,
|
|
53
|
+
* which is why that orbit is crowded and regulated.
|
|
54
|
+
*/
|
|
55
|
+
declare function orbitalPeriodMin(altitudeKm: number): number;
|
|
56
|
+
/**
|
|
57
|
+
* Half-angle of the ground patch a satellite can serve, in radians, measured from the Earth's centre.
|
|
58
|
+
*
|
|
59
|
+
* cos(θ + ε) = (R / (R + h)) · cos(ε)
|
|
60
|
+
*
|
|
61
|
+
* The minimum elevation matters as much as the altitude: a terminal near the horizon is looking
|
|
62
|
+
* through far more atmosphere and past far more rooftops, so constellations set a floor and give up
|
|
63
|
+
* the rest of the geometric footprint to get a link that works.
|
|
64
|
+
*/
|
|
65
|
+
declare function centralAngleRad(altitudeKm: number, minElevationDeg: number): number;
|
|
66
|
+
/** Radius of that patch measured along the ground, in km. */
|
|
67
|
+
declare const footprintRadiusKm: (altitudeKm: number, minElevationDeg: number) => number;
|
|
68
|
+
/** Area of the patch, in km², as a spherical cap rather than a flat disc. */
|
|
69
|
+
declare function footprintAreaKm2(altitudeKm: number, minElevationDeg: number): number;
|
|
70
|
+
declare const EARTH_AREA_KM2: number;
|
|
71
|
+
/**
|
|
72
|
+
* Satellites needed to see the whole planet at once, as a geometric floor.
|
|
73
|
+
*
|
|
74
|
+
* This is the number of caps required to cover a sphere, and it is a FLOOR rather than a fleet size.
|
|
75
|
+
* Real constellations fly several times more, because caps must overlap for a link to survive a
|
|
76
|
+
* satellite setting, because the orbits have to form a workable pattern, and above all because
|
|
77
|
+
* capacity is shared: one satellite over a city serves everyone under it at once. Starlink flies
|
|
78
|
+
* thousands where the geometry asks for a few hundred, and almost all of that difference is capacity
|
|
79
|
+
* rather than coverage. Saying so is the difference between a model and a claim.
|
|
80
|
+
*/
|
|
81
|
+
declare function satellitesForCoverage(altitudeKm: number, minElevationDeg: number): number;
|
|
82
|
+
/** How long one satellite stays in view of a fixed point, in minutes. Zero when it never sets. */
|
|
83
|
+
declare function passMinutes(altitudeKm: number, minElevationDeg: number): number;
|
|
84
|
+
declare const orbitById: (id: string) => Orbit;
|
|
85
|
+
//#endregion
|
|
86
|
+
export { C_KM_S, EARTH_AREA_KM2, EARTH_RADIUS_KM, MU_EARTH, ORBITS, Orbit, centralAngleRad, footprintAreaKm2, footprintRadiusKm, oneWayMs, orbitById, orbitalPeriodMin, passMinutes, roundTripMs, satellitesForCoverage };
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
import { SPEED_OF_LIGHT } from "../../core/constants.mjs";
|
|
2
|
+
|
|
3
|
+
//#region src/networking/models/satellite.ts
|
|
4
|
+
/**
|
|
5
|
+
* Satellite links: the one delay nobody can engineer away.
|
|
6
|
+
*
|
|
7
|
+
* Every other limit in this course yields to money. A weak room gets a second access point, a city
|
|
8
|
+
* gets more masts, a slow band gets refarmed. Distance does not yield to anything, because the signal
|
|
9
|
+
* travels at the speed of light and that is the end of the discussion.
|
|
10
|
+
*
|
|
11
|
+
* A geostationary satellite sits 35,786 km up. The signal has to climb that, come back down, and then
|
|
12
|
+
* do it again for the reply, so a round trip is roughly half a second before a single byte is
|
|
13
|
+
* processed. No better modem, no wider band and no amount of capital changes it. That is why
|
|
14
|
+
* satellite television, which is one-way and buffered, has always worked beautifully, and why a video
|
|
15
|
+
* call over the same link has always been unbearable.
|
|
16
|
+
*
|
|
17
|
+
* It is also the whole reason low orbit was worth the trouble. Flying at 550 km instead cuts the
|
|
18
|
+
* round trip by a factor of about sixty and brings interactive use back within reach. The price is
|
|
19
|
+
* paid twice over: a low satellite covers a tiny patch of ground so you need hundreds of them, and it
|
|
20
|
+
* crosses the sky in minutes, so the link must be handed from one satellite to the next exactly as a
|
|
21
|
+
* moving phone is handed between masts. Chapters 2 and 3 are the bill for this chapter's fix.
|
|
22
|
+
*/
|
|
23
|
+
/** Speed of light in vacuum, km/s. Every number in this file is a consequence of it. */
|
|
24
|
+
const C_KM_S = SPEED_OF_LIGHT / 1e3;
|
|
25
|
+
/** Mean radius of the Earth, km. */
|
|
26
|
+
const EARTH_RADIUS_KM = 6371;
|
|
27
|
+
/** Standard gravitational parameter of the Earth, km³/s². */
|
|
28
|
+
const MU_EARTH = 398600.4418;
|
|
29
|
+
const ORBITS = [
|
|
30
|
+
{
|
|
31
|
+
id: "leo",
|
|
32
|
+
label: "Low orbit",
|
|
33
|
+
altitudeKm: 550,
|
|
34
|
+
minElevationDeg: 25,
|
|
35
|
+
use: "Starlink and similar constellations",
|
|
36
|
+
note: "Low enough that the round trip stops being the problem. It sees so little ground that hundreds are needed, and it crosses the sky in minutes, so the link is handed on constantly."
|
|
37
|
+
},
|
|
38
|
+
{
|
|
39
|
+
id: "meo",
|
|
40
|
+
label: "Medium orbit",
|
|
41
|
+
altitudeKm: 8063,
|
|
42
|
+
minElevationDeg: 10,
|
|
43
|
+
use: "O3b, and the navigation constellations a little higher",
|
|
44
|
+
note: "A working compromise. Far fewer satellites than low orbit and a round trip a business can live with, though still too long for anything reflex-driven."
|
|
45
|
+
},
|
|
46
|
+
{
|
|
47
|
+
id: "geo",
|
|
48
|
+
label: "Geostationary",
|
|
49
|
+
altitudeKm: 35786,
|
|
50
|
+
minElevationDeg: 10,
|
|
51
|
+
use: "Television broadcast, and the satellite internet that came before Starlink",
|
|
52
|
+
note: "It orbits once per day, so it hangs over the same spot and a dish can be aimed once and bolted down. Three of them see almost the whole planet. The half-second is the price of all of that."
|
|
53
|
+
}
|
|
54
|
+
];
|
|
55
|
+
/**
|
|
56
|
+
* Round trip in ms for a request and its reply, from propagation alone.
|
|
57
|
+
*
|
|
58
|
+
* Four times the altitude: up, down, up and down again. Deliberately propagation only, with nothing
|
|
59
|
+
* added for the modem, the gateway or the server. A learner should see the number that cannot be
|
|
60
|
+
* argued with first, and meet the extra overheads afterwards as things engineers can actually attack.
|
|
61
|
+
*/
|
|
62
|
+
const roundTripMs = (altitudeKm) => 4 * altitudeKm / C_KM_S * 1e3;
|
|
63
|
+
/** One hop, ground to satellite to ground, in ms. What a one-way broadcast costs. */
|
|
64
|
+
const oneWayMs = (altitudeKm) => 2 * altitudeKm / C_KM_S * 1e3;
|
|
65
|
+
/**
|
|
66
|
+
* Orbital period in minutes, from Kepler's third law.
|
|
67
|
+
*
|
|
68
|
+
* Worth computing rather than quoting, because it explains the two things about geostationary orbit
|
|
69
|
+
* that look like coincidences. It sits at exactly the altitude where one orbit takes a day, which is
|
|
70
|
+
* why it appears motionless, which is why a dish never has to move. There is only one such altitude,
|
|
71
|
+
* which is why that orbit is crowded and regulated.
|
|
72
|
+
*/
|
|
73
|
+
function orbitalPeriodMin(altitudeKm) {
|
|
74
|
+
const a = EARTH_RADIUS_KM + altitudeKm;
|
|
75
|
+
return 2 * Math.PI * Math.sqrt(a * a * a / MU_EARTH) / 60;
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Half-angle of the ground patch a satellite can serve, in radians, measured from the Earth's centre.
|
|
79
|
+
*
|
|
80
|
+
* cos(θ + ε) = (R / (R + h)) · cos(ε)
|
|
81
|
+
*
|
|
82
|
+
* The minimum elevation matters as much as the altitude: a terminal near the horizon is looking
|
|
83
|
+
* through far more atmosphere and past far more rooftops, so constellations set a floor and give up
|
|
84
|
+
* the rest of the geometric footprint to get a link that works.
|
|
85
|
+
*/
|
|
86
|
+
function centralAngleRad(altitudeKm, minElevationDeg) {
|
|
87
|
+
const epsilon = minElevationDeg * Math.PI / 180;
|
|
88
|
+
const ratio = EARTH_RADIUS_KM / (EARTH_RADIUS_KM + altitudeKm) * Math.cos(epsilon);
|
|
89
|
+
return Math.acos(Math.min(1, Math.max(-1, ratio))) - epsilon;
|
|
90
|
+
}
|
|
91
|
+
/** Radius of that patch measured along the ground, in km. */
|
|
92
|
+
const footprintRadiusKm = (altitudeKm, minElevationDeg) => EARTH_RADIUS_KM * centralAngleRad(altitudeKm, minElevationDeg);
|
|
93
|
+
/** Area of the patch, in km², as a spherical cap rather than a flat disc. */
|
|
94
|
+
function footprintAreaKm2(altitudeKm, minElevationDeg) {
|
|
95
|
+
const theta = centralAngleRad(altitudeKm, minElevationDeg);
|
|
96
|
+
return 2 * Math.PI * EARTH_RADIUS_KM * EARTH_RADIUS_KM * (1 - Math.cos(theta));
|
|
97
|
+
}
|
|
98
|
+
const EARTH_AREA_KM2 = 4 * Math.PI * EARTH_RADIUS_KM * EARTH_RADIUS_KM;
|
|
99
|
+
/**
|
|
100
|
+
* Satellites needed to see the whole planet at once, as a geometric floor.
|
|
101
|
+
*
|
|
102
|
+
* This is the number of caps required to cover a sphere, and it is a FLOOR rather than a fleet size.
|
|
103
|
+
* Real constellations fly several times more, because caps must overlap for a link to survive a
|
|
104
|
+
* satellite setting, because the orbits have to form a workable pattern, and above all because
|
|
105
|
+
* capacity is shared: one satellite over a city serves everyone under it at once. Starlink flies
|
|
106
|
+
* thousands where the geometry asks for a few hundred, and almost all of that difference is capacity
|
|
107
|
+
* rather than coverage. Saying so is the difference between a model and a claim.
|
|
108
|
+
*/
|
|
109
|
+
function satellitesForCoverage(altitudeKm, minElevationDeg) {
|
|
110
|
+
return Math.max(1, Math.ceil(EARTH_AREA_KM2 / footprintAreaKm2(altitudeKm, minElevationDeg)));
|
|
111
|
+
}
|
|
112
|
+
/** How long one satellite stays in view of a fixed point, in minutes. Zero when it never sets. */
|
|
113
|
+
function passMinutes(altitudeKm, minElevationDeg) {
|
|
114
|
+
const period = orbitalPeriodMin(altitudeKm);
|
|
115
|
+
if (period >= 1400) return Infinity;
|
|
116
|
+
return period * (2 * centralAngleRad(altitudeKm, minElevationDeg)) / (2 * Math.PI);
|
|
117
|
+
}
|
|
118
|
+
const orbitById = (id) => ORBITS.find((orbit) => orbit.id === id) ?? ORBITS[0];
|
|
119
|
+
|
|
120
|
+
//#endregion
|
|
121
|
+
export { C_KM_S, EARTH_AREA_KM2, EARTH_RADIUS_KM, MU_EARTH, ORBITS, centralAngleRad, footprintAreaKm2, footprintRadiusKm, oneWayMs, orbitById, orbitalPeriodMin, passMinutes, roundTripMs, satellitesForCoverage };
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
//#region src/networking/models/spectrum.d.ts
|
|
2
|
+
/**
|
|
3
|
+
* The invisible spectrum: why a remote control needs to be pointed and Wi-Fi does not.
|
|
4
|
+
*
|
|
5
|
+
* Radio, microwave, infrared and light are one thing, and are almost always taught as four. A
|
|
6
|
+
* student learns that Wi-Fi is "radio waves", that a remote uses "infrared", that 5G is "faster",
|
|
7
|
+
* and nothing connects those three facts, so none of them predicts anything. They are the same
|
|
8
|
+
* phenomenon at different frequencies, and almost every practical difference between them follows
|
|
9
|
+
* from one number.
|
|
10
|
+
*
|
|
11
|
+
* The number is the wavelength, and the reason it decides everything is SIZE. A wave interacts with
|
|
12
|
+
* an object according to how the object compares to its own wavelength. An FM broadcast is three
|
|
13
|
+
* metres long and treats a person as though they were not there. Wi-Fi is twelve centimetres and
|
|
14
|
+
* treats a brick wall as an obstacle it loses some energy to. A 5G millimetre wave is a centimetre
|
|
15
|
+
* and is stopped by a hand, a leaf, or coated window glass. Infrared is a thousandth of a
|
|
16
|
+
* millimetre and is stopped by anything at all, which is why the remote has to see the television.
|
|
17
|
+
*
|
|
18
|
+
* So this table exists to be sorted and compared rather than recited. The derived quantities are
|
|
19
|
+
* computed from the frequency instead of stored, because the whole claim of the lesson is that they
|
|
20
|
+
* FOLLOW from it: change the frequency and the wavelength, the antenna and the ability to cross a
|
|
21
|
+
* wall all move together, and a learner who has watched them move together owns the relationship.
|
|
22
|
+
*
|
|
23
|
+
* It also settles the single most common misconception about Wi-Fi in one line. A microwave oven
|
|
24
|
+
* runs at 2.45 GHz and a Wi-Fi router runs at 2.437 GHz. They are the same band. The oven is not
|
|
25
|
+
* interfering with the network by coincidence or by poor design: it is shouting on the channel.
|
|
26
|
+
*/
|
|
27
|
+
declare const C = 299792458;
|
|
28
|
+
/** How well a band crosses ordinary building materials. */
|
|
29
|
+
type Penetration = "through-anything" | "through-walls" | "through-one-wall" | "blocked" | "line-of-sight";
|
|
30
|
+
interface SpectrumBand {
|
|
31
|
+
id: string;
|
|
32
|
+
label: string;
|
|
33
|
+
/** Centre frequency in hertz. Everything else on this record is derived from it. */
|
|
34
|
+
hz: number;
|
|
35
|
+
/** What this band is used for, in the words a learner would meet it by. */
|
|
36
|
+
use: string;
|
|
37
|
+
penetration: Penetration;
|
|
38
|
+
/** A familiar object of roughly the same size as one wavelength. */
|
|
39
|
+
compare: string;
|
|
40
|
+
/** That object's real size in metres, so the figure can draw the two lengths to one scale. */
|
|
41
|
+
compareM: number;
|
|
42
|
+
note: string;
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Real centre frequencies, in the order a learner should meet them: longest wave first, because the
|
|
46
|
+
* story is what happens as the wave gets shorter.
|
|
47
|
+
*/
|
|
48
|
+
declare const SPECTRUM: SpectrumBand[];
|
|
49
|
+
/** Wavelength in metres. Everything visual about a band comes from this one division. */
|
|
50
|
+
declare const wavelengthM: (hz: number) => number;
|
|
51
|
+
/**
|
|
52
|
+
* Quarter-wave antenna length in metres, the classic first-order rule.
|
|
53
|
+
*
|
|
54
|
+
* It is worth computing rather than asserting, because it explains hardware a learner has already
|
|
55
|
+
* seen and never questioned: the metre-long whip on an old car radio, the few centimetres inside a
|
|
56
|
+
* phone, and the fact that a 5G millimetre-wave antenna is small enough to put dozens on one chip.
|
|
57
|
+
*/
|
|
58
|
+
declare const quarterWaveM: (hz: number) => number;
|
|
59
|
+
/** A length in the largest unit that keeps it readable, which is how a person would say it. */
|
|
60
|
+
declare function humanLength(metres: number): string;
|
|
61
|
+
/** A frequency in the unit it is normally quoted in. */
|
|
62
|
+
declare function humanFrequency(hz: number): string;
|
|
63
|
+
interface PenetrationSpec {
|
|
64
|
+
id: Penetration;
|
|
65
|
+
label: string;
|
|
66
|
+
/** What actually stops it, said as a thing rather than as a category. */
|
|
67
|
+
stoppedBy: string;
|
|
68
|
+
}
|
|
69
|
+
declare const PENETRATION: Record<Penetration, PenetrationSpec>;
|
|
70
|
+
/**
|
|
71
|
+
* Position on a logarithmic axis from 0 (left) to 1 (right).
|
|
72
|
+
*
|
|
73
|
+
* The axis has to be logarithmic because the table spans nine orders of magnitude: on a linear
|
|
74
|
+
* scale every radio band would pile into the first pixel and the lesson would be invisible. Worth
|
|
75
|
+
* saying to a learner rather than hiding, since "the axis multiplies instead of adding" is itself
|
|
76
|
+
* one of the more useful things this figure can teach.
|
|
77
|
+
*/
|
|
78
|
+
declare function logPosition(hz: number, fromHz?: number, toHz?: number): number;
|
|
79
|
+
/** The decade ticks an axis should carry between two frequencies. */
|
|
80
|
+
declare function decades(fromHz?: number, toHz?: number): number[];
|
|
81
|
+
declare const bandById: (id: string) => SpectrumBand;
|
|
82
|
+
//#endregion
|
|
83
|
+
export { C, PENETRATION, Penetration, PenetrationSpec, SPECTRUM, SpectrumBand, bandById, decades, humanFrequency, humanLength, logPosition, quarterWaveM, wavelengthM };
|