@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.
Files changed (431) hide show
  1. package/dist/_virtual/_rolldown/runtime.mjs +18 -0
  2. package/dist/atomic/aufbau.d.mts +144 -0
  3. package/dist/atomic/aufbau.mjs +384 -0
  4. package/dist/atomic/elements.d.mts +67 -0
  5. package/dist/atomic/elements.mjs +785 -0
  6. package/dist/atomic/emission.d.mts +112 -0
  7. package/dist/atomic/emission.mjs +179 -0
  8. package/dist/atomic/index.d.mts +8 -0
  9. package/dist/atomic/index.mjs +9 -0
  10. package/dist/atomic/periodic.d.mts +82 -0
  11. package/dist/atomic/periodic.mjs +231 -0
  12. package/dist/atomic/properties.d.mts +100 -0
  13. package/dist/atomic/properties.mjs +574 -0
  14. package/dist/atomic/shells.d.mts +137 -0
  15. package/dist/atomic/shells.mjs +170 -0
  16. package/dist/atomic/trends.d.mts +148 -0
  17. package/dist/atomic/trends.mjs +225 -0
  18. package/dist/chem/chromatography.d.mts +66 -0
  19. package/dist/chem/chromatography.mjs +63 -0
  20. package/dist/chem/complex.d.mts +114 -0
  21. package/dist/chem/complex.mjs +234 -0
  22. package/dist/chem/cycle.d.mts +75 -0
  23. package/dist/chem/cycle.mjs +145 -0
  24. package/dist/chem/equation.d.mts +86 -0
  25. package/dist/chem/equation.mjs +168 -0
  26. package/dist/chem/formula.d.mts +90 -0
  27. package/dist/chem/formula.mjs +201 -0
  28. package/dist/chem/functional-groups.d.mts +31 -0
  29. package/dist/chem/functional-groups.mjs +187 -0
  30. package/dist/chem/hazard.d.mts +94 -0
  31. package/dist/chem/hazard.mjs +329 -0
  32. package/dist/chem/index.d.mts +34 -33
  33. package/dist/chem/index.mjs +34 -28
  34. package/dist/chem/ionic.d.mts +98 -0
  35. package/dist/chem/ionic.mjs +156 -0
  36. package/dist/chem/layout.d.mts +46 -0
  37. package/dist/chem/layout.mjs +342 -0
  38. package/dist/chem/lewis.d.mts +79 -0
  39. package/dist/chem/lewis.mjs +163 -0
  40. package/dist/chem/molecular-orbital.d.mts +114 -0
  41. package/dist/chem/molecular-orbital.mjs +201 -0
  42. package/dist/chem/molecule.d.mts +154 -0
  43. package/dist/chem/molecule.mjs +282 -0
  44. package/dist/chem/nmr.d.mts +153 -0
  45. package/dist/chem/nmr.mjs +165 -0
  46. package/dist/chem/polymer.d.mts +65 -0
  47. package/dist/chem/polymer.mjs +179 -0
  48. package/dist/chem/redox.d.mts +138 -0
  49. package/dist/chem/redox.mjs +328 -0
  50. package/dist/chem/relations.d.mts +183 -0
  51. package/dist/chem/relations.mjs +299 -0
  52. package/dist/chem/skeleton.d.mts +51 -0
  53. package/dist/chem/skeleton.mjs +186 -0
  54. package/dist/chem/solution.d.mts +116 -0
  55. package/dist/chem/solution.mjs +186 -0
  56. package/dist/chem/species.d.mts +47 -0
  57. package/dist/chem/species.mjs +128 -0
  58. package/dist/chem/stereo.d.mts +108 -0
  59. package/dist/chem/stereo.mjs +286 -0
  60. package/dist/chem/stoichiometry.d.mts +95 -0
  61. package/dist/chem/stoichiometry.mjs +145 -0
  62. package/dist/chem/synthesis.d.mts +113 -0
  63. package/dist/chem/synthesis.mjs +281 -0
  64. package/dist/chem/vsepr.d.mts +80 -0
  65. package/dist/chem/vsepr.mjs +247 -0
  66. package/dist/circuit/ac.d.mts +163 -0
  67. package/dist/circuit/ac.mjs +452 -0
  68. package/dist/circuit/dc.d.mts +92 -0
  69. package/dist/circuit/dc.mjs +333 -0
  70. package/dist/circuit/index.d.mts +5 -92
  71. package/dist/circuit/index.mjs +5 -332
  72. package/dist/circuit/network.d.mts +99 -0
  73. package/dist/circuit/network.mjs +440 -0
  74. package/dist/circuit/topology.d.mts +102 -0
  75. package/dist/circuit/topology.mjs +143 -0
  76. package/dist/colour/absorption.d.mts +79 -0
  77. package/dist/colour/absorption.mjs +137 -0
  78. package/dist/colour/index.d.mts +6 -0
  79. package/dist/colour/index.mjs +7 -0
  80. package/dist/colour/name.d.mts +14 -0
  81. package/dist/colour/name.mjs +76 -0
  82. package/dist/colour/observer.d.mts +31 -0
  83. package/dist/colour/observer.mjs +46 -0
  84. package/dist/colour/spectrum.d.mts +61 -0
  85. package/dist/colour/spectrum.mjs +108 -0
  86. package/dist/colour/srgb.d.mts +49 -0
  87. package/dist/colour/srgb.mjs +108 -0
  88. package/dist/core/constants.d.mts +138 -0
  89. package/dist/core/constants.mjs +139 -0
  90. package/dist/core/index.d.mts +3 -1
  91. package/dist/core/index.mjs +3 -1
  92. package/dist/core/vec3.d.mts +94 -0
  93. package/dist/core/vec3.mjs +123 -0
  94. package/dist/core/worked.d.mts +35 -0
  95. package/dist/core/worked.mjs +44 -0
  96. package/dist/electro/cell.d.mts +102 -0
  97. package/dist/electro/cell.mjs +170 -0
  98. package/dist/electro/conductivity.d.mts +157 -0
  99. package/dist/electro/conductivity.mjs +156 -0
  100. package/dist/electro/couples.d.mts +114 -0
  101. package/dist/electro/couples.mjs +334 -0
  102. package/dist/electro/electrolysis.d.mts +96 -0
  103. package/dist/electro/electrolysis.mjs +274 -0
  104. package/dist/electro/faraday.d.mts +150 -0
  105. package/dist/electro/faraday.mjs +118 -0
  106. package/dist/electro/index.d.mts +6 -0
  107. package/dist/electro/index.mjs +7 -0
  108. package/dist/finance/accounting/adjustments.d.mts +17 -0
  109. package/dist/finance/accounting/adjustments.mjs +202 -0
  110. package/dist/finance/accounting/analysis.d.mts +8 -0
  111. package/dist/finance/accounting/analysis.mjs +205 -0
  112. package/dist/finance/accounting/clubs.d.mts +21 -0
  113. package/dist/finance/accounting/clubs.mjs +217 -0
  114. package/dist/finance/accounting/company-statements.d.mts +7 -0
  115. package/dist/finance/accounting/company-statements.mjs +150 -0
  116. package/dist/finance/accounting/harness.d.mts +7 -0
  117. package/dist/finance/accounting/harness.mjs +45 -0
  118. package/dist/finance/accounting/index.d.mts +18 -0
  119. package/dist/finance/accounting/index.mjs +18 -0
  120. package/dist/finance/accounting/journalize.d.mts +16 -0
  121. package/dist/finance/accounting/journalize.mjs +128 -0
  122. package/dist/finance/accounting/manufacturing.d.mts +8 -0
  123. package/dist/finance/accounting/manufacturing.mjs +236 -0
  124. package/dist/finance/accounting/partnership.d.mts +7 -0
  125. package/dist/finance/accounting/partnership.mjs +152 -0
  126. package/dist/finance/accounting/period-case.d.mts +6 -0
  127. package/dist/finance/accounting/period-case.mjs +71 -0
  128. package/dist/finance/accounting/post.d.mts +9 -0
  129. package/dist/finance/accounting/post.mjs +84 -0
  130. package/dist/finance/accounting/precision.d.mts +9 -0
  131. package/dist/finance/accounting/precision.mjs +15 -0
  132. package/dist/finance/accounting/rules.d.mts +21 -0
  133. package/dist/finance/accounting/rules.mjs +37 -0
  134. package/dist/finance/accounting/solve.d.mts +28 -0
  135. package/dist/finance/accounting/solve.mjs +92 -0
  136. package/dist/finance/accounting/statements.d.mts +7 -0
  137. package/dist/finance/accounting/statements.mjs +142 -0
  138. package/dist/finance/accounting/types.d.mts +649 -0
  139. package/dist/finance/accounting/validate.d.mts +7 -0
  140. package/dist/finance/accounting/validate.mjs +67 -0
  141. package/dist/finance/accounting/verification.d.mts +24 -0
  142. package/dist/finance/accounting/verification.mjs +386 -0
  143. package/dist/finance/bizsim.d.mts +21 -39
  144. package/dist/finance/bizsim.mjs +276 -97
  145. package/dist/finance/index.d.mts +20 -43
  146. package/dist/finance/index.mjs +19 -77
  147. package/dist/finance/investment-math.d.mts +7 -0
  148. package/dist/finance/investment-math.mjs +18 -0
  149. package/dist/finance/management-accounting/budgeting.d.mts +7 -0
  150. package/dist/finance/management-accounting/budgeting.mjs +189 -0
  151. package/dist/finance/management-accounting/cash-budget.d.mts +7 -0
  152. package/dist/finance/management-accounting/cash-budget.mjs +154 -0
  153. package/dist/finance/management-accounting/costing.d.mts +8 -0
  154. package/dist/finance/management-accounting/costing.mjs +175 -0
  155. package/dist/finance/management-accounting/decisions.d.mts +8 -0
  156. package/dist/finance/management-accounting/decisions.mjs +164 -0
  157. package/dist/finance/management-accounting/index.d.mts +13 -0
  158. package/dist/finance/management-accounting/index.mjs +13 -0
  159. package/dist/finance/management-accounting/integrated-budget.d.mts +8 -0
  160. package/dist/finance/management-accounting/integrated-budget.mjs +67 -0
  161. package/dist/finance/management-accounting/inventory-costing.d.mts +7 -0
  162. package/dist/finance/management-accounting/inventory-costing.mjs +173 -0
  163. package/dist/finance/management-accounting/investment-appraisal.d.mts +7 -0
  164. package/dist/finance/management-accounting/investment-appraisal.mjs +148 -0
  165. package/dist/finance/management-accounting/management-case.d.mts +8 -0
  166. package/dist/finance/management-accounting/management-case.mjs +91 -0
  167. package/dist/finance/management-accounting/master-budget.d.mts +7 -0
  168. package/dist/finance/management-accounting/master-budget.mjs +137 -0
  169. package/dist/finance/management-accounting/production-costing.d.mts +8 -0
  170. package/dist/finance/management-accounting/production-costing.mjs +214 -0
  171. package/dist/finance/management-accounting/types.d.mts +644 -0
  172. package/dist/finance/management-accounting/variances.d.mts +7 -0
  173. package/dist/finance/management-accounting/variances.mjs +150 -0
  174. package/dist/index.d.mts +6 -6
  175. package/dist/index.mjs +1 -1
  176. package/dist/math/analysis.d.mts +61 -0
  177. package/dist/math/analysis.mjs +187 -0
  178. package/dist/math/answer-check.d.mts +50 -0
  179. package/dist/math/answer-check.mjs +106 -0
  180. package/dist/math/calculus.d.mts +4 -9
  181. package/dist/math/calculus.mjs +216 -7
  182. package/dist/math/complex.d.mts +93 -0
  183. package/dist/math/complex.mjs +239 -0
  184. package/dist/math/expr.d.mts +23 -0
  185. package/dist/math/expr.mjs +36 -0
  186. package/dist/math/index.d.mts +8 -22
  187. package/dist/math/index.mjs +8 -37
  188. package/dist/math/latex.mjs +2 -1
  189. package/dist/math/parse.mjs +1 -1
  190. package/dist/math/poly.d.mts +55 -0
  191. package/dist/math/poly.mjs +273 -0
  192. package/dist/math/rearrange.d.mts +14 -0
  193. package/dist/math/rearrange.mjs +125 -0
  194. package/dist/math/solve.d.mts +21 -0
  195. package/dist/math/solve.mjs +75 -0
  196. package/dist/networking/addressing.d.mts +26 -0
  197. package/dist/networking/addressing.mjs +33 -0
  198. package/dist/networking/cloud/access.d.mts +36 -0
  199. package/dist/networking/cloud/access.mjs +95 -0
  200. package/dist/networking/cloud/containers.d.mts +43 -0
  201. package/dist/networking/cloud/containers.mjs +54 -0
  202. package/dist/networking/cloud/edge.d.mts +17 -0
  203. package/dist/networking/cloud/edge.mjs +31 -0
  204. package/dist/networking/cloud/failure-domains.d.mts +19 -0
  205. package/dist/networking/cloud/failure-domains.mjs +22 -0
  206. package/dist/networking/cloud/geo-routing.d.mts +22 -0
  207. package/dist/networking/cloud/geo-routing.mjs +64 -0
  208. package/dist/networking/cloud/index.d.mts +18 -0
  209. package/dist/networking/cloud/index.mjs +19 -0
  210. package/dist/networking/cloud/inference-reliability.d.mts +30 -0
  211. package/dist/networking/cloud/inference-reliability.mjs +76 -0
  212. package/dist/networking/cloud/inference.d.mts +118 -0
  213. package/dist/networking/cloud/inference.mjs +179 -0
  214. package/dist/networking/cloud/infrastructure.d.mts +45 -0
  215. package/dist/networking/cloud/infrastructure.mjs +96 -0
  216. package/dist/networking/cloud/observability.d.mts +24 -0
  217. package/dist/networking/cloud/observability.mjs +34 -0
  218. package/dist/networking/cloud/orchestration.d.mts +32 -0
  219. package/dist/networking/cloud/orchestration.mjs +38 -0
  220. package/dist/networking/cloud/recovery.d.mts +21 -0
  221. package/dist/networking/cloud/recovery.mjs +27 -0
  222. package/dist/networking/cloud/releases.d.mts +42 -0
  223. package/dist/networking/cloud/releases.mjs +135 -0
  224. package/dist/networking/cloud/scaling.d.mts +25 -0
  225. package/dist/networking/cloud/scaling.mjs +65 -0
  226. package/dist/networking/cloud/secrets.d.mts +39 -0
  227. package/dist/networking/cloud/secrets.mjs +68 -0
  228. package/dist/networking/cloud/server-deployment.d.mts +29 -0
  229. package/dist/networking/cloud/server-deployment.mjs +72 -0
  230. package/dist/networking/cloud/storage.d.mts +16 -0
  231. package/dist/networking/cloud/storage.mjs +58 -0
  232. package/dist/networking/cloud/vpc.d.mts +18 -0
  233. package/dist/networking/cloud/vpc.mjs +100 -0
  234. package/dist/networking/delivery.d.mts +34 -0
  235. package/dist/networking/delivery.mjs +52 -0
  236. package/dist/networking/index.d.mts +47 -0
  237. package/dist/networking/index.mjs +47 -0
  238. package/dist/networking/ipv6.d.mts +28 -0
  239. package/dist/networking/ipv6.mjs +17 -0
  240. package/dist/networking/journeys.d.mts +83 -0
  241. package/dist/networking/journeys.mjs +161 -0
  242. package/dist/networking/models/airtime.d.mts +87 -0
  243. package/dist/networking/models/airtime.mjs +130 -0
  244. package/dist/networking/models/cellular.d.mts +157 -0
  245. package/dist/networking/models/cellular.mjs +252 -0
  246. package/dist/networking/models/encapsulation.d.mts +98 -0
  247. package/dist/networking/models/encapsulation.mjs +132 -0
  248. package/dist/networking/models/handover.d.mts +116 -0
  249. package/dist/networking/models/handover.mjs +209 -0
  250. package/dist/networking/models/handshake.d.mts +90 -0
  251. package/dist/networking/models/handshake.mjs +122 -0
  252. package/dist/networking/models/index.d.mts +14 -0
  253. package/dist/networking/models/index.mjs +15 -0
  254. package/dist/networking/models/media.d.mts +82 -0
  255. package/dist/networking/models/media.mjs +188 -0
  256. package/dist/networking/models/satellite.d.mts +86 -0
  257. package/dist/networking/models/satellite.mjs +121 -0
  258. package/dist/networking/models/spectrum.d.mts +83 -0
  259. package/dist/networking/models/spectrum.mjs +235 -0
  260. package/dist/networking/models/switch.d.mts +80 -0
  261. package/dist/networking/models/switch.mjs +155 -0
  262. package/dist/networking/models/vlan.d.mts +62 -0
  263. package/dist/networking/models/vlan.mjs +100 -0
  264. package/dist/networking/models/vpn.d.mts +66 -0
  265. package/dist/networking/models/vpn.mjs +125 -0
  266. package/dist/networking/models/wifi-privacy.d.mts +82 -0
  267. package/dist/networking/models/wifi-privacy.mjs +130 -0
  268. package/dist/networking/models/wifi.d.mts +240 -0
  269. package/dist/networking/models/wifi.mjs +562 -0
  270. package/dist/networking/nat-traversal.d.mts +24 -0
  271. package/dist/networking/nat-traversal.mjs +38 -0
  272. package/dist/networking/protocols.d.mts +17 -0
  273. package/dist/networking/protocols.mjs +57 -0
  274. package/dist/networking/queue.d.mts +12 -0
  275. package/dist/networking/queue.mjs +18 -0
  276. package/dist/networking/route-learning.d.mts +23 -0
  277. package/dist/networking/route-learning.mjs +43 -0
  278. package/dist/networking/routing.d.mts +11 -0
  279. package/dist/networking/routing.mjs +25 -0
  280. package/dist/networking/signals.d.mts +26 -0
  281. package/dist/networking/signals.mjs +35 -0
  282. package/dist/networking/subnet.d.mts +49 -0
  283. package/dist/networking/subnet.mjs +89 -0
  284. package/dist/networking/tcp-reliability.d.mts +24 -0
  285. package/dist/networking/tcp-reliability.mjs +38 -0
  286. package/dist/networking/topology/contract.d.mts +123 -0
  287. package/dist/networking/topology/index.d.mts +4 -0
  288. package/dist/networking/topology/index.mjs +4 -0
  289. package/dist/networking/topology/presets.d.mts +7 -0
  290. package/dist/networking/topology/presets.mjs +302 -0
  291. package/dist/networking/topology/simulation.d.mts +8 -0
  292. package/dist/networking/topology/simulation.mjs +179 -0
  293. package/dist/networking/wireless.d.mts +11 -0
  294. package/dist/networking/wireless.mjs +17 -0
  295. package/dist/optics/imaging.d.mts +218 -0
  296. package/dist/optics/imaging.mjs +276 -0
  297. package/dist/optics/index.d.mts +7 -0
  298. package/dist/optics/index.mjs +8 -0
  299. package/dist/optics/laws.d.mts +70 -0
  300. package/dist/optics/laws.mjs +195 -0
  301. package/dist/optics/prism.d.mts +148 -0
  302. package/dist/optics/prism.mjs +197 -0
  303. package/dist/optics/refraction.d.mts +201 -0
  304. package/dist/optics/refraction.mjs +270 -0
  305. package/dist/optics/wave-optics.d.mts +171 -0
  306. package/dist/optics/wave-optics.mjs +259 -0
  307. package/dist/physics/ac/index.d.mts +183 -0
  308. package/dist/physics/ac/index.mjs +203 -0
  309. package/dist/physics/dynamics/forces.d.mts +98 -0
  310. package/dist/physics/dynamics/forces.mjs +153 -0
  311. package/dist/physics/dynamics/friction.d.mts +76 -0
  312. package/dist/physics/dynamics/friction.mjs +119 -0
  313. package/dist/physics/dynamics/system.d.mts +68 -0
  314. package/dist/physics/dynamics/system.mjs +125 -0
  315. package/dist/physics/electrostatics/index.d.mts +169 -0
  316. package/dist/physics/electrostatics/index.mjs +249 -0
  317. package/dist/physics/energy/centre-of-mass.d.mts +115 -0
  318. package/dist/physics/energy/centre-of-mass.mjs +180 -0
  319. package/dist/physics/energy/conservation.d.mts +81 -0
  320. package/dist/physics/energy/conservation.mjs +129 -0
  321. package/dist/physics/energy/power.d.mts +90 -0
  322. package/dist/physics/energy/power.mjs +167 -0
  323. package/dist/physics/energy/spring.d.mts +73 -0
  324. package/dist/physics/energy/spring.mjs +129 -0
  325. package/dist/physics/energy/store.d.mts +63 -0
  326. package/dist/physics/energy/store.mjs +108 -0
  327. package/dist/physics/energy/theorem.d.mts +65 -0
  328. package/dist/physics/energy/theorem.mjs +113 -0
  329. package/dist/physics/energy/work.d.mts +114 -0
  330. package/dist/physics/energy/work.mjs +219 -0
  331. package/dist/physics/gravitation/body.d.mts +85 -0
  332. package/dist/physics/gravitation/body.mjs +168 -0
  333. package/dist/physics/gravitation/kepler.d.mts +127 -0
  334. package/dist/physics/gravitation/kepler.mjs +216 -0
  335. package/dist/physics/gravitation/law.d.mts +117 -0
  336. package/dist/physics/gravitation/law.mjs +175 -0
  337. package/dist/physics/gravitation/orbit.d.mts +119 -0
  338. package/dist/physics/gravitation/orbit.mjs +202 -0
  339. package/dist/physics/gravitation/potential.d.mts +114 -0
  340. package/dist/physics/gravitation/potential.mjs +202 -0
  341. package/dist/physics/gravitation/variation.d.mts +97 -0
  342. package/dist/physics/gravitation/variation.mjs +175 -0
  343. package/dist/physics/index.d.mts +35 -0
  344. package/dist/physics/index.mjs +36 -0
  345. package/dist/physics/integral-sweep.d.mts +63 -0
  346. package/dist/physics/integral-sweep.mjs +126 -0
  347. package/dist/physics/kinematics/equations.d.mts +47 -0
  348. package/dist/physics/kinematics/equations.mjs +126 -0
  349. package/dist/physics/kinematics/free-fall.d.mts +53 -0
  350. package/dist/physics/kinematics/free-fall.mjs +71 -0
  351. package/dist/physics/kinematics/given.d.mts +16 -0
  352. package/dist/physics/kinematics/given.mjs +55 -0
  353. package/dist/physics/kinematics/roots.d.mts +41 -0
  354. package/dist/physics/kinematics/roots.mjs +72 -0
  355. package/dist/physics/kinematics/solve.d.mts +52 -0
  356. package/dist/physics/kinematics/solve.mjs +172 -0
  357. package/dist/physics/magnetism/biot-savart.d.mts +161 -0
  358. package/dist/physics/magnetism/biot-savart.mjs +353 -0
  359. package/dist/physics/magnetism/flux.d.mts +94 -0
  360. package/dist/physics/magnetism/flux.mjs +313 -0
  361. package/dist/physics/magnetism/geomagnetism.d.mts +151 -0
  362. package/dist/physics/magnetism/geomagnetism.mjs +184 -0
  363. package/dist/physics/magnetism/index.d.mts +12 -0
  364. package/dist/physics/magnetism/index.mjs +74 -0
  365. package/dist/physics/magnetism/lorentz.d.mts +28 -0
  366. package/dist/physics/magnetism/lorentz.mjs +88 -0
  367. package/dist/physics/magnetism/magnetic-force.d.mts +102 -0
  368. package/dist/physics/magnetism/magnetic-force.mjs +169 -0
  369. package/dist/physics/momentum/collide.d.mts +77 -0
  370. package/dist/physics/momentum/collide.mjs +115 -0
  371. package/dist/physics/momentum/impulse.d.mts +89 -0
  372. package/dist/physics/momentum/impulse.mjs +159 -0
  373. package/dist/physics/momentum/planar.d.mts +60 -0
  374. package/dist/physics/momentum/planar.mjs +110 -0
  375. package/dist/physics/projectile.d.mts +107 -0
  376. package/dist/physics/projectile.mjs +185 -0
  377. package/dist/physics/rotation/angular.d.mts +85 -0
  378. package/dist/physics/rotation/angular.mjs +130 -0
  379. package/dist/physics/rotation/circular.d.mts +79 -0
  380. package/dist/physics/rotation/circular.mjs +131 -0
  381. package/dist/physics/rotation/inertia.d.mts +164 -0
  382. package/dist/physics/rotation/inertia.mjs +332 -0
  383. package/dist/physics/rotation/torque.d.mts +65 -0
  384. package/dist/physics/rotation/torque.mjs +134 -0
  385. package/dist/physics/vectors.d.mts +64 -0
  386. package/dist/physics/vectors.mjs +114 -0
  387. package/dist/quantity/index.d.mts +119 -0
  388. package/dist/quantity/index.mjs +417 -0
  389. package/dist/relation/derive.d.mts +74 -0
  390. package/dist/relation/derive.mjs +73 -0
  391. package/dist/relation/index.d.mts +56 -0
  392. package/dist/relation/index.mjs +234 -0
  393. package/dist/scene/evaluators.mjs +1 -1
  394. package/dist/sim/thermal.mjs +45 -20
  395. package/dist/thermo/calorimetry.d.mts +207 -0
  396. package/dist/thermo/calorimetry.mjs +345 -0
  397. package/dist/thermo/cycles.d.mts +142 -0
  398. package/dist/thermo/cycles.mjs +256 -0
  399. package/dist/thermo/entropy.d.mts +87 -0
  400. package/dist/thermo/entropy.mjs +140 -0
  401. package/dist/thermo/expansion.d.mts +130 -0
  402. package/dist/thermo/expansion.mjs +178 -0
  403. package/dist/thermo/gas.d.mts +197 -0
  404. package/dist/thermo/gas.mjs +279 -0
  405. package/dist/thermo/heat-transfer.d.mts +164 -0
  406. package/dist/thermo/heat-transfer.mjs +217 -0
  407. package/dist/thermo/index.d.mts +9 -82
  408. package/dist/thermo/index.mjs +9 -132
  409. package/dist/thermo/processes.d.mts +95 -0
  410. package/dist/thermo/processes.mjs +154 -0
  411. package/dist/thermo/temperature.d.mts +174 -0
  412. package/dist/thermo/temperature.mjs +236 -0
  413. package/dist/waves/damping.d.mts +224 -0
  414. package/dist/waves/damping.mjs +317 -0
  415. package/dist/waves/doppler.d.mts +72 -0
  416. package/dist/waves/doppler.mjs +125 -0
  417. package/dist/waves/index.d.mts +10 -0
  418. package/dist/waves/index.mjs +10 -0
  419. package/dist/waves/pendulum.d.mts +130 -0
  420. package/dist/waves/pendulum.mjs +211 -0
  421. package/dist/waves/pitch.d.mts +125 -0
  422. package/dist/waves/pitch.mjs +158 -0
  423. package/dist/waves/shm.d.mts +170 -0
  424. package/dist/waves/shm.mjs +279 -0
  425. package/dist/waves/springs.d.mts +103 -0
  426. package/dist/waves/springs.mjs +176 -0
  427. package/dist/waves/superposition.d.mts +124 -0
  428. package/dist/waves/superposition.mjs +196 -0
  429. package/dist/waves/wave.d.mts +154 -0
  430. package/dist/waves/wave.mjs +178 -0
  431. package/package.json +74 -2
