@classytic/labs 0.1.0 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (455) hide show
  1. package/dist/_virtual/_rolldown/runtime.mjs +18 -0
  2. package/dist/biology/enzyme-rate/preset.mjs +5 -5
  3. package/dist/biology/genetic-cross/core.d.mts +7 -7
  4. package/dist/biology/genetic-cross/core.mjs +4 -4
  5. package/dist/biology/genetic-cross/grid.mjs +132 -123
  6. package/dist/biology/genetic-cross/preset.mjs +4 -4
  7. package/dist/biology/genetic-cross/sex-linked.mjs +7 -7
  8. package/dist/biology/photosynthesis-factors/preset.mjs +8 -8
  9. package/dist/biology/respiration/preset.mjs +4 -4
  10. package/dist/biology/sequence/central-dogma.mjs +5 -5
  11. package/dist/biology/sequence/core.d.mts +6 -6
  12. package/dist/biology/sequence/core.mjs +1 -1
  13. package/dist/biology/sequence/preset.mjs +6 -6
  14. package/dist/blocks/authoring.mjs +5 -5
  15. package/dist/blocks/biology.d.mts +2 -2
  16. package/dist/blocks/biology.mjs +5 -5
  17. package/dist/blocks/chem.d.mts +2 -2
  18. package/dist/blocks/chem.mjs +13 -13
  19. package/dist/blocks/circuits.d.mts +293 -4
  20. package/dist/blocks/circuits.mjs +874 -9
  21. package/dist/blocks/discrete.d.mts +30 -2
  22. package/dist/blocks/discrete.mjs +74 -4
  23. package/dist/blocks/economics.mjs +1 -1
  24. package/dist/blocks/geography.mjs +1 -1
  25. package/dist/blocks/geometry.mjs +3 -3
  26. package/dist/blocks/ict.d.mts +90 -1
  27. package/dist/blocks/ict.mjs +217 -7
  28. package/dist/blocks/index.d.mts +3064 -657
  29. package/dist/blocks/index.mjs +9 -9
  30. package/dist/blocks/lab-block.mjs +5 -5
  31. package/dist/blocks/lab-config.d.mts +1 -1
  32. package/dist/blocks/lab-config.mjs +4 -4
  33. package/dist/blocks/lab-gallery.d.mts +1 -1
  34. package/dist/blocks/lab-gallery.mjs +2 -2
  35. package/dist/blocks/language.d.mts +6 -6
  36. package/dist/blocks/language.mjs +12 -12
  37. package/dist/blocks/lesson.mjs +4 -4
  38. package/dist/blocks/math.d.mts +577 -11
  39. package/dist/blocks/math.mjs +1648 -14
  40. package/dist/blocks/ml.d.mts +45 -1
  41. package/dist/blocks/ml.mjs +80 -6
  42. package/dist/blocks/physics.d.mts +9 -4
  43. package/dist/blocks/physics.mjs +75 -28
  44. package/dist/blocks/statistics.mjs +1 -1
  45. package/dist/build/CircuitEditor.d.mts +14 -0
  46. package/dist/build/CircuitEditor.mjs +787 -0
  47. package/dist/build/CircuitPlayer.d.mts +19 -0
  48. package/dist/build/CircuitPlayer.mjs +53 -0
  49. package/dist/build/CircuitScene.d.mts +61 -0
  50. package/dist/build/CircuitScene.mjs +383 -0
  51. package/dist/build/contract.d.mts +116 -0
  52. package/dist/build/editor-ops.d.mts +65 -0
  53. package/dist/build/editor-ops.mjs +306 -0
  54. package/dist/build/editor-ui.mjs +121 -0
  55. package/dist/build/flow.d.mts +14 -0
  56. package/dist/build/flow.mjs +119 -0
  57. package/dist/build/index.d.mts +10 -0
  58. package/dist/build/index.mjs +10 -0
  59. package/dist/build/parts/ammeter.d.mts +1 -0
  60. package/dist/build/parts/ammeter.mjs +32 -0
  61. package/dist/build/parts/bulb.d.mts +1 -0
  62. package/dist/build/parts/bulb.mjs +50 -0
  63. package/dist/build/parts/capacitor.d.mts +1 -0
  64. package/dist/build/parts/capacitor.mjs +26 -0
  65. package/dist/build/parts/cell.d.mts +1 -0
  66. package/dist/build/parts/cell.mjs +40 -0
  67. package/dist/build/parts/diode.d.mts +1 -0
  68. package/dist/build/parts/diode.mjs +33 -0
  69. package/dist/build/parts/index.d.mts +5 -0
  70. package/dist/build/parts/index.mjs +43 -0
  71. package/dist/build/parts/mosfet.d.mts +1 -0
  72. package/dist/build/parts/mosfet.mjs +95 -0
  73. package/dist/build/parts/node.d.mts +1 -0
  74. package/dist/build/parts/node.mjs +32 -0
  75. package/dist/build/parts/resistor.d.mts +1 -0
  76. package/dist/build/parts/resistor.mjs +49 -0
  77. package/dist/build/parts/shared.mjs +42 -0
  78. package/dist/build/parts/switch.d.mts +1 -0
  79. package/dist/build/parts/switch.mjs +34 -0
  80. package/dist/build/parts.d.mts +1 -0
  81. package/dist/build/registry.d.mts +9 -0
  82. package/dist/build/registry.mjs +15 -0
  83. package/dist/build/solve.d.mts +8 -0
  84. package/dist/build/solve.mjs +0 -0
  85. package/dist/catalog/registry.d.mts +2 -2
  86. package/dist/catalog/templates.d.mts +1 -1
  87. package/dist/catalog/templates.mjs +6 -6
  88. package/dist/chem/battery.mjs +1 -1
  89. package/dist/chem/bohr-atom.mjs +4 -4
  90. package/dist/chem/diffusion/preset.mjs +4 -4
  91. package/dist/chem/electrochem/preset.mjs +5 -5
  92. package/dist/chem/equilibrium/preset.d.mts +1 -1
  93. package/dist/chem/equilibrium/preset.mjs +6 -6
  94. package/dist/chem/gas-box/preset.mjs +6 -6
  95. package/dist/chem/kinetics/preset.mjs +6 -6
  96. package/dist/chem/periodic-trends/preset.mjs +7 -7
  97. package/dist/chem/reaction-lab.mjs +3 -3
  98. package/dist/chem/reaction-profile.mjs +4 -4
  99. package/dist/chem/solution/dilution.mjs +6 -6
  100. package/dist/chem/solution/field.d.mts +2 -2
  101. package/dist/chem/solution/field.mjs +2 -2
  102. package/dist/chem/solution/solution-box.mjs +7 -7
  103. package/dist/chem/stoichiometry/preset.mjs +5 -5
  104. package/dist/chem/titration/preset.mjs +5 -5
  105. package/dist/circuits/ac-dc/asset.mjs +1 -1
  106. package/dist/circuits/ac-dc/preset.mjs +2 -2
  107. package/dist/circuits/brownout/index.d.mts +1 -0
  108. package/dist/circuits/brownout/preset.d.mts +22 -0
  109. package/dist/circuits/brownout/preset.mjs +399 -0
  110. package/dist/circuits/capacitor-leak/preset.mjs +13 -8
  111. package/dist/circuits/circuit/asset.mjs +71 -14
  112. package/dist/circuits/circuit/preset.mjs +23 -5
  113. package/dist/circuits/circuit-builder.mjs +60 -132
  114. package/dist/circuits/circuit-lab.mjs +60 -40
  115. package/dist/circuits/cmos-gate/index.d.mts +1 -0
  116. package/dist/circuits/cmos-gate/preset.d.mts +75 -0
  117. package/dist/circuits/cmos-gate/preset.mjs +1491 -0
  118. package/dist/circuits/diode/index.d.mts +1 -0
  119. package/dist/circuits/diode/preset.d.mts +25 -0
  120. package/dist/circuits/diode/preset.mjs +266 -0
  121. package/dist/circuits/index.d.mts +7 -1
  122. package/dist/circuits/index.mjs +7 -1
  123. package/dist/circuits/rc-charging/index.d.mts +1 -0
  124. package/dist/circuits/rc-charging/preset.d.mts +27 -0
  125. package/dist/circuits/rc-charging/preset.mjs +329 -0
  126. package/dist/circuits/semiconductor/index.d.mts +1 -0
  127. package/dist/circuits/semiconductor/preset.d.mts +102 -0
  128. package/dist/circuits/semiconductor/preset.mjs +1855 -0
  129. package/dist/circuits/transistor/index.d.mts +1 -0
  130. package/dist/circuits/transistor/preset.d.mts +27 -0
  131. package/dist/circuits/transistor/preset.mjs +329 -0
  132. package/dist/commerce/accounting/core.d.mts +1 -1
  133. package/dist/commerce/accounting/equation-balance.mjs +5 -5
  134. package/dist/commerce/accounting/journal-poster.mjs +8 -8
  135. package/dist/commerce/accounting/statement-sorter.mjs +4 -4
  136. package/dist/commerce/economics/core.d.mts +2 -2
  137. package/dist/commerce/economics/core.mjs +1 -1
  138. package/dist/commerce/economics/demand-shift-vs-move.mjs +6 -6
  139. package/dist/commerce/economics/elasticity-revenue.mjs +6 -6
  140. package/dist/commerce/economics/market-equilibrium.mjs +5 -5
  141. package/dist/core/easing.d.mts +3 -3
  142. package/dist/core/easing.mjs +2 -2
  143. package/dist/core/numeric.d.mts +3 -3
  144. package/dist/core/numeric.mjs +2 -2
  145. package/dist/core/reactive.d.mts +1 -1
  146. package/dist/core/reactive.mjs +1 -1
  147. package/dist/core/rng.d.mts +2 -2
  148. package/dist/core/rng.mjs +1 -1
  149. package/dist/core/tex.mjs +2 -2
  150. package/dist/core/timeline.d.mts +1 -1
  151. package/dist/core/timeline.mjs +1 -1
  152. package/dist/core/util.mjs +11 -1
  153. package/dist/discrete/arrangements/preset.mjs +6 -14
  154. package/dist/discrete/bayes/preset.mjs +43 -35
  155. package/dist/discrete/binomial/preset.mjs +2 -2
  156. package/dist/discrete/combination-studio/figure.d.mts +6 -0
  157. package/dist/discrete/combination-studio/figure.mjs +159 -0
  158. package/dist/discrete/combination-studio/index.d.mts +2 -0
  159. package/dist/discrete/combination-studio/preset.d.mts +44 -0
  160. package/dist/discrete/combination-studio/preset.mjs +440 -0
  161. package/dist/discrete/core/combinatorics.d.mts +23 -3
  162. package/dist/discrete/core/combinatorics.mjs +38 -3
  163. package/dist/discrete/core/pigeonhole.d.mts +1 -1
  164. package/dist/discrete/core/pigeonhole.mjs +1 -1
  165. package/dist/discrete/core/probability.d.mts +3 -3
  166. package/dist/discrete/core/probability.mjs +3 -3
  167. package/dist/discrete/core/sets.d.mts +1 -1
  168. package/dist/discrete/counting-slots/preset.mjs +8 -8
  169. package/dist/discrete/counting-tree/preset.mjs +65 -8
  170. package/dist/discrete/expected-value/preset.mjs +13 -13
  171. package/dist/discrete/hypergeometric/preset.mjs +48 -15
  172. package/dist/discrete/index.d.mts +4 -2
  173. package/dist/discrete/index.mjs +4 -2
  174. package/dist/discrete/karnaugh/preset.mjs +26 -20
  175. package/dist/discrete/lln/preset.mjs +44 -3
  176. package/dist/discrete/logic-circuit/preset.mjs +2 -2
  177. package/dist/discrete/monte-carlo/preset.d.mts +1 -1
  178. package/dist/discrete/monte-carlo/preset.mjs +14 -14
  179. package/dist/discrete/monty-hall/preset.mjs +6 -6
  180. package/dist/discrete/outcome-builder/preset.mjs +3 -3
  181. package/dist/discrete/pascal/preset.mjs +37 -7
  182. package/dist/discrete/rules.d.mts +20 -0
  183. package/dist/discrete/rules.mjs +264 -0
  184. package/dist/discrete/sample-space/preset.mjs +4 -4
  185. package/dist/discrete/selection/preset.mjs +7 -13
  186. package/dist/discrete/truth-table/preset.mjs +32 -9
  187. package/dist/discrete/venn/preset.mjs +71 -48
  188. package/dist/geography/cycle-lab/preset.mjs +17 -10
  189. package/dist/geography/cycles.d.mts +3 -3
  190. package/dist/geography/cycles.mjs +3 -3
  191. package/dist/geometry/board/preset.d.mts +2 -0
  192. package/dist/geometry/board/preset.mjs +11 -15
  193. package/dist/geometry/builder.mjs +3 -3
  194. package/dist/ict/number-systems/base-odometer.mjs +4 -4
  195. package/dist/ict/number-systems/bit-grouper.d.mts +1 -1
  196. package/dist/ict/number-systems/bit-grouper.mjs +4 -4
  197. package/dist/ict/number-systems/place-value-dial.d.mts +1 -1
  198. package/dist/ict/number-systems/place-value-dial.mjs +3 -3
  199. package/dist/ict/number-systems/wheel.d.mts +3 -3
  200. package/dist/ict/number-systems/wheel.mjs +4 -4
  201. package/dist/kit/annotate.mjs +3 -3
  202. package/dist/kit/answer-check.d.mts +2 -2
  203. package/dist/kit/answer-check.mjs +34 -6
  204. package/dist/kit/ask.d.mts +19 -0
  205. package/dist/kit/ask.mjs +46 -0
  206. package/dist/kit/bar-strip.mjs +53 -0
  207. package/dist/kit/calc.d.mts +33 -0
  208. package/dist/kit/calc.mjs +27 -0
  209. package/dist/kit/carrier-engine.mjs +147 -0
  210. package/dist/kit/clue-scene.d.mts +86 -0
  211. package/dist/kit/clue-scene.mjs +424 -0
  212. package/dist/kit/cluster.d.mts +30 -0
  213. package/dist/kit/cluster.mjs +81 -0
  214. package/dist/kit/controls.mjs +11 -5
  215. package/dist/kit/coords.d.mts +88 -0
  216. package/dist/kit/coords.mjs +192 -0
  217. package/dist/kit/data-scene.d.mts +27 -0
  218. package/dist/kit/data-scene.mjs +199 -0
  219. package/dist/kit/diagram.mjs +111 -50
  220. package/dist/kit/electronics.mjs +552 -60
  221. package/dist/kit/expr-analysis.d.mts +18 -6
  222. package/dist/kit/expr-analysis.mjs +82 -28
  223. package/dist/kit/frame.d.mts +3 -3
  224. package/dist/kit/frame.mjs +25 -6
  225. package/dist/kit/gameshow.mjs +2 -2
  226. package/dist/kit/index.d.mts +14 -2
  227. package/dist/kit/index.mjs +13 -1
  228. package/dist/kit/logic-gates.mjs +246 -47
  229. package/dist/kit/palette.mjs +26 -0
  230. package/dist/kit/pedagogy.d.mts +4 -4
  231. package/dist/kit/pedagogy.mjs +21 -17
  232. package/dist/kit/play.d.mts +1 -1
  233. package/dist/kit/play.mjs +3 -3
  234. package/dist/kit/predict.d.mts +55 -0
  235. package/dist/kit/predict.mjs +146 -0
  236. package/dist/kit/receipt.d.mts +29 -0
  237. package/dist/kit/receipt.mjs +94 -0
  238. package/dist/kit/rich.mjs +2 -2
  239. package/dist/kit/rule.d.mts +59 -0
  240. package/dist/kit/rule.mjs +215 -0
  241. package/dist/kit/scale.mjs +1 -1
  242. package/dist/kit/scene-library.d.mts +22 -0
  243. package/dist/kit/scene-library.mjs +311 -0
  244. package/dist/kit/scene-studio.d.mts +14 -0
  245. package/dist/kit/scene-studio.mjs +338 -0
  246. package/dist/kit/scenes.d.mts +31 -0
  247. package/dist/kit/scenes.mjs +569 -0
  248. package/dist/kit/slot-fill.d.mts +61 -0
  249. package/dist/kit/slot-fill.mjs +207 -0
  250. package/dist/kit/solve.d.mts +21 -0
  251. package/dist/kit/solve.mjs +75 -0
  252. package/dist/kit/space.mjs +5 -5
  253. package/dist/kit/steps.mjs +2 -2
  254. package/dist/kit/vessel.d.mts +69 -0
  255. package/dist/kit/vessel.mjs +191 -0
  256. package/dist/language/agreement/preset.mjs +2 -2
  257. package/dist/language/article-lens/preset.d.mts +1 -1
  258. package/dist/language/article-lens/preset.mjs +8 -8
  259. package/dist/language/deck.d.mts +3 -3
  260. package/dist/language/deck.mjs +1 -1
  261. package/dist/language/preposition-scene/preset.d.mts +2 -2
  262. package/dist/language/preposition-scene/preset.mjs +5 -5
  263. package/dist/language/sentence-builder/preset.mjs +5 -5
  264. package/dist/language/transform/preset.d.mts +2 -2
  265. package/dist/language/transform/preset.mjs +5 -5
  266. package/dist/language/ui.d.mts +3 -3
  267. package/dist/language/ui.mjs +4 -4
  268. package/dist/language/word-match/preset.mjs +3 -3
  269. package/dist/logic/LogicBuildLab.d.mts +22 -0
  270. package/dist/logic/LogicBuildLab.mjs +170 -0
  271. package/dist/logic/LogicEditScene.d.mts +31 -0
  272. package/dist/logic/LogicEditScene.mjs +276 -0
  273. package/dist/logic/LogicEditor.d.mts +14 -0
  274. package/dist/logic/LogicEditor.mjs +413 -0
  275. package/dist/logic/LogicScene.d.mts +32 -0
  276. package/dist/logic/LogicScene.mjs +277 -0
  277. package/dist/logic/contract.d.mts +72 -0
  278. package/dist/logic/display.d.mts +24 -0
  279. package/dist/logic/display.mjs +127 -0
  280. package/dist/logic/edit-ops.d.mts +44 -0
  281. package/dist/logic/edit-ops.mjs +177 -0
  282. package/dist/logic/evaluate.d.mts +11 -0
  283. package/dist/logic/evaluate.mjs +93 -0
  284. package/dist/logic/gates.d.mts +10 -0
  285. package/dist/logic/gates.mjs +73 -0
  286. package/dist/logic/index.d.mts +14 -0
  287. package/dist/logic/index.mjs +13 -0
  288. package/dist/logic/lab.d.mts +32 -0
  289. package/dist/logic/lab.mjs +160 -0
  290. package/dist/logic/presets.d.mts +12 -0
  291. package/dist/logic/presets.mjs +241 -0
  292. package/dist/logic/registry.d.mts +9 -0
  293. package/dist/logic/registry.mjs +15 -0
  294. package/dist/math/area-model/preset.mjs +70 -44
  295. package/dist/math/balance-algebra/preset.mjs +14 -5
  296. package/dist/math/broken-tree/index.d.mts +1 -0
  297. package/dist/math/broken-tree/preset.d.mts +26 -0
  298. package/dist/math/broken-tree/preset.mjs +435 -0
  299. package/dist/math/circle/index.d.mts +1 -0
  300. package/dist/math/circle/preset.d.mts +44 -0
  301. package/dist/math/circle/preset.mjs +198 -0
  302. package/dist/math/complex/core.d.mts +93 -0
  303. package/dist/math/complex/core.mjs +239 -0
  304. package/dist/math/complex/index.d.mts +3 -0
  305. package/dist/math/complex/preset.d.mts +31 -0
  306. package/dist/math/complex/preset.mjs +377 -0
  307. package/dist/math/complex/rules.d.mts +6 -0
  308. package/dist/math/complex/rules.mjs +121 -0
  309. package/dist/math/conic/index.d.mts +1 -0
  310. package/dist/math/conic/preset.d.mts +30 -0
  311. package/dist/math/conic/preset.mjs +334 -0
  312. package/dist/math/derivation.mjs +5 -5
  313. package/dist/math/derivative-explorer/preset.mjs +5 -5
  314. package/dist/math/domain-range/index.d.mts +1 -0
  315. package/dist/math/domain-range/preset.d.mts +33 -0
  316. package/dist/math/domain-range/preset.mjs +313 -0
  317. package/dist/math/fraction-bar/index.d.mts +1 -0
  318. package/dist/math/fraction-bar/preset.d.mts +27 -0
  319. package/dist/math/fraction-bar/preset.mjs +197 -0
  320. package/dist/math/function-machine/preset.mjs +2 -2
  321. package/dist/math/gradient-descent.mjs +6 -6
  322. package/dist/math/grapher/preset.d.mts +1 -1
  323. package/dist/math/grapher/preset.mjs +4 -4
  324. package/dist/math/harmonic-form/preset.mjs +6 -6
  325. package/dist/math/index.d.mts +27 -2
  326. package/dist/math/index.mjs +27 -2
  327. package/dist/math/integral-explorer/preset.mjs +2 -2
  328. package/dist/math/interactive/preset.mjs +3 -3
  329. package/dist/math/limit-explorer/preset.mjs +4 -4
  330. package/dist/math/linear-model/index.d.mts +1 -0
  331. package/dist/math/linear-model/preset.d.mts +53 -0
  332. package/dist/math/linear-model/preset.mjs +164 -0
  333. package/dist/math/linear-system/preset.mjs +4 -4
  334. package/dist/math/mystery-bucket/preset.mjs +6 -6
  335. package/dist/math/number-line/preset.mjs +3 -2
  336. package/dist/math/parabola/preset.mjs +4 -3
  337. package/dist/math/pattern/preset.mjs +7 -13
  338. package/dist/math/percent-bar/index.d.mts +1 -0
  339. package/dist/math/percent-bar/preset.d.mts +37 -0
  340. package/dist/math/percent-bar/preset.mjs +275 -0
  341. package/dist/math/poly/core.d.mts +50 -0
  342. package/dist/math/poly/core.mjs +268 -0
  343. package/dist/math/poly/index.d.mts +3 -0
  344. package/dist/math/poly/preset.d.mts +23 -0
  345. package/dist/math/poly/preset.mjs +141 -0
  346. package/dist/math/poly/steps.d.mts +10 -0
  347. package/dist/math/poly/steps.mjs +99 -0
  348. package/dist/math/rate-machine/index.d.mts +1 -0
  349. package/dist/math/rate-machine/preset.d.mts +35 -0
  350. package/dist/math/rate-machine/preset.mjs +281 -0
  351. package/dist/math/ratio-share/index.d.mts +1 -0
  352. package/dist/math/ratio-share/preset.d.mts +24 -0
  353. package/dist/math/ratio-share/preset.mjs +204 -0
  354. package/dist/math/receipt/index.d.mts +1 -0
  355. package/dist/math/receipt/preset.d.mts +22 -0
  356. package/dist/math/receipt/preset.mjs +137 -0
  357. package/dist/math/sequence-predict/index.d.mts +1 -0
  358. package/dist/math/sequence-predict/preset.d.mts +34 -0
  359. package/dist/math/sequence-predict/preset.mjs +130 -0
  360. package/dist/math/straight-line/index.d.mts +1 -0
  361. package/dist/math/straight-line/preset.d.mts +37 -0
  362. package/dist/math/straight-line/preset.mjs +374 -0
  363. package/dist/math/system-solve/index.d.mts +1 -0
  364. package/dist/math/system-solve/preset.d.mts +21 -0
  365. package/dist/math/system-solve/preset.mjs +227 -0
  366. package/dist/math/transform/index.d.mts +1 -0
  367. package/dist/math/transform/preset.d.mts +41 -0
  368. package/dist/math/transform/preset.mjs +343 -0
  369. package/dist/math/triangle-trig/preset.mjs +12 -9
  370. package/dist/math/trig/core.d.mts +37 -0
  371. package/dist/math/trig/core.mjs +150 -0
  372. package/dist/math/trig/diagrams.d.mts +1 -0
  373. package/dist/math/trig/diagrams.mjs +321 -0
  374. package/dist/math/trig/index.d.mts +3 -0
  375. package/dist/math/trig/preset.d.mts +25 -0
  376. package/dist/math/trig/preset.mjs +260 -0
  377. package/dist/math/trig/rules.d.mts +6 -0
  378. package/dist/math/trig/rules.mjs +159 -0
  379. package/dist/math/trig-explorer.mjs +4 -4
  380. package/dist/ml/boundary/preset.mjs +8 -3
  381. package/dist/ml/classifier/preset.mjs +31 -6
  382. package/dist/ml/kmeans/preset.mjs +4 -4
  383. package/dist/ml/knn/preset.mjs +47 -12
  384. package/dist/ml/regression/preset.mjs +36 -7
  385. package/dist/physics/atwood/preset.mjs +4 -4
  386. package/dist/physics/bullet-walls/preset.d.mts +1 -1
  387. package/dist/physics/bullet-walls/preset.mjs +7 -7
  388. package/dist/physics/carnot/preset.mjs +6 -6
  389. package/dist/physics/circular-motion/preset.mjs +36 -5
  390. package/dist/physics/collision-track/preset.mjs +35 -5
  391. package/dist/physics/efficiency/preset.d.mts +2 -2
  392. package/dist/physics/efficiency/preset.mjs +5 -5
  393. package/dist/physics/electric-field/preset.mjs +32 -23
  394. package/dist/physics/electric-flux/index.d.mts +1 -0
  395. package/dist/physics/electric-flux/preset.d.mts +29 -0
  396. package/dist/physics/electric-flux/preset.mjs +264 -0
  397. package/dist/physics/energy-skate/preset.mjs +5 -5
  398. package/dist/physics/entropy/preset.mjs +7 -7
  399. package/dist/physics/expansion/preset.mjs +13 -13
  400. package/dist/physics/exponential/asset.mjs +1 -1
  401. package/dist/physics/exponential/preset.mjs +4 -4
  402. package/dist/physics/gas-process/preset.mjs +3 -3
  403. package/dist/physics/gauss-law/index.d.mts +1 -0
  404. package/dist/physics/gauss-law/preset.d.mts +20 -0
  405. package/dist/physics/gauss-law/preset.mjs +286 -0
  406. package/dist/physics/gravitation/preset.mjs +7 -7
  407. package/dist/physics/gravity-drop.mjs +4 -4
  408. package/dist/physics/heat-transfer/preset.d.mts +1 -1
  409. package/dist/physics/heat-transfer/preset.mjs +10 -10
  410. package/dist/physics/impulse/preset.mjs +5 -5
  411. package/dist/physics/index.d.mts +4 -1
  412. package/dist/physics/index.mjs +4 -1
  413. package/dist/physics/kepler/preset.mjs +4 -4
  414. package/dist/physics/lever/preset.mjs +3 -3
  415. package/dist/physics/lorentz/preset.mjs +11 -11
  416. package/dist/physics/magnetism/preset.mjs +3 -3
  417. package/dist/physics/optics/preset.mjs +2 -2
  418. package/dist/physics/orbit-lab.mjs +5 -5
  419. package/dist/physics/projectile-lab.mjs +4 -4
  420. package/dist/physics/rain-relative/preset.mjs +5 -5
  421. package/dist/physics/ramp-forces/preset.mjs +5 -5
  422. package/dist/physics/river-boat.mjs +6 -6
  423. package/dist/physics/shm/preset.mjs +9 -9
  424. package/dist/physics/stopping-distance/preset.mjs +3 -3
  425. package/dist/physics/temperature-scales/preset.mjs +105 -116
  426. package/dist/physics/terminal-velocity/preset.mjs +5 -5
  427. package/dist/physics/thermal/preset.mjs +5 -5
  428. package/dist/physics/vector-board/preset.mjs +7 -6
  429. package/dist/physics/vector-scene.mjs +2 -2
  430. package/dist/physics/vector-types/preset.mjs +37 -3
  431. package/dist/physics/water-density/preset.mjs +12 -12
  432. package/dist/physics/waves/doppler.mjs +2 -2
  433. package/dist/physics/waves/preset.mjs +4 -4
  434. package/dist/physics/waves/ripple.mjs +6 -6
  435. package/dist/physics/waves/string.mjs +5 -5
  436. package/dist/physics/work-energy/preset.mjs +4 -4
  437. package/dist/physics/work-potential/index.d.mts +1 -0
  438. package/dist/physics/work-potential/preset.d.mts +20 -0
  439. package/dist/physics/work-potential/preset.mjs +276 -0
  440. package/dist/schemas/index.d.mts +6 -6
  441. package/dist/schemas/index.mjs +3 -3
  442. package/dist/statistics/center-spread/preset.mjs +3 -3
  443. package/dist/statistics/core/descriptive.d.mts +2 -2
  444. package/dist/statistics/core/descriptive.mjs +2 -2
  445. package/dist/statistics/core/normal.d.mts +3 -3
  446. package/dist/statistics/core/normal.mjs +3 -3
  447. package/dist/statistics/core/sequences.d.mts +1 -1
  448. package/dist/statistics/galton/preset.mjs +2 -2
  449. package/dist/statistics/histogram/preset.mjs +6 -6
  450. package/dist/statistics/normal/preset.mjs +2 -2
  451. package/dist/statistics/sampling/preset.mjs +4 -4
  452. package/dist/statistics/sequence/preset.mjs +58 -15
  453. package/dist/statistics/z-table/preset.mjs +17 -4
  454. package/package.json +11 -3
  455. package/styles.css +4 -1