@@ -0,0 +1,185 @@
1
+ import { calc, texSigFigs } from "../core/worked.mjs";
2
+ import { compose, resolve, toDegrees, toRadians } from "./vectors.mjs";
3
+ import { G_EARTH, vertical } from "./kinematics/free-fall.mjs";
4
+ import { MOTION_UNITS_TEX } from "./kinematics/equations.mjs";
5
+ import { motion, timeToReach } from "./kinematics/solve.mjs";
6
+
7
+ //#region src/physics/projectile.ts
8
+ /**
9
+ * Projectile motion, as what it actually is: TWO straight-line motions sharing one clock.
10
+ *
11
+ * Every formula in a projectile chapter is a consequence of three sentences:
12
+ *
13
+ * 1. Horizontally there is no force, so the horizontal velocity never changes: `x = u_x t`.
14
+ * 2. Vertically there is gravity and nothing else, so it is ordinary SUVAT with `a = −g`.
15
+ * 3. The two motions share `t`, and that is the only thing connecting them.
16
+ *
17
+ * So this module declares almost no formulas of its own. It resolves the launch into components
18
+ * with `vectors`, hands the vertical part to `kinematics`, and multiplies the horizontal one out.
19
+ * A chapter's worth of results, range and time of flight and maximum height, fall out of that,
20
+ * and crucially they fall out IN THE SAME WAY for the cases textbooks separate into different
21
+ * "types": launched from the ground, launched from a cliff, launched downwards. Those are the same
22
+ * three sentences with a different starting height, and building them as one thing rather than as
23
+ * three is the whole point.
24
+ *
25
+ * The two-motion structure is also what makes the derivations honest. When {@link flightSteps}
26
+ * shows a time of flight, the quadratic and its rejected root come from the kinematics kernel, not
27
+ * from a projectile-shaped formula that hides them.
28
+ *
29
+ * Pure: no React, no pixels.
30
+ */
31
+ const gravityOf = (launch) => launch.g ?? 9.8;
32
+ const heightOf = (launch) => launch.height ?? 0;
33
+ /** The launch speed split into its horizontal and vertical parts. */
34
+ const launchVelocity = (launch) => resolve(launch.speed, launch.angleDeg);
35
+ /** The vertical half of a flight, as the signed SUVAT a falling-body question would use. */
36
+ const verticalHalf = (uy, fallsBy, g) => vertical({
37
+ speed: Math.abs(uy),
38
+ direction: uy >= 0 ? "up" : "down",
39
+ fallsBy,
40
+ g
41
+ });
42
+ /**
43
+ * Everything about one flight.
44
+ *
45
+ * The time of flight goes through the kinematics solver rather than through a closed form, because
46
+ * with a launch height it IS a quadratic with a root to reject, and routing it through the same
47
+ * code path as the level-ground case means the level-ground case cannot quietly be a different
48
+ * piece of physics.
49
+ */
50
+ function flight(launch) {
51
+ const g = gravityOf(launch);
52
+ const h = heightOf(launch);
53
+ const { x: ux, y: uy } = launchVelocity(launch);
54
+ const timeOfFlight = motion("t", verticalHalf(uy, h, g)).value;
55
+ const range = ux * timeOfFlight;
56
+ const timeToPeak = uy > 0 ? uy / g : 0;
57
+ const peakRise = uy > 0 ? uy * uy / (2 * g) : 0;
58
+ const impact = velocityAt(launch, timeOfFlight);
59
+ const { magnitude, angleDeg } = compose(impact.x, impact.y);
60
+ return {
61
+ launchVelocity: {
62
+ x: ux,
63
+ y: uy
64
+ },
65
+ timeOfFlight,
66
+ range,
67
+ timeToPeak,
68
+ peakRise,
69
+ maxHeight: h + peakRise,
70
+ impactSpeed: magnitude,
71
+ impactAngleDeg: -angleDeg
72
+ };
73
+ }
74
+ /** Where the projectile is at time `t`, measured from the launch point. */
75
+ function positionAt(launch, t) {
76
+ const g = gravityOf(launch);
77
+ const { x: ux, y: uy } = launchVelocity(launch);
78
+ return {
79
+ x: ux * t,
80
+ y: uy * t - .5 * g * t * t
81
+ };
82
+ }
83
+ /** How fast and which way it is going at time `t`. Horizontal never changes; that is the point. */
84
+ function velocityAt(launch, t) {
85
+ const g = gravityOf(launch);
86
+ const { x: ux, y: uy } = launchVelocity(launch);
87
+ return {
88
+ x: ux,
89
+ y: uy - g * t
90
+ };
91
+ }
92
+ /** The arc, sampled for drawing. Always includes the landing point exactly. */
93
+ function arc(launch, samples = 64) {
94
+ const total = flight(launch).timeOfFlight;
95
+ const points = [];
96
+ for (let i = 0; i <= samples; i++) points.push(positionAt(launch, total * i / samples));
97
+ return points;
98
+ }
99
+ /**
100
+ * Every moment the projectile is at a given height above the LAUNCH point.
101
+ *
102
+ * Usually two, and that is the interesting part: on the way up and on the way down. A lab that
103
+ * draws both, and a lesson that says why there are two, turns a confusing quadratic into the
104
+ * obvious fact that the arc is symmetric.
105
+ */
106
+ function timeAtHeight(launch, heightAboveLaunch) {
107
+ const g = gravityOf(launch);
108
+ const { y: uy } = launchVelocity(launch);
109
+ return timeToReach(heightAboveLaunch, {
110
+ u: uy,
111
+ a: -g
112
+ });
113
+ }
114
+ /**
115
+ * The launch angles that put a projectile a given distance away on level ground.
116
+ *
117
+ * There are normally TWO, one low and flat and one high and lobbed, and they are complementary
118
+ * (they add to 90°). That pair is the most under-taught fact in the topic: a mortar and a rifle
119
+ * hitting the same target is the same equation twice. Returns null when the target is out of
120
+ * range at that speed, which is the honest answer and the one a game needs.
121
+ */
122
+ function anglesForRange(range, speed, g = G_EARTH) {
123
+ const sin2theta = range * g / (speed * speed);
124
+ if (sin2theta > 1 || sin2theta < -1) return null;
125
+ const low = toDegrees(Math.asin(sin2theta)) / 2;
126
+ return {
127
+ low,
128
+ high: 90 - low
129
+ };
130
+ }
131
+ /**
132
+ * The smallest launch speed that can reach a distance on level ground, and the angle that does it.
133
+ *
134
+ * `R = v² sin 2θ / g` is largest for a given speed when `sin 2θ = 1`, so the cheapest shot is
135
+ * always at 45° and needs `v = √(Rg)`. Worth having as its own function because "what is the
136
+ * minimum speed" is a standard exam question and because the answer explains why 45° is the angle
137
+ * everybody remembers.
138
+ */
139
+ function minimumSpeedForRange(range, g = G_EARTH) {
140
+ return {
141
+ speed: Math.sqrt(range * g),
142
+ angleDeg: 45
143
+ };
144
+ }
145
+ /**
146
+ * The launch angle at which the range equals the maximum height.
147
+ *
148
+ * `R = H` gives `tan θ = 4`, independent of speed and of gravity, which is a genuinely surprising
149
+ * result and a good lab question: the learner predicts whether firing harder changes the angle,
150
+ * and it does not.
151
+ */
152
+ const angleWhereRangeEqualsHeight = () => toDegrees(Math.atan(4));
153
+ /**
154
+ * The worked solution for a flight, as a lesson would set it out.
155
+ *
156
+ * Structured as resolve, then vertical, then horizontal, in that order and labelled as such,
157
+ * because that ordering IS the method. A derivation that jumps to `R = u² sin 2θ / g` gives a
158
+ * student a formula to memorise; this one gives them something they can redo when the question has
159
+ * a cliff in it and the memorised formula does not apply.
160
+ */
161
+ function flightSteps(launch, sf = 3) {
162
+ const g = gravityOf(launch);
163
+ const h = heightOf(launch);
164
+ const { x: ux, y: uy } = launchVelocity(launch);
165
+ const f = flight(launch);
166
+ const w = calc();
167
+ const SPEED = MOTION_UNITS_TEX.u;
168
+ w.step(`u_x = u\\cos\\theta = ${texSigFigs(launch.speed, sf)}\\cos ${texSigFigs(launch.angleDeg, sf)}^\\circ = ${texSigFigs(ux, sf)}\\ ${SPEED}`, "step 1: split the launch into two motions");
169
+ w.step(`u_y = u\\sin\\theta = ${texSigFigs(launch.speed, sf)}\\sin ${texSigFigs(launch.angleDeg, sf)}^\\circ = ${texSigFigs(uy, sf)}\\ ${SPEED}`);
170
+ const verticalSolve = motion("t", verticalHalf(uy, h, g), sf);
171
+ w.step(`\\text{up is positive} \\;\\Rightarrow\\; a = -g, \\quad s = ${h > 0 ? "-h" : "0"}`, h > 0 ? "step 2: the vertical motion. It lands below the launch point, so its displacement is negative" : "step 2: the vertical motion. It lands back at launch height, so its displacement is zero");
172
+ for (const step of verticalSolve.worked.steps.slice(1)) w.step(step.tex, step.note);
173
+ w.step(`x = u_x t = ${texSigFigs(ux, sf + 1)} \\times ${texSigFigs(f.timeOfFlight, sf + 1)} = ${texSigFigs(f.range, sf + 1)}\\ \\mathrm{m}`, "step 3: the horizontal motion, which never accelerated, over that same time");
174
+ return w.done(f.range);
175
+ }
176
+ /** The working for the peak: why the highest point is where the vertical velocity is zero. */
177
+ function peakSteps(launch, sf = 3) {
178
+ const g = gravityOf(launch);
179
+ const { y: uy } = launchVelocity(launch);
180
+ const f = flight(launch);
181
+ return calc().step(`v_y = 0 \\text{ at the top}`, "it is still moving horizontally, but for that instant it is going neither up nor down").step(`t = \\frac{u_y}{g} = \\frac{${texSigFigs(uy, sf)}}{${texSigFigs(g, sf)}} = ${texSigFigs(f.timeToPeak, sf)}\\ \\mathrm{s}`, "from v = u + at with v = 0").step(`H = \\frac{u_y^2}{2g} = ${texSigFigs(f.peakRise, sf)}\\ \\mathrm{m}`, "from v² = u² + 2as with v = 0").done(f.peakRise);
182
+ }
183
+
184
+ //#endregion
185
+ export { angleWhereRangeEqualsHeight, anglesForRange, arc, flight, flightSteps, launchVelocity, minimumSpeedForRange, peakSteps, positionAt, timeAtHeight, velocityAt };
@@ -0,0 +1,85 @@
1
+ import { Worked } from "../../core/worked.mjs";
2
+
3
+ //#region src/physics/rotation/angular.d.ts
4
+ /** Revolutions per second to radians per second. */
5
+ declare const fromRevsPerSecond: (n: number) => number;
6
+ /** Revolutions per minute to radians per second. */
7
+ declare const fromRPM: (rpm: number) => number;
8
+ /** `L = Iω`, for a body whose moment of inertia you know. */
9
+ declare const angularMomentum: (inertia: number, omega: number) => number;
10
+ /**
11
+ * `L = mvr` for a point mass on a string, which is `Iω` with `I = mr²` written out.
12
+ *
13
+ * Kept because that is how the question is posed, and because seeing the two forms give the same
14
+ * number is what makes `I = mr²` feel like a definition rather than another formula.
15
+ */
16
+ declare function angularMomentumOfPoint(mass: number, speed: number, radius: number, sf?: number): {
17
+ value: number;
18
+ worked: Worked;
19
+ };
20
+ interface SpinChange {
21
+ readonly omega2: number;
22
+ readonly energyBefore: number;
23
+ readonly energyAfter: number;
24
+ /** Positive when the body ends up with MORE energy, which pulling in always does. */
25
+ readonly workDone: number;
26
+ readonly worked: Worked;
27
+ }
28
+ /**
29
+ * The skater: `I₁ω₁ = I₂ω₂` when nothing external twists the system.
30
+ *
31
+ * Returns the energy on both sides as well as the new spin rate, because the energy is the
32
+ * interesting half and a function that returned only `ω₂` would hide it.
33
+ */
34
+ declare function conserveSpin(inertia1: number, omega1: number, inertia2: number, sf?: number): SpinChange;
35
+ /**
36
+ * The shape factor `k²/r²` for the bodies a rolling question uses.
37
+ *
38
+ * Derived from the standard results rather than listed as folklore: a solid disc is `½MR²`, so
39
+ * `k²/r² = ½`, and so on. Everything about a rolling race follows from this one column.
40
+ */
41
+ declare const ROLLING_SHAPES: {
42
+ readonly hoop: {
43
+ readonly label: "hoop or thin ring";
44
+ readonly factor: 1;
45
+ };
46
+ readonly disc: {
47
+ readonly label: "solid disc or cylinder";
48
+ readonly factor: 0.5;
49
+ };
50
+ readonly sphere: {
51
+ readonly label: "solid sphere";
52
+ readonly factor: 0.4;
53
+ };
54
+ readonly shell: {
55
+ readonly label: "hollow sphere";
56
+ readonly factor: number;
57
+ };
58
+ };
59
+ type RollingShape = keyof typeof ROLLING_SHAPES;
60
+ interface RollingEnergy {
61
+ readonly translational: number;
62
+ readonly rotational: number;
63
+ readonly total: number;
64
+ /** The fraction of the energy that is in the spin. Shape alone decides it. */
65
+ readonly spinShare: number;
66
+ readonly worked: Worked;
67
+ }
68
+ /** How a rolling body's kinetic energy divides between going along and going round. */
69
+ declare function rollingEnergy(mass: number, speed: number, shape: RollingShape, sf?: number): RollingEnergy;
70
+ /**
71
+ * The speed a body reaches rolling from rest down a height `h`.
72
+ *
73
+ * `v = √(2gh / (1 + k²/r²))`. Mass and radius cancel completely, so the race down a slope is
74
+ * decided by shape and nothing else: sphere, then disc, then hollow sphere, then hoop, every time,
75
+ * whatever they weigh. Worth having a learner predict first, because the intuition is that the
76
+ * heavy one wins.
77
+ */
78
+ declare function rollingSpeedFromHeight(height: number, shape: RollingShape, g?: number, sf?: number): {
79
+ speed: number;
80
+ worked: Worked;
81
+ };
82
+ /** Order a set of shapes by how fast they finish a roll: the race, as a prediction to check. */
83
+ declare const rollingRace: (shapes?: readonly RollingShape[]) => RollingShape[];
84
+ //#endregion
85
+ export { ROLLING_SHAPES, RollingEnergy, RollingShape, SpinChange, angularMomentum, angularMomentumOfPoint, conserveSpin, fromRPM, fromRevsPerSecond, rollingEnergy, rollingRace, rollingSpeedFromHeight };
@@ -0,0 +1,130 @@
1
+ import { calc, texSigFigs } from "../../core/worked.mjs";
2
+
3
+ //#region src/physics/rotation/angular.ts
4
+ /**
5
+ * Angular momentum, rotational energy, and rolling.
6
+ *
7
+ * THE SKATER. Angular momentum is conserved when no external torque acts, and `L = Iω` means that
8
+ * pulling your arms in cuts `I` and so must raise `ω`. Everyone has seen this and almost nobody is
9
+ * told the surprising half: the kinetic energy goes UP, not stays the same. `E = ½Iω²` and `L = Iω`
10
+ * together give `E = L²/2I`, so halving `I` at constant `L` DOUBLES the energy. It comes from the
11
+ * skater's muscles doing work pulling the arms in against the outward pull, which is a real,
12
+ * checkable, slightly startling fact and a much better question than "what is the new ω".
13
+ *
14
+ * ROLLING. A rolling body carries its energy in two places at once, `½mv²` in its motion and `½Iω²`
15
+ * in its spin, and the split depends only on SHAPE. `v = rω` links them, so
16
+ *
17
+ * E = ½mv²(1 + k²/r²)
18
+ *
19
+ * where `k` is the radius of gyration. A hoop puts half its energy into spin and a sphere only
20
+ * two-sevenths, so racing them down a slope sorts them by shape with mass and radius cancelling
21
+ * out entirely. That cancellation is the best prediction question in the topic, because everybody
22
+ * guesses the heavy one wins.
23
+ *
24
+ * Pure: no React, no pixels.
25
+ */
26
+ /** Revolutions per second to radians per second. */
27
+ const fromRevsPerSecond = (n) => 2 * Math.PI * n;
28
+ /** Revolutions per minute to radians per second. */
29
+ const fromRPM = (rpm) => 2 * Math.PI * rpm / 60;
30
+ /** `L = Iω`, for a body whose moment of inertia you know. */
31
+ const angularMomentum = (inertia, omega) => inertia * omega;
32
+ /**
33
+ * `L = mvr` for a point mass on a string, which is `Iω` with `I = mr²` written out.
34
+ *
35
+ * Kept because that is how the question is posed, and because seeing the two forms give the same
36
+ * number is what makes `I = mr²` feel like a definition rather than another formula.
37
+ */
38
+ function angularMomentumOfPoint(mass, speed, radius, sf = 3) {
39
+ const value = mass * speed * radius;
40
+ return {
41
+ value,
42
+ worked: calc().step("L = I\\omega = (mr^2)\\left(\\frac{v}{r}\\right) = mvr", "the same thing written two ways").step(`L = ${texSigFigs(mass, sf)} \\times ${texSigFigs(speed, sf)} \\times ${texSigFigs(radius, sf)} = ${texSigFigs(value, sf)}\\ \\mathrm{kg\\,m^2\\,s^{-1}}`).done(value)
43
+ };
44
+ }
45
+ /**
46
+ * The skater: `I₁ω₁ = I₂ω₂` when nothing external twists the system.
47
+ *
48
+ * Returns the energy on both sides as well as the new spin rate, because the energy is the
49
+ * interesting half and a function that returned only `ω₂` would hide it.
50
+ */
51
+ function conserveSpin(inertia1, omega1, inertia2, sf = 3) {
52
+ if (inertia1 <= 0 || inertia2 <= 0) throw new Error("Moments of inertia must be positive.");
53
+ const omega2 = inertia1 * omega1 / inertia2;
54
+ const energyBefore = .5 * inertia1 * omega1 * omega1;
55
+ const energyAfter = .5 * inertia2 * omega2 * omega2;
56
+ const worked = calc().step("I_1\\omega_1 = I_2\\omega_2", "no external torque, so the angular momentum cannot change").step(`\\omega_2 = \\frac{${texSigFigs(inertia1, sf)} \\times ${texSigFigs(omega1, sf)}}{${texSigFigs(inertia2, sf)}} = ${texSigFigs(omega2, sf)}\\ \\mathrm{rad\\,s^{-1}}`).step(`E = \\frac{L^2}{2I}: ${texSigFigs(energyBefore, sf)} \\to ${texSigFigs(energyAfter, sf)}\\ \\mathrm{J}`, energyAfter > energyBefore + 1e-12 ? "the energy ROSE, and it came from the muscles pulling the arms in against the outward pull" : energyAfter < energyBefore - 1e-12 ? "the energy fell: letting the arms out, work is done BY the body" : "unchanged, because the moment of inertia did not change").done(omega2);
57
+ return {
58
+ omega2,
59
+ energyBefore,
60
+ energyAfter,
61
+ workDone: energyAfter - energyBefore,
62
+ worked
63
+ };
64
+ }
65
+ /**
66
+ * The shape factor `k²/r²` for the bodies a rolling question uses.
67
+ *
68
+ * Derived from the standard results rather than listed as folklore: a solid disc is `½MR²`, so
69
+ * `k²/r² = ½`, and so on. Everything about a rolling race follows from this one column.
70
+ */
71
+ const ROLLING_SHAPES = {
72
+ hoop: {
73
+ label: "hoop or thin ring",
74
+ factor: 1
75
+ },
76
+ disc: {
77
+ label: "solid disc or cylinder",
78
+ factor: .5
79
+ },
80
+ sphere: {
81
+ label: "solid sphere",
82
+ factor: .4
83
+ },
84
+ shell: {
85
+ label: "hollow sphere",
86
+ factor: 2 / 3
87
+ }
88
+ };
89
+ /** How a rolling body's kinetic energy divides between going along and going round. */
90
+ function rollingEnergy(mass, speed, shape, sf = 3) {
91
+ const { factor, label } = ROLLING_SHAPES[shape];
92
+ const translational = .5 * mass * speed * speed;
93
+ const rotational = factor * translational;
94
+ const total = translational + rotational;
95
+ const worked = calc().step("E = \\tfrac{1}{2}mv^2 + \\tfrac{1}{2}I\\omega^2 = \\tfrac{1}{2}mv^2\\left(1 + \\frac{k^2}{r^2}\\right)", `v = rω links the two, and for a ${label} the shape factor is ${factor}`).step(`E = ${texSigFigs(translational, sf)} + ${texSigFigs(rotational, sf)} = ${texSigFigs(total, sf)}\\ \\mathrm{J}`, `${texSigFigs(100 * (rotational / total), sf)}% of it is in the spin, and that share depends on SHAPE alone`).done(total);
96
+ return {
97
+ translational,
98
+ rotational,
99
+ total,
100
+ spinShare: rotational / total,
101
+ worked
102
+ };
103
+ }
104
+ /**
105
+ * The speed a body reaches rolling from rest down a height `h`.
106
+ *
107
+ * `v = √(2gh / (1 + k²/r²))`. Mass and radius cancel completely, so the race down a slope is
108
+ * decided by shape and nothing else: sphere, then disc, then hollow sphere, then hoop, every time,
109
+ * whatever they weigh. Worth having a learner predict first, because the intuition is that the
110
+ * heavy one wins.
111
+ */
112
+ function rollingSpeedFromHeight(height, shape, g = 9.8, sf = 3) {
113
+ if (height < 0) throw new Error("The drop must not be negative.");
114
+ const { factor, label } = ROLLING_SHAPES[shape];
115
+ const speed = Math.sqrt(2 * g * height / (1 + factor));
116
+ return {
117
+ speed,
118
+ worked: calc().step("mgh = \\tfrac{1}{2}mv^2\\left(1 + \\frac{k^2}{r^2}\\right)", "all the lost height becomes both kinds of motion").step("v = \\sqrt{\\frac{2gh}{1 + k^2/r^2}}", "the mass cancels, and so does the radius: only the SHAPE is left").step(`v = ${texSigFigs(speed, sf)}\\ \\mathrm{m\\,s^{-1}}`, `for a ${label}. A body that puts more energy into spinning arrives slower, whatever it weighs`).done(speed)
119
+ };
120
+ }
121
+ /** Order a set of shapes by how fast they finish a roll: the race, as a prediction to check. */
122
+ const rollingRace = (shapes = [
123
+ "sphere",
124
+ "disc",
125
+ "shell",
126
+ "hoop"
127
+ ]) => [...shapes].sort((a, b) => ROLLING_SHAPES[a].factor - ROLLING_SHAPES[b].factor);
128
+
129
+ //#endregion
130
+ export { ROLLING_SHAPES, angularMomentum, angularMomentumOfPoint, conserveSpin, fromRPM, fromRevsPerSecond, rollingEnergy, rollingRace, rollingSpeedFromHeight };
@@ -0,0 +1,79 @@
1
+ import { Worked } from "../../core/worked.mjs";
2
+
3
+ //#region src/physics/rotation/circular.d.ts
4
+ /** `a = v²/r = ω²r`, directed at the centre. */
5
+ declare const centripetalAcceleration: (speed: number, radius: number) => number;
6
+ /** `F = mv²/r`: not an extra force, but what the real ones have to add up to. */
7
+ declare function centripetalForce(mass: number, speed: number, radius: number, sf?: number): {
8
+ value: number;
9
+ acceleration: number;
10
+ worked: Worked;
11
+ };
12
+ /** The same thing from a spin rate: `F = mω²r`, which is what a whirled string question gives. */
13
+ declare const centripetalFromOmega: (mass: number, omega: number, radius: number) => number;
14
+ /**
15
+ * The fastest a vehicle can take a FLAT bend before it slides.
16
+ *
17
+ * Friction is the only thing pointing at the centre, so `μmg ≥ mv²/r` and the mass cancels: a
18
+ * loaded lorry and an empty one slide at the same speed, which is not what anyone expects.
19
+ */
20
+ declare function maxSpeedFlat(radius: number, mu: number, g?: number, sf?: number): {
21
+ speed: number;
22
+ worked: Worked;
23
+ };
24
+ /**
25
+ * The angle a bend should be banked to, so that no friction is needed at all: `tan θ = v²/rg`.
26
+ *
27
+ * At this angle the track's normal force alone leans inward enough to turn the vehicle, and the
28
+ * tyres do no sideways work. It is the design speed of the bend, and again the mass cancels, so one
29
+ * bank angle serves a bicycle and a lorry.
30
+ */
31
+ declare function bankingAngle(speed: number, radius: number, g?: number, sf?: number): {
32
+ degrees: number;
33
+ worked: Worked;
34
+ };
35
+ /**
36
+ * How much higher the outer rail must sit, given the gauge.
37
+ *
38
+ * The railway form of the same question: the bank angle is set by raising one rail, so
39
+ * `h = gauge · sin θ`. Their worked example is a 98 m bend at 9.8 m/s on a 1.525 m gauge.
40
+ */
41
+ declare function railCant(speed: number, radius: number, gauge: number, g?: number, sf?: number): {
42
+ height: number;
43
+ degrees: number;
44
+ worked: Worked;
45
+ };
46
+ /**
47
+ * The fastest a vehicle can take a BANKED bend that also has friction.
48
+ *
49
+ * Both help: the bank leans the normal force inward and friction adds to it. The denominator is
50
+ * what makes this interesting, because `cos θ − μ sin θ` goes to zero at `μ = cot θ` and the
51
+ * predicted speed goes to infinity. That is not a bug in the algebra, it is the statement that a
52
+ * bend banked steeply enough, with grippy enough tyres, cannot be slid out of at any speed. Real
53
+ * tracks do not go that far, and the function says so rather than returning Infinity quietly.
54
+ */
55
+ declare function maxSpeedBanked(radius: number, angleDeg: number, mu: number, g?: number, sf?: number): {
56
+ speed: number;
57
+ worked: Worked;
58
+ };
59
+ /**
60
+ * The tension in a string whirling a mass in a VERTICAL circle, at any angle from the top.
61
+ *
62
+ * `T = mv²/r − mg cos φ` measuring `φ` from the top, so the string is slackest at the top and
63
+ * tightest at the bottom, with the difference `2mg`. Gravity helps provide the centripetal force at
64
+ * the top and fights it at the bottom, and that single sentence is the whole of the topic.
65
+ */
66
+ declare function verticalCircleTension(mass: number, speed: number, radius: number, angleFromTopDeg: number, g?: number): number;
67
+ /**
68
+ * The slowest a mass can go round a vertical circle without the string going slack at the top.
69
+ *
70
+ * At the critical speed the string carries nothing and gravity alone supplies the whole centripetal
71
+ * requirement: `mg = mv²/r`, so `v = √(gr)`. Below it the string cannot push, so the mass leaves
72
+ * the circular path, which is why a bucket of water must be swung fast enough and not merely swung.
73
+ */
74
+ declare function minimumSpeedAtTop(radius: number, g?: number, sf?: number): {
75
+ speed: number;
76
+ worked: Worked;
77
+ };
78
+ //#endregion
79
+ export { bankingAngle, centripetalAcceleration, centripetalForce, centripetalFromOmega, maxSpeedBanked, maxSpeedFlat, minimumSpeedAtTop, railCant, verticalCircleTension };
@@ -0,0 +1,131 @@
1
+ import { calc, texSigFigs } from "../../core/worked.mjs";
2
+ import { toDegrees, toRadians } from "../vectors.mjs";
3
+ import { G_EARTH } from "../kinematics/free-fall.mjs";
4
+
5
+ //#region src/physics/rotation/circular.ts
6
+ /**
7
+ * Going round in a circle: what holds you in, and how fast you can take the bend.
8
+ *
9
+ * ONE CORRECTION FIRST, because it is the misconception the whole topic trips on. There is no
10
+ * outward force. A body moving in a circle is ACCELERATING, towards the centre, and something real
11
+ * has to supply that: friction on tyres, tension in a string, gravity on a satellite. The outward
12
+ * push a passenger feels is their own inertia continuing in a straight line while the car turns
13
+ * under them. "Centrifugal force" names that feeling, not a force, and a diagram that draws it
14
+ * alongside the real forces has two arrows where physics has one.
15
+ *
16
+ * So `F = mv²/r` is never an extra force to add. It is what the forces you already have must SUM
17
+ * TO. Every question in the topic is that one sentence: find the real forces, resolve them towards
18
+ * the centre, set the total equal to `mv²/r`.
19
+ *
20
+ * Pure: no React, no pixels.
21
+ */
22
+ /** `a = v²/r = ω²r`, directed at the centre. */
23
+ const centripetalAcceleration = (speed, radius) => {
24
+ if (radius <= 0) throw new Error("The radius must be positive.");
25
+ return speed * speed / radius;
26
+ };
27
+ /** `F = mv²/r`: not an extra force, but what the real ones have to add up to. */
28
+ function centripetalForce(mass, speed, radius, sf = 3) {
29
+ const acceleration = centripetalAcceleration(speed, radius);
30
+ const value = mass * acceleration;
31
+ return {
32
+ value,
33
+ acceleration,
34
+ worked: calc().step("\\sum F_{\\text{towards centre}} = \\frac{mv^2}{r}", "the REQUIREMENT, not an extra arrow. Something real has to supply it").step(`\\frac{mv^2}{r} = \\frac{${texSigFigs(mass, sf)} \\times ${texSigFigs(speed, sf)}^2}{${texSigFigs(radius, sf)}} = ${texSigFigs(value, sf)}\\ \\mathrm{N}`).done(value)
35
+ };
36
+ }
37
+ /** The same thing from a spin rate: `F = mω²r`, which is what a whirled string question gives. */
38
+ const centripetalFromOmega = (mass, omega, radius) => mass * omega * omega * radius;
39
+ /**
40
+ * The fastest a vehicle can take a FLAT bend before it slides.
41
+ *
42
+ * Friction is the only thing pointing at the centre, so `μmg ≥ mv²/r` and the mass cancels: a
43
+ * loaded lorry and an empty one slide at the same speed, which is not what anyone expects.
44
+ */
45
+ function maxSpeedFlat(radius, mu, g = G_EARTH, sf = 3) {
46
+ if (radius <= 0 || mu < 0) throw new Error("Radius must be positive and friction cannot be negative.");
47
+ const speed = Math.sqrt(mu * radius * g);
48
+ return {
49
+ speed,
50
+ worked: calc().step("\\mu m g \\geq \\frac{mv^2}{r}", "friction is the only force pointing at the centre").step("v \\leq \\sqrt{\\mu r g}", "the mass cancels: how heavily loaded it is makes no difference").step(`v_{\\max} = ${texSigFigs(speed, sf)}\\ \\mathrm{m\\,s^{-1}}`).done(speed)
51
+ };
52
+ }
53
+ /**
54
+ * The angle a bend should be banked to, so that no friction is needed at all: `tan θ = v²/rg`.
55
+ *
56
+ * At this angle the track's normal force alone leans inward enough to turn the vehicle, and the
57
+ * tyres do no sideways work. It is the design speed of the bend, and again the mass cancels, so one
58
+ * bank angle serves a bicycle and a lorry.
59
+ */
60
+ function bankingAngle(speed, radius, g = G_EARTH, sf = 3) {
61
+ if (radius <= 0) throw new Error("The radius must be positive.");
62
+ const ratio = speed * speed / (radius * g);
63
+ const degrees = toDegrees(Math.atan(ratio));
64
+ return {
65
+ degrees,
66
+ worked: calc().step("N\\sin\\theta = \\frac{mv^2}{r}, \\quad N\\cos\\theta = mg", "the track pushes perpendicular to itself; tilt it and part of that push aims at the centre").step("\\tan\\theta = \\frac{v^2}{rg}", "dividing kills both N and m, so one angle suits every vehicle").step(`\\theta = \\arctan ${texSigFigs(ratio, sf)} = ${texSigFigs(degrees, sf)}^\\circ`, "at this speed the tyres need no sideways grip at all").done(degrees)
67
+ };
68
+ }
69
+ /**
70
+ * How much higher the outer rail must sit, given the gauge.
71
+ *
72
+ * The railway form of the same question: the bank angle is set by raising one rail, so
73
+ * `h = gauge · sin θ`. Their worked example is a 98 m bend at 9.8 m/s on a 1.525 m gauge.
74
+ */
75
+ function railCant(speed, radius, gauge, g = G_EARTH, sf = 3) {
76
+ const { degrees } = bankingAngle(speed, radius, g);
77
+ const height = gauge * Math.sin(toRadians(degrees));
78
+ return {
79
+ height,
80
+ degrees,
81
+ worked: calc().step("\\tan\\theta = \\frac{v^2}{rg}", "the bank angle the bend needs").step(`\\theta = ${texSigFigs(degrees, sf)}^\\circ`).step(`h = L\\sin\\theta = ${texSigFigs(gauge, sf)}\\sin ${texSigFigs(degrees, sf)}^\\circ = ${texSigFigs(height, sf)}\\ \\mathrm{m}`, "raise the outer rail by this and the train leans into the bend on its own").done(height)
82
+ };
83
+ }
84
+ /**
85
+ * The fastest a vehicle can take a BANKED bend that also has friction.
86
+ *
87
+ * Both help: the bank leans the normal force inward and friction adds to it. The denominator is
88
+ * what makes this interesting, because `cos θ − μ sin θ` goes to zero at `μ = cot θ` and the
89
+ * predicted speed goes to infinity. That is not a bug in the algebra, it is the statement that a
90
+ * bend banked steeply enough, with grippy enough tyres, cannot be slid out of at any speed. Real
91
+ * tracks do not go that far, and the function says so rather than returning Infinity quietly.
92
+ */
93
+ function maxSpeedBanked(radius, angleDeg, mu, g = G_EARTH, sf = 3) {
94
+ if (radius <= 0) throw new Error("The radius must be positive.");
95
+ const theta = toRadians(angleDeg);
96
+ const denominator = Math.cos(theta) - mu * Math.sin(theta);
97
+ if (denominator <= 1e-9) throw new Error(`With a bank of ${angleDeg}° and μ = ${mu}, cos θ − μ sin θ is zero or negative, so this model predicts no upper speed limit at all: the bank and the grip together can hold any speed. That is the algebra being honest about an extreme case, not a defect.`);
98
+ const speed = Math.sqrt(radius * g * (Math.sin(theta) + mu * Math.cos(theta)) / denominator);
99
+ return {
100
+ speed,
101
+ worked: calc().step("v \\leq \\sqrt{\\frac{rg(\\sin\\theta + \\mu\\cos\\theta)}{\\cos\\theta - \\mu\\sin\\theta}}", "the bank and the friction both help, so the two effects appear together").step(`v_{\\max} = ${texSigFigs(speed, sf)}\\ \\mathrm{m\\,s^{-1}}`).done(speed)
102
+ };
103
+ }
104
+ /**
105
+ * The tension in a string whirling a mass in a VERTICAL circle, at any angle from the top.
106
+ *
107
+ * `T = mv²/r − mg cos φ` measuring `φ` from the top, so the string is slackest at the top and
108
+ * tightest at the bottom, with the difference `2mg`. Gravity helps provide the centripetal force at
109
+ * the top and fights it at the bottom, and that single sentence is the whole of the topic.
110
+ */
111
+ function verticalCircleTension(mass, speed, radius, angleFromTopDeg, g = G_EARTH) {
112
+ return mass * centripetalAcceleration(speed, radius) - mass * g * Math.cos(toRadians(angleFromTopDeg));
113
+ }
114
+ /**
115
+ * The slowest a mass can go round a vertical circle without the string going slack at the top.
116
+ *
117
+ * At the critical speed the string carries nothing and gravity alone supplies the whole centripetal
118
+ * requirement: `mg = mv²/r`, so `v = √(gr)`. Below it the string cannot push, so the mass leaves
119
+ * the circular path, which is why a bucket of water must be swung fast enough and not merely swung.
120
+ */
121
+ function minimumSpeedAtTop(radius, g = G_EARTH, sf = 3) {
122
+ if (radius <= 0) throw new Error("The radius must be positive.");
123
+ const speed = Math.sqrt(g * radius);
124
+ return {
125
+ speed,
126
+ worked: calc().step("T + mg = \\frac{mv^2}{r}", "at the top, gravity points the same way as the centripetal requirement").step("T = 0 \\;\\Rightarrow\\; mg = \\frac{mv^2}{r}", "the critical case is the string carrying nothing at all").step(`v_{\\min} = \\sqrt{gr} = ${texSigFigs(speed, sf)}\\ \\mathrm{m\\,s^{-1}}`, "any slower and the string would have to PUSH, which a string cannot do, so the mass falls inward").done(speed)
127
+ };
128
+ }
129
+
130
+ //#endregion
131
+ export { bankingAngle, centripetalAcceleration, centripetalForce, centripetalFromOmega, maxSpeedBanked, maxSpeedFlat, minimumSpeedAtTop, railCant, verticalCircleTension };