@@ -11,9 +11,9 @@ import { useControlSurface } from "@classytic/stage";
11
11
 
12
12
  //#region src/discrete/counting-slots/preset.tsx
13
13
  /**
14
- * CountingSlotsLab — counting made concrete, the FUN way (the tree drowns past ~8
14
+ * CountingSlotsLab, counting made concrete, the FUN way (the tree drowns past ~8
15
15
  * leaves; this scales and reads friendly). The multiplication principle as filling
16
- * a row of POSITIONS: fill slot 1 from the whole pool, slot 2 from what's left, … —
16
+ * a row of POSITIONS: fill slot 1 from the whole pool, slot 2 from what's left, … ,
17
17
  * the pool shrinks, the product builds (4 × 3 × 2). It covers the whole family from
18
18
  * one model:
19
19
  * • arrange (order matters) → permutations nPr (k = n ⇒ factorial n!)
@@ -139,7 +139,7 @@ function CountingSlotsLab({ items = [
139
139
  /* @__PURE__ */ jsxs("div", { children: [/* @__PURE__ */ jsxs("p", {
140
140
  className: "lab-field-label",
141
141
  children: [
142
- "the pool — ",
142
+ "the pool, ",
143
143
  n,
144
144
  " to pick from",
145
145
  !repl && ", each used once"
@@ -176,7 +176,7 @@ function CountingSlotsLab({ items = [
176
176
  " position",
177
177
  k === 1 ? "" : "s",
178
178
  " to fill ",
179
- mode === "choose" ? "(a group — order won't matter)" : "(in order)"
179
+ mode === "choose" ? "(a group, order won't matter)" : "(in order)"
180
180
  ]
181
181
  }), /* @__PURE__ */ jsx("div", {
182
182
  style: {
@@ -244,7 +244,7 @@ function CountingSlotsLab({ items = [
244
244
  fontWeight: 500,
245
245
  fontSize: 14
246
246
  },
247
- children: "Fill the first slot — how many choices?"
247
+ children: "Fill the first slot, how many choices?"
248
248
  }) : /* @__PURE__ */ jsxs(Fragment$1, { children: [
249
249
  /* @__PURE__ */ jsx(Tex$1, { tex: Array.from({ length: step }, (_, i) => choices(i)).join(" \\times ") }),
250
250
  step < k && /* @__PURE__ */ jsxs("span", {
@@ -277,7 +277,7 @@ function CountingSlotsLab({ items = [
277
277
  children: [
278
278
  /* @__PURE__ */ jsx("p", {
279
279
  className: "lab-field-label",
280
- children: "order doesn't matter — these are all the SAME group"
280
+ children: "order doesn't matter, these are all the SAME group"
281
281
  }),
282
282
  factorial(k) <= 8 ? /* @__PURE__ */ jsxs("div", {
283
283
  style: {
@@ -324,7 +324,7 @@ function CountingSlotsLab({ items = [
324
324
  k,
325
325
  "! = ",
326
326
  factorial(k),
327
- " ways — all the same selection."
327
+ " ways, all the same selection."
328
328
  ]
329
329
  }),
330
330
  /* @__PURE__ */ jsxs("p", {
@@ -460,7 +460,7 @@ function CountingSlotsLab({ items = [
460
460
  }),
461
461
  checked && /* @__PURE__ */ jsx(StatusPill, {
462
462
  ok: guess === total,
463
- children: guess === total ? "✓ right!" : "not yet — fill the slots"
463
+ children: guess === total ? "✓ right!" : "not yet, fill the slots"
464
464
  })
465
465
  ] })] })] }),
466
466
  controls: /* @__PURE__ */ jsxs(ControlBar, { children: [
@@ -3,7 +3,7 @@
3
3
  import { Tex as Tex$1 } from "../../core/tex.mjs";
4
4
  import { CheckButton, Chip, StatusPill, Stepper } from "../../kit/controls.mjs";
5
5
  import { ControlBar, Field, LabFrame } from "../../kit/frame.mjs";
6
- import { HintLadder, RevealSolution, useCheckpoint, useHints } from "../../kit/pedagogy.mjs";
6
+ import { ChallengeCard, HintLadder, RevealSolution, useChallenge, useCheckpoint, useHints } from "../../kit/pedagogy.mjs";
7
7
  import { factorial } from "../core/combinatorics.mjs";
8
8
  import { Fragment, useMemo, useState } from "react";
9
9
  import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
@@ -11,7 +11,7 @@ import { Dot, Label, Segment, Stage, useControlSurface, useLearner } from "@clas
11
11
 
12
12
  //#region src/discrete/counting-tree/preset.tsx
13
13
  /**
14
- * CountingTree — the GENERAL sequential-counting + probability-tree tool. One
14
+ * CountingTree, the GENERAL sequential-counting + probability-tree tool. One
15
15
  * model covers the multiplication principle, permutations (draw without
16
16
  * replacement → n·(n−1)·…), with-replacement counts (nᵏ), the
17
17
  * permutation→combination collapse (÷k!), AND probability trees (multiply the
@@ -20,9 +20,9 @@ import { Dot, Label, Segment, Stage, useControlSurface, useLearner } from "@clas
20
20
  * an agent narrates and never invents.
21
21
  *
22
22
  * Two authoring forms:
23
- * • `stages` — explicit uniform-per-stage branches (general multiplication /
23
+ * • `stages` , explicit uniform-per-stage branches (general multiplication /
24
24
  * independent probability, e.g. flip a coin 3×).
25
- * • `pool`+`draws`+`replacement` — draw k items from a pool; replacement off
25
+ * • `pool`+`draws`+`replacement`, draw k items from a pool; replacement off
26
26
  * ⇒ a permutation tree (5·4·3), on ⇒ nᵏ.
27
27
  */
28
28
  const MAX_LEAVES = 28;
@@ -141,9 +141,61 @@ function CountingTreeLab({ stages, pool, draws = 2, replacement = false, mode =
141
141
  stages
142
142
  ]);
143
143
  const target = ask === "unordered" ? unorderedTotal : orderedTotal;
144
+ const predictQ = useMemo(() => {
145
+ if (mode !== "count") return [];
146
+ const n = pool ? pool.length : 0;
147
+ const withRepl = pool ? Math.pow(n, draws) : 0;
148
+ const kFact = factorial(k);
149
+ const addTrap = pool ? n * draws : 0;
150
+ const prompt = pool ? `Filling ${draws} ranked ${draws === 1 ? "spot" : "spots"} from ${n} ${n === 1 ? "option" : "options"}, ${replacement ? "reuse allowed" : "with no repeats"} — how many ${ask === "unordered" ? "unordered selections" : "ordered outcomes"} are there?` : `Working down ${k} ${k === 1 ? "stage" : "stages"} of choices, how many ${ask === "unordered" ? "unordered selections" : "ordered paths"} does the tree end with?`;
151
+ const distractors = [
152
+ withRepl,
153
+ kFact,
154
+ addTrap,
155
+ target + 1,
156
+ target * 2
157
+ ].filter((v) => Number.isFinite(v) && v > 0 && v !== target);
158
+ const seen = new Set([target]);
159
+ const choiceVals = [target];
160
+ for (const v of distractors) {
161
+ if (!seen.has(v)) {
162
+ seen.add(v);
163
+ choiceVals.push(v);
164
+ }
165
+ if (choiceVals.length >= 3) break;
166
+ }
167
+ choiceVals.sort((a, b) => a - b);
168
+ return [{
169
+ id: "predict-count",
170
+ prompt,
171
+ choices: choiceVals.map((v) => ({
172
+ value: String(v),
173
+ label: String(v)
174
+ })),
175
+ answer: String(target),
176
+ explain: /* @__PURE__ */ jsxs(Fragment$1, { children: [
177
+ "Multiply a ",
178
+ /* @__PURE__ */ jsx("b", { children: "shrinking pool" }),
179
+ ": ",
180
+ /* @__PURE__ */ jsx(Tex$1, { tex: `${factorStr}${ask === "unordered" ? ` \\div ${k}!` : ""} = ${target}` }),
181
+ "."
182
+ ] })
183
+ }];
184
+ }, [
185
+ mode,
186
+ pool,
187
+ draws,
188
+ replacement,
189
+ ask,
190
+ k,
191
+ target,
192
+ orderedTotal,
193
+ factorStr
194
+ ]);
195
+ const ch = useChallenge(predictQ);
144
196
  const solved = mode === "count" ? checked && guess === target && !peeked : false;
145
197
  useCheckpoint({
146
- solved,
198
+ solved: solved || ch.allCorrect,
147
199
  activity: `counting-tree:${title}`,
148
200
  hintsUsed: hints.count
149
201
  });
@@ -260,7 +312,7 @@ function CountingTreeLab({ stages, pool, draws = 2, replacement = false, mode =
260
312
  children: [
261
313
  "Tree truncated at ",
262
314
  MAX_LEAVES,
263
- " paths — shrink the pool/draws to see it all."
315
+ " paths, shrink the pool/draws to see it all."
264
316
  ]
265
317
  })] });
266
318
  return /* @__PURE__ */ jsx(LabFrame, {
@@ -286,7 +338,7 @@ function CountingTreeLab({ stages, pool, draws = 2, replacement = false, mode =
286
338
  }),
287
339
  checked && /* @__PURE__ */ jsx(StatusPill, {
288
340
  ok: guess === target,
289
- children: guess === target ? `✓ ${target}` : `Not yet — count the branches`
341
+ children: guess === target ? `✓ ${target}` : `Not yet, count the branches`
290
342
  }),
291
343
  built.leafPaths.length <= 16 && /* @__PURE__ */ jsxs(Field, {
292
344
  label: "Trace each path",
@@ -326,6 +378,11 @@ function CountingTreeLab({ stages, pool, draws = 2, replacement = false, mode =
326
378
  ]
327
379
  })] }),
328
380
  footer: /* @__PURE__ */ jsxs(Fragment$1, { children: [
381
+ predictQ.length > 0 && /* @__PURE__ */ jsx(ChallengeCard, {
382
+ questions: predictQ,
383
+ state: ch,
384
+ title: "Predict first"
385
+ }),
329
386
  mode === "count" && checked && /* @__PURE__ */ jsxs("p", {
330
387
  className: "lab-prompt",
331
388
  children: [
@@ -348,7 +405,7 @@ function CountingTreeLab({ stages, pool, draws = 2, replacement = false, mode =
348
405
  solution: /* @__PURE__ */ jsxs(Fragment$1, { children: [
349
406
  "The count is ",
350
407
  /* @__PURE__ */ jsx("b", { children: target }),
351
- " — ",
408
+ ", ",
352
409
  /* @__PURE__ */ jsx(Tex$1, { tex: `${factorStr}${ask === "unordered" ? ` \\div ${k}!` : ""}` }),
353
410
  "."
354
411
  ] }),
@@ -4,33 +4,27 @@ import { mulberry32 } from "../../core/rng.mjs";
4
4
  import { Tex as Tex$1 } from "../../core/tex.mjs";
5
5
  import { Chip, Slider, Stepper } from "../../kit/controls.mjs";
6
6
  import { Callout, ControlBar, Field, LabFrame } from "../../kit/frame.mjs";
7
- import { HintLadder, useHints } from "../../kit/pedagogy.mjs";
7
+ import { HintLadder, useCheckpoint, useHints } from "../../kit/pedagogy.mjs";
8
8
  import { expectedValue } from "../core/probability.mjs";
9
+ import { CATEGORICAL } from "../../kit/palette.mjs";
9
10
  import { useMemo, useRef, useState } from "react";
10
11
  import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
11
12
  import { useControlSurface } from "@classytic/stage";
12
13
 
13
14
  //#region src/discrete/expected-value/preset.tsx
14
15
  /**
15
- * ExpectedValueLab — E[X] = Σ value·prob, made physical: each outcome is a WEIGHT
16
+ * ExpectedValueLab, E[X] = Σ value·prob, made physical: each outcome is a WEIGHT
16
17
  * (heavier = more likely) sitting at its value on a number line, and the expected
17
18
  * value is exactly where they BALANCE (the long-run average payout). Framed as "is
18
19
  * this game worth it?": a cost marker shows the house edge when E[X] < cost. Then
19
20
  * SPIN it many times and watch the running average settle onto E[X] (the law of
20
- * large numbers — the average is the expectation, earned).
21
+ * large numbers, the average is the expectation, earned).
21
22
  *
22
23
  * Drag the probabilities/values; the fulcrum slides. Kernel = expectedValue; seeded
23
24
  * rng for replayable spins.
24
25
  */
25
26
  const W = 520, H = 210, ML = 30, MR = 20, AXIS = 138;
26
- const PAL = [
27
- "#1c7ed6",
28
- "#2f9e44",
29
- "#e8590c",
30
- "#9c36b5",
31
- "#0ca678",
32
- "#e03131"
33
- ];
27
+ const PAL = CATEGORICAL;
34
28
  function ExpectedValueLab({ outcomes = [
35
29
  {
36
30
  label: "lose",
@@ -47,7 +41,7 @@ function ExpectedValueLab({ outcomes = [
47
41
  value: 50,
48
42
  prob: .05
49
43
  }
50
- ], cost = 5, title = "Expected value — is the game fair?", prompt, objectives, hints: hintList, controlId }) {
44
+ ], cost = 5, title = "Expected value: is the game fair?", prompt, objectives, hints: hintList, controlId }) {
51
45
  const [probs, setProbs] = useState(outcomes.map((o) => o.prob));
52
46
  const [vals, setVals] = useState(outcomes.map((o) => o.value));
53
47
  const [plays, setPlays] = useState(0);
@@ -63,6 +57,12 @@ function ExpectedValueLab({ outcomes = [
63
57
  const lo = Math.min(0, ...vals), hi = Math.max(...vals, cost) * 1.12 || 1;
64
58
  const xOf = (v) => ML + (v - lo) / (hi - lo) * (W - ML - MR);
65
59
  const avg = plays ? total / plays : null;
60
+ const tol = Math.max(.5, Math.abs(ev) * .05);
61
+ useCheckpoint({
62
+ solved: plays >= 30 && avg != null && Math.abs(avg - ev) <= tol,
63
+ activity: `expected-value:${title}`,
64
+ hintsUsed: hints?.count ?? 0
65
+ });
66
66
  const spin = (times) => {
67
67
  let t = total, c = plays;
68
68
  for (let s = 0; s < times; s++) {
@@ -281,7 +281,7 @@ function ExpectedValueLab({ outcomes = [
281
281
  /* @__PURE__ */ jsxs("div", { children: [/* @__PURE__ */ jsx("p", {
282
282
  className: "lab-prompt",
283
283
  style: { fontSize: 13 },
284
- children: "Play it for real — the average payout homes in on E[X]."
284
+ children: "Play it for real, the average payout homes in on E[X]."
285
285
  }), /* @__PURE__ */ jsxs(ControlBar, { children: [
286
286
  /* @__PURE__ */ jsx(Chip, {
287
287
  selected: false,
@@ -3,7 +3,7 @@
3
3
  import { Tex as Tex$1 } from "../../core/tex.mjs";
4
4
  import { Slider } from "../../kit/controls.mjs";
5
5
  import { Callout, ControlBar, Field, LabFrame } from "../../kit/frame.mjs";
6
- import { HintLadder, useHints } from "../../kit/pedagogy.mjs";
6
+ import { ChallengeCard, HintLadder, useChallenge, useCheckpoint, useHints } from "../../kit/pedagogy.mjs";
7
7
  import { nCr } from "../core/combinatorics.mjs";
8
8
  import { useMemo, useState } from "react";
9
9
  import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
@@ -11,12 +11,12 @@ import { useControlSurface } from "@classytic/stage";
11
11
 
12
12
  //#region src/discrete/hypergeometric/preset.tsx
13
13
  /**
14
- * HypergeometricLab — does it matter whether you put the ball back? Same urn (K
14
+ * HypergeometricLab, does it matter whether you put the ball back? Same urn (K
15
15
  * winners in N), draw n, and compare the two distributions of "how many winners":
16
16
  * • WITH replacement → binomial C(n,k) pᵏ(1−p)ⁿ⁻ᵏ, p = K/N (draws independent)
17
17
  * • WITHOUT → hypergeometric C(K,k)·C(N−K,n−k) / C(N,n)
18
18
  * Drawn as paired bars. The lesson lives in the difference: without replacement is
19
- * NARROWER (each draw shifts the odds — a finite-population correction (N−n)/(N−1)),
19
+ * NARROWER (each draw shifts the odds, a finite-population correction (N−n)/(N−1)),
20
20
  * but as the population N grows huge the two distributions merge (taking one ball
21
21
  * barely changes the mix). Both share the same mean n·K/N.
22
22
  *
@@ -26,12 +26,37 @@ const W = 540, H = 300, ML = 30, MR = 14, MT = 16, MB = 34;
26
26
  const PW = W - ML - MR, PH = H - MT - MB;
27
27
  const BIN = "var(--stage-accent)", HYP = "var(--stage-warn)";
28
28
  const f3 = (x) => x < 5e-4 && x > 0 ? x.toExponential(1) : x.toFixed(3);
29
+ const Q = [{
30
+ id: "narrower",
31
+ prompt: "Same urn, draw n. One version puts each ball BACK (independent draws), the other does NOT. Which distribution of 'number of winners' is NARROWER (less spread)?",
32
+ choices: [
33
+ {
34
+ value: "without",
35
+ label: "WITHOUT replacement (hypergeometric)"
36
+ },
37
+ {
38
+ value: "with",
39
+ label: "WITH replacement (binomial)"
40
+ },
41
+ {
42
+ value: "same",
43
+ label: "identical spread"
44
+ }
45
+ ],
46
+ answer: "without",
47
+ explain: "Without replacement is narrower. Each draw removes a ball and shifts the odds for the next, so draws are negatively correlated. That shrinks the variance by the finite-population correction (N−n)/(N−1) < 1: varHyp = varBin · (N−n)/(N−1). The means stay identical at n·K/N; only the spread differs, and the two converge as N grows huge."
48
+ }];
29
49
  function HypergeometricLab({ N: N0 = 10, K: K0 = 4, n: n0 = 3, title = "With vs without replacement", prompt, objectives, hints: hintList, controlId }) {
30
50
  const [N, setN] = useState(N0);
31
51
  const [K, setK] = useState(K0);
32
52
  const [n, setN_] = useState(n0);
33
53
  const [sel, setSel] = useState(null);
34
54
  const hints = useHints(hintList);
55
+ const ch = useChallenge(Q);
56
+ useCheckpoint({
57
+ solved: ch.allCorrect,
58
+ activity: "hypergeometric:predict"
59
+ });
35
60
  const Kc = Math.min(K, N), nc = Math.min(n, N);
36
61
  const p = Kc / N;
37
62
  const bin = useMemo(() => Array.from({ length: nc + 1 }, (_, k) => nCr(nc, k) * p ** k * (1 - p) ** (nc - k)), [nc, p]);
@@ -310,18 +335,26 @@ function HypergeometricLab({ N: N0 = 10, K: K0 = 4, n: n0 = 3, title = "With vs
310
335
  })
311
336
  })
312
337
  ] }),
313
- footer: /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsxs("p", {
314
- className: "lab-prompt",
315
- style: {
316
- fontSize: 12.5,
317
- color: "var(--stage-muted)"
318
- },
319
- children: [
320
- "Without replacement is narrower by the factor (N−n)/(N−1) = ",
321
- ((N - nc) / (N - 1 || 1)).toFixed(2),
322
- ". Push N up (with K/N fixed) and the bars converge — for a huge population, taking one out barely changes the odds."
323
- ]
324
- }), /* @__PURE__ */ jsx(HintLadder, { hints })] }),
338
+ footer: /* @__PURE__ */ jsxs(Fragment$1, { children: [
339
+ /* @__PURE__ */ jsx(ChallengeCard, {
340
+ questions: Q,
341
+ state: ch,
342
+ title: "Predict first"
343
+ }),
344
+ /* @__PURE__ */ jsxs("p", {
345
+ className: "lab-prompt",
346
+ style: {
347
+ fontSize: 12.5,
348
+ color: "var(--stage-muted)"
349
+ },
350
+ children: [
351
+ "Without replacement is narrower by the factor (N−n)/(N−1) = ",
352
+ ((N - nc) / (N - 1 || 1)).toFixed(2),
353
+ ". Push N up (with K/N fixed) and the bars converge, for a huge population, taking one out barely changes the odds."
354
+ ]
355
+ }),
356
+ /* @__PURE__ */ jsx(HintLadder, { hints })
357
+ ] }),
325
358
  children: figure
326
359
  });
327
360
  }
@@ -1,9 +1,10 @@
1
- import { binomial, factorial, gcd, lcm, multinomial, nCr, nPr, starsAndBars } from "./core/combinatorics.mjs";
1
+ import { binomial, circularPermutations, combinationsWithRepetition, factorial, gcd, lcm, multichoose, multinomial, nCr, nPr, permutationsWithRepetition, ruleOfProduct, ruleOfSum, starsAndBars } from "./core/combinatorics.mjs";
2
2
  import { Elem, cartesian, complement, difference, intersection, isSubset, powerset, setEqual, symmetricDifference, union } from "./core/sets.mjs";
3
3
  import { IEResult, IETerm, inclusionExclusion } from "./core/inclusionExclusion.mjs";
4
4
  import { atLeastOne, bayes, complement as complement$1, conditional, expectedValue, independent, probability } from "./core/probability.mjs";
5
5
  import { guaranteedOccupancy, minForOccupancy, minToGuaranteePair } from "./core/pigeonhole.mjs";
6
6
  import { Rng, mulberry32, randInt, sample, shuffle } from "../core/rng.mjs";
7
+ import { COMBINATION_RULE, COUNTING_RULES, FACTORIAL_RULE, PERMUTATION_RULE, PERM_REP_RULE, PRODUCT_RULE, SUM_RULE, explainFactorial, explainNCr, explainNPr, explainPermWithRep, explainProduct, explainSum } from "./rules.mjs";
7
8
  import { TruthTableLab, TruthTableMode, TruthTableProps } from "./truth-table/preset.mjs";
8
9
  import { CountAsk, CountingTreeLab, CountingTreeProps, TreeBranch, TreeStage } from "./counting-tree/preset.mjs";
9
10
  import { VennMode, VennSet, VennSetBoardLab, VennSetBoardProps } from "./venn/preset.mjs";
@@ -13,6 +14,7 @@ import { KMapMode, KMapProps, KarnaughMapLab } from "./karnaugh/preset.mjs";
13
14
  import { ExperimentSpec, MCSeries, MonteCarloLab, MonteCarloProps } from "./monte-carlo/preset.mjs";
14
15
  import { MontyHallLab, MontyHallProps } from "./monty-hall/preset.mjs";
15
16
  import { OutcomeBuilderLab, OutcomeBuilderProps } from "./outcome-builder/preset.mjs";
17
+ import { CombinationStudioLab, CombinationStudioProps, ComboCategory, ComboOption } from "./combination-studio/preset.mjs";
16
18
  import { BayesLab, BayesProps } from "./bayes/preset.mjs";
17
19
  import { LawOfLargeNumbersLab, LlnProps } from "./lln/preset.mjs";
18
20
  import { CountingSlotsLab, CountingSlotsProps, SlotMode } from "./counting-slots/preset.mjs";
@@ -23,4 +25,4 @@ import { BinomialDistributionLab, BinomialProps } from "./binomial/preset.mjs";
23
25
  import { HypergeometricLab, HypergeometricProps } from "./hypergeometric/preset.mjs";
24
26
  import { EVOutcome, ExpectedValueLab, ExpectedValueProps } from "./expected-value/preset.mjs";
25
27
  import { Classification, CompiledLogic, Cube, LNode, LogicResult, Minimization, TruthRow, TruthTable, classify, compileLogic, cubeCovers, cubeOfSelection, cubeTerm, equivalent, evalBool, logicToLatex, minimalCover, minimize, parseLogic, primeImplicants, toCNF, toDNF, truthTable } from "@classytic/stage";
26
- export { type ArrangeItem, ArrangementsLab, type ArrangementsProps, BayesLab, type BayesProps, BinomialDistributionLab, type BinomialProps, BooleanCircuitLab, type BooleanCircuitProps, type CircuitGate, type CircuitInput, type CircuitOutput, type Classification, type Cmp, type CompiledLogic, type CountAsk, CountingSlotsLab, type CountingSlotsProps, CountingTreeLab, type CountingTreeProps, type Cube, type EVOutcome, type Elem, ExpectedValueLab, type ExpectedValueProps, type ExperimentSpec, HypergeometricLab, type HypergeometricProps, type IEResult, type IETerm, type KMapMode, type KMapProps, KarnaughMapLab, type LNode, LawOfLargeNumbersLab, type LlnProps, type LogicResult, type MCSeries, type Minimization, MonteCarloLab, type MonteCarloProps, MontyHallLab, type MontyHallProps, OutcomeBuilderLab, type OutcomeBuilderProps, type PascalProps, PascalTriangleLab, type PascalView, type Reduce, type Rng, type SampleEvent, SampleSpaceBoardLab, type SampleSpaceProps, type SelectionGroup, SelectionLab, type SelectionMode, type SelectionProps, type SlotMode, type TreeBranch, type TreeStage, type TruthRow, type TruthTable, TruthTableLab, type TruthTableMode, type TruthTableProps, type VennMode, type VennSet, VennSetBoardLab, type VennSetBoardProps, atLeastOne, bayes, binomial, cartesian, classify, compileLogic, complement, conditional, cubeCovers, cubeOfSelection, cubeTerm, difference, equivalent, evalBool, expectedValue, factorial, gcd, guaranteedOccupancy, inclusionExclusion, independent, intersection, isSubset, lcm, logicToLatex, minForOccupancy, minToGuaranteePair, minimalCover, minimize, mulberry32, multinomial, nCr, nPr, parseLogic, powerset, primeImplicants, complement$1 as probComplement, probability, randInt, sample, setEqual, shuffle, starsAndBars, symmetricDifference, toCNF, toDNF, truthTable, union };
28
+ export { type ArrangeItem, ArrangementsLab, type ArrangementsProps, BayesLab, type BayesProps, BinomialDistributionLab, type BinomialProps, BooleanCircuitLab, type BooleanCircuitProps, COMBINATION_RULE, COUNTING_RULES, type CircuitGate, type CircuitInput, type CircuitOutput, type Classification, type Cmp, CombinationStudioLab, type CombinationStudioProps, type ComboCategory, type ComboOption, type CompiledLogic, type CountAsk, CountingSlotsLab, type CountingSlotsProps, CountingTreeLab, type CountingTreeProps, type Cube, type EVOutcome, type Elem, ExpectedValueLab, type ExpectedValueProps, type ExperimentSpec, FACTORIAL_RULE, HypergeometricLab, type HypergeometricProps, type IEResult, type IETerm, type KMapMode, type KMapProps, KarnaughMapLab, type LNode, LawOfLargeNumbersLab, type LlnProps, type LogicResult, type MCSeries, type Minimization, MonteCarloLab, type MonteCarloProps, MontyHallLab, type MontyHallProps, OutcomeBuilderLab, type OutcomeBuilderProps, PERMUTATION_RULE, PERM_REP_RULE, PRODUCT_RULE, type PascalProps, PascalTriangleLab, type PascalView, type Reduce, type Rng, SUM_RULE, type SampleEvent, SampleSpaceBoardLab, type SampleSpaceProps, type SelectionGroup, SelectionLab, type SelectionMode, type SelectionProps, type SlotMode, type TreeBranch, type TreeStage, type TruthRow, type TruthTable, TruthTableLab, type TruthTableMode, type TruthTableProps, type VennMode, type VennSet, VennSetBoardLab, type VennSetBoardProps, atLeastOne, bayes, binomial, cartesian, circularPermutations, classify, combinationsWithRepetition, compileLogic, complement, conditional, cubeCovers, cubeOfSelection, cubeTerm, difference, equivalent, evalBool, expectedValue, explainFactorial, explainNCr, explainNPr, explainPermWithRep, explainProduct, explainSum, factorial, gcd, guaranteedOccupancy, inclusionExclusion, independent, intersection, isSubset, lcm, logicToLatex, minForOccupancy, minToGuaranteePair, minimalCover, minimize, mulberry32, multichoose, multinomial, nCr, nPr, parseLogic, permutationsWithRepetition, powerset, primeImplicants, complement$1 as probComplement, probability, randInt, ruleOfProduct, ruleOfSum, sample, setEqual, shuffle, starsAndBars, symmetricDifference, toCNF, toDNF, truthTable, union };
@@ -1,9 +1,10 @@
1
1
  import { mulberry32, randInt, sample, shuffle } from "../core/rng.mjs";
2
- import { binomial, factorial, gcd, lcm, multinomial, nCr, nPr, starsAndBars } from "./core/combinatorics.mjs";
2
+ import { binomial, circularPermutations, combinationsWithRepetition, factorial, gcd, lcm, multichoose, multinomial, nCr, nPr, permutationsWithRepetition, ruleOfProduct, ruleOfSum, starsAndBars } from "./core/combinatorics.mjs";
3
3
  import { cartesian, complement, difference, intersection, isSubset, powerset, setEqual, symmetricDifference, union } from "./core/sets.mjs";
4
4
  import { inclusionExclusion } from "./core/inclusionExclusion.mjs";
5
5
  import { atLeastOne, bayes, complement as complement$1, conditional, expectedValue, independent, probability } from "./core/probability.mjs";
6
6
  import { guaranteedOccupancy, minForOccupancy, minToGuaranteePair } from "./core/pigeonhole.mjs";
7
+ import { COMBINATION_RULE, COUNTING_RULES, FACTORIAL_RULE, PERMUTATION_RULE, PERM_REP_RULE, PRODUCT_RULE, SUM_RULE, explainFactorial, explainNCr, explainNPr, explainPermWithRep, explainProduct, explainSum } from "./rules.mjs";
7
8
  import { TruthTableLab } from "./truth-table/preset.mjs";
8
9
  import { CountingTreeLab } from "./counting-tree/preset.mjs";
9
10
  import { VennSetBoardLab } from "./venn/preset.mjs";
@@ -13,6 +14,7 @@ import { KarnaughMapLab } from "./karnaugh/preset.mjs";
13
14
  import { MonteCarloLab } from "./monte-carlo/preset.mjs";
14
15
  import { MontyHallLab } from "./monty-hall/preset.mjs";
15
16
  import { OutcomeBuilderLab } from "./outcome-builder/preset.mjs";
17
+ import { CombinationStudioLab } from "./combination-studio/preset.mjs";
16
18
  import { BayesLab } from "./bayes/preset.mjs";
17
19
  import { LawOfLargeNumbersLab } from "./lln/preset.mjs";
18
20
  import { CountingSlotsLab } from "./counting-slots/preset.mjs";
@@ -24,4 +26,4 @@ import { HypergeometricLab } from "./hypergeometric/preset.mjs";
24
26
  import { ExpectedValueLab } from "./expected-value/preset.mjs";
25
27
  import { classify, compileLogic, cubeCovers, cubeOfSelection, cubeTerm, equivalent, evalBool, logicToLatex, minimalCover, minimize, parseLogic, primeImplicants, toCNF, toDNF, truthTable } from "@classytic/stage";
26
28
 
27
- export { ArrangementsLab, BayesLab, BinomialDistributionLab, BooleanCircuitLab, CountingSlotsLab, CountingTreeLab, ExpectedValueLab, HypergeometricLab, KarnaughMapLab, LawOfLargeNumbersLab, MonteCarloLab, MontyHallLab, OutcomeBuilderLab, PascalTriangleLab, SampleSpaceBoardLab, SelectionLab, TruthTableLab, VennSetBoardLab, atLeastOne, bayes, binomial, cartesian, classify, compileLogic, complement, conditional, cubeCovers, cubeOfSelection, cubeTerm, difference, equivalent, evalBool, expectedValue, factorial, gcd, guaranteedOccupancy, inclusionExclusion, independent, intersection, isSubset, lcm, logicToLatex, minForOccupancy, minToGuaranteePair, minimalCover, minimize, mulberry32, multinomial, nCr, nPr, parseLogic, powerset, primeImplicants, complement$1 as probComplement, probability, randInt, sample, setEqual, shuffle, starsAndBars, symmetricDifference, toCNF, toDNF, truthTable, union };
29
+ export { ArrangementsLab, BayesLab, BinomialDistributionLab, BooleanCircuitLab, COMBINATION_RULE, COUNTING_RULES, CombinationStudioLab, CountingSlotsLab, CountingTreeLab, ExpectedValueLab, FACTORIAL_RULE, HypergeometricLab, KarnaughMapLab, LawOfLargeNumbersLab, MonteCarloLab, MontyHallLab, OutcomeBuilderLab, PERMUTATION_RULE, PERM_REP_RULE, PRODUCT_RULE, PascalTriangleLab, SUM_RULE, SampleSpaceBoardLab, SelectionLab, TruthTableLab, VennSetBoardLab, atLeastOne, bayes, binomial, cartesian, circularPermutations, classify, combinationsWithRepetition, compileLogic, complement, conditional, cubeCovers, cubeOfSelection, cubeTerm, difference, equivalent, evalBool, expectedValue, explainFactorial, explainNCr, explainNPr, explainPermWithRep, explainProduct, explainSum, factorial, gcd, guaranteedOccupancy, inclusionExclusion, independent, intersection, isSubset, lcm, logicToLatex, minForOccupancy, minToGuaranteePair, minimalCover, minimize, mulberry32, multichoose, multinomial, nCr, nPr, parseLogic, permutationsWithRepetition, powerset, primeImplicants, complement$1 as probComplement, probability, randInt, ruleOfProduct, ruleOfSum, sample, setEqual, shuffle, starsAndBars, symmetricDifference, toCNF, toDNF, truthTable, union };
@@ -4,42 +4,36 @@ import { Tex as Tex$1 } from "../../core/tex.mjs";
4
4
  import { Chip } from "../../kit/controls.mjs";
5
5
  import { LabFrame } from "../../kit/frame.mjs";
6
6
  import { HintLadder, RevealSolution, useCheckpoint, useHints } from "../../kit/pedagogy.mjs";
7
+ import { CATEGORICAL } from "../../kit/palette.mjs";
7
8
  import { useMemo, useState } from "react";
8
9
  import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
9
10
  import { compileLogic, cubeCovers, cubeOfSelection, cubeTerm, logicToLatex, minimize, useControlSurface } from "@classytic/stage";
10
11
 
11
12
  //#region src/discrete/karnaugh/preset.tsx
12
13
  /**
13
- * KarnaughMapLab — the GENERAL "simplify boolean by eye" tool. A K-map is just a
14
+ * KarnaughMapLab, the GENERAL "simplify boolean by eye" tool. A K-map is just a
14
15
  * truth table re-laid in GRAY-CODE order so that adjacent cells differ in ONE
15
16
  * variable; circling a power-of-two block of 1s drops the variable that changes
16
17
  * across it. That is the same "overcount, then correct" move as the rest of the
17
- * pack — a group merges redundant minterms the way ÷k! merges redundant orderings.
18
+ * pack, a group merges redundant minterms the way ÷k! merges redundant orderings.
18
19
  *
19
20
  * Creator declares a `formula` (any 2–4 variable expression) OR explicit
20
21
  * `minterms` (+ optional `dontCares`). Two modes:
21
- * • show — the kernel's minimal cover is drawn as coloured loops + the SOP.
22
- * • simplify — the learner taps 1-cells to draw their own groups; each is
22
+ * • show , the kernel's minimal cover is drawn as coloured loops + the SOP.
23
+ * • simplify, the learner taps 1-cells to draw their own groups; each is
23
24
  * live-validated (legal sub-cube? all ones?) and its product term
24
25
  * shown; solved when every 1 is covered, with a "minimal!" bonus.
25
26
  *
26
27
  * Minimisation is Quine–McCluskey in the stage logic kernel (`minimize` /
27
- * `cubeOfSelection`) — the map only RENDERS what the kernel computes. Groups that
28
+ * `cubeOfSelection`), the map only RENDERS what the kernel computes. Groups that
28
29
  * wrap the map edges render as two (or four) loops, exactly as on paper.
29
30
  */
30
31
  const CS = 50;
31
32
  const LH = 50, TH = 46;
32
- const PALETTE = [
33
- "#2f9e44",
34
- "#1c7ed6",
35
- "#e8590c",
36
- "#9c36b5",
37
- "#1098ad",
38
- "#e03131"
39
- ];
33
+ const PALETTE = CATEGORICAL;
40
34
  const gray = (i) => i ^ i >> 1;
41
35
  const bits = (v, n) => v.toString(2).padStart(n, "0");
42
- /** Maximal consecutive runs of sorted indices (wrap shows as two runs — desired). */
36
+ /** Maximal consecutive runs of sorted indices (wrap shows as two runs, desired). */
43
37
  function runs(idx) {
44
38
  const s = [...idx].sort((a, b) => a - b);
45
39
  const out = [];
@@ -205,11 +199,11 @@ function KarnaughMapLab({ formula, minterms: mtIn, dontCares: dcIn = [], vars: v
205
199
  viewBox: `0 0 ${W} ${H}`,
206
200
  style: {
207
201
  width: "100%",
208
- maxWidth: W,
202
+ maxWidth: "100%",
209
203
  height: "auto"
210
204
  },
211
- role: "img",
212
- "aria-label": `Karnaugh map of ${vars.join(",")}, ${minterms.length} ones`,
205
+ role: "grid",
206
+ "aria-label": `Karnaugh map, ${n} variables (${vars.join(", ")}), ${nRows * nCols} cells, ${minterms.length} one${minterms.length === 1 ? "" : "s"}`,
213
207
  children: [
214
208
  /* @__PURE__ */ jsx("text", {
215
209
  x: LH + gridW / 2,
@@ -256,9 +250,21 @@ function KarnaughMapLab({ formula, minterms: mtIn, dontCares: dcIn = [], vars: v
256
250
  const isOne = oneSet.has(m), isDC = dcSet.has(m);
257
251
  const sel = mode === "simplify" && selected.includes(m);
258
252
  const val = isOne ? "1" : isDC ? "X" : "0";
253
+ const tappable = mode === "simplify" && (isOne || isDC) && !revealed;
254
+ const cellLabel = `minterm ${m}, value ${val}${sel ? ", selected" : ""}`;
259
255
  return /* @__PURE__ */ jsxs("g", {
260
256
  onClick: () => tapCell(m),
261
- style: { cursor: mode === "simplify" && (isOne || isDC) && !revealed ? "pointer" : "default" },
257
+ onKeyDown: tappable ? (e) => {
258
+ if (e.key === "Enter" || e.key === " ") {
259
+ e.preventDefault();
260
+ tapCell(m);
261
+ }
262
+ } : void 0,
263
+ role: tappable ? "button" : "img",
264
+ tabIndex: tappable ? 0 : void 0,
265
+ "aria-label": cellLabel,
266
+ "aria-pressed": tappable ? sel : void 0,
267
+ style: { cursor: tappable ? "pointer" : "default" },
262
268
  children: [
263
269
  /* @__PURE__ */ jsx("rect", {
264
270
  x: cellX(gc),
@@ -427,7 +433,7 @@ function KarnaughMapLab({ formula, minterms: mtIn, dontCares: dcIn = [], vars: v
427
433
  className: "lab-pill",
428
434
  "data-state": "ok",
429
435
  style: { marginTop: 8 },
430
- children: minimal ? "✓ all ones covered — minimal!" : `✓ covered, but minimal is ${result.cover.length} group${result.cover.length === 1 ? "" : "s"}`
436
+ children: minimal ? "✓ all ones covered, minimal!" : `✓ covered, but minimal is ${result.cover.length} group${result.cover.length === 1 ? "" : "s"}`
431
437
  })
432
438
  ] }) }),
433
439
  footer: /* @__PURE__ */ jsxs(Fragment$1, { children: [mode === "simplify" && /* @__PURE__ */ jsx(RevealSolution, {
@@ -436,7 +442,7 @@ function KarnaughMapLab({ formula, minterms: mtIn, dontCares: dcIn = [], vars: v
436
442
  solution: /* @__PURE__ */ jsxs(Fragment$1, { children: [
437
443
  "The minimal SOP is ",
438
444
  /* @__PURE__ */ jsx(TexExpr, { expr: result.expression }),
439
- " — ",
445
+ ", ",
440
446
  result.cover.length,
441
447
  " group",
442
448
  result.cover.length === 1 ? "" : "s",
@@ -2,6 +2,7 @@
2
2
 
3
3
  import { Chip } from "../../kit/controls.mjs";
4
4
  import { ControlBar, Field, LabFrame } from "../../kit/frame.mjs";
5
+ import { useCheckpoint } from "../../kit/pedagogy.mjs";
5
6
  import { LLN_ASSET } from "./asset.mjs";
6
7
  import { useMemo, useState } from "react";
7
8
  import { jsx, jsxs } from "react/jsx-runtime";
@@ -9,17 +10,17 @@ import { Scene, registerAsset } from "@classytic/stage";
9
10
 
10
11
  //#region src/discrete/lln/preset.tsx
11
12
  /**
12
- * LawOfLargeNumbersLab — the `sampler` core made tangible, the STANDARD data-driven
13
+ * LawOfLargeNumbersLab, the `sampler` core made tangible, the STANDARD data-driven
13
14
  * way: a SceneDoc with one `sampler` sim (meta.sims) + the `lln` asset reading it
14
15
  * live via simBind. Flip a coin / roll a die thousands of times and watch the
15
- * frequencies settle onto the true probability. Coin vs die is just `weights` —
16
+ * frequencies settle onto the true probability. Coin vs die is just `weights` ,
16
17
  * the general tool, not a one-off widget.
17
18
  *
18
19
  * Changing the experiment or hitting "new run" re-keys <Scene> so the sampler
19
20
  * re-seeds (fresh counts); "speed" (draws/frame) merges live without a restart.
20
21
  */
21
22
  registerAsset("lln", LLN_ASSET);
22
- function LawOfLargeNumbersLab({ experiment: exp0 = "coin", title = "The law of large numbers", prompt = "Flip a coin (or roll a die) over and over — the running frequencies settle onto the true probability.", objectives } = {}) {
23
+ function LawOfLargeNumbersLab({ experiment: exp0 = "coin", title = "The law of large numbers", prompt = "Flip a coin (or roll a die) over and over, the running frequencies settle onto the true probability.", objectives } = {}) {
23
24
  const [experiment, setExperiment] = useState(exp0);
24
25
  const [perStep, setPerStep] = useState(1);
25
26
  const [resetN, setResetN] = useState(0);
@@ -94,6 +95,46 @@ function LawOfLargeNumbersLab({ experiment: exp0 = "coin", title = "The law of l
94
95
  perStep,
95
96
  resetN
96
97
  ]);
98
+ const { totalSamples, estimates, trueProbs } = useMemo(() => {
99
+ const weights = experiment === "coin" ? [1, 1] : [
100
+ 1,
101
+ 1,
102
+ 1,
103
+ 1,
104
+ 1,
105
+ 1
106
+ ];
107
+ const maxDraws = experiment === "coin" ? 4e3 : 12e3;
108
+ const total = weights.reduce((a, b) => a + b, 0) || 1;
109
+ const trueP = weights.map((w) => w / total);
110
+ const counts = new Array(weights.length).fill(0);
111
+ let a = 1 + resetN | 0;
112
+ for (let n = 0; n < maxDraws; n++) {
113
+ a = a + 1831565813 | 0;
114
+ let t = Math.imul(a ^ a >>> 15, 1 | a);
115
+ t = t + Math.imul(t ^ t >>> 7, 61 | t) ^ t;
116
+ let x = ((t ^ t >>> 14) >>> 0) / 4294967296 * total;
117
+ let idx = weights.length - 1;
118
+ for (let i = 0; i < weights.length - 1; i++) {
119
+ const w = weights[i] ?? 0;
120
+ if (x < w) {
121
+ idx = i;
122
+ break;
123
+ }
124
+ x -= w;
125
+ }
126
+ counts[idx] = (counts[idx] ?? 0) + 1;
127
+ }
128
+ return {
129
+ totalSamples: maxDraws,
130
+ estimates: counts.map((c) => c / maxDraws),
131
+ trueProbs: trueP
132
+ };
133
+ }, [experiment, resetN]);
134
+ useCheckpoint({
135
+ solved: totalSamples >= 300 && estimates.every((est, i) => Math.abs(est - (trueProbs[i] ?? 0)) <= .02),
136
+ activity: `lln:${title}`
137
+ });
97
138
  return /* @__PURE__ */ jsx(LabFrame, {
98
139
  title,
99
140
  prompt,
@@ -10,7 +10,7 @@ import { useControlSurface } from "@classytic/stage";
10
10
 
11
11
  //#region src/discrete/logic-circuit/preset.tsx
12
12
  /**
13
- * BooleanCircuitLab — the GENERAL "build something real with logic gates" tool.
13
+ * BooleanCircuitLab, the GENERAL "build something real with logic gates" tool.
14
14
  * A creator declares a NETLIST (input switches, typed gates wired by id, output
15
15
  * devices = LEDs/lamps); the learner flips switches and watches power flow
16
16
  * through the gates and LIGHT the outputs. One tool → any combinational circuit:
@@ -297,7 +297,7 @@ function BooleanCircuitLab({ inputs: inputs0, gates, outputs, initial, title = "
297
297
  "."
298
298
  ] }),
299
299
  onReveal: () => {},
300
- note: "Try each switch combination — the wires glow when they carry a 1."
300
+ note: "Try each switch combination, the wires glow when they carry a 1."
301
301
  }), /* @__PURE__ */ jsx(HintLadder, { hints })] }),
302
302
  children: figure
303
303
  });
@@ -15,7 +15,7 @@ interface MCSeries {
15
15
  };
16
16
  /** Map the hit-fraction to the reported quantity (default: the fraction itself). */
17
17
  estimate?: (frac: number) => number;
18
- /** The value the estimate should converge to — drawn as a dashed guide. */
18
+ /** The value the estimate should converge to, drawn as a dashed guide. */
19
19
  theoretical?: number;
20
20
  }
21
21
  type ExperimentSpec = {