@the-inclusionist/engine 9.0.0 → 11.0.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 (532) hide show
  1. package/README.md +120 -78
  2. package/app/css/style.css +761 -377
  3. package/app/public/vendor/fonts/playwrite-cu.woff2 +0 -0
  4. package/app/public/vendor/fonts/playwrite-es-deco.woff2 +0 -0
  5. package/app/public/vendor/fonts/playwrite-es.woff2 +0 -0
  6. package/app/public/vendor/fonts/playwrite-gb-j.woff2 +0 -0
  7. package/app/public/vendor/fonts/playwrite-gb-s.woff2 +0 -0
  8. package/app/public/vendor/fonts/playwrite-pe.woff2 +0 -0
  9. package/app/public/vendor/fonts/playwrite-pt.woff2 +0 -0
  10. package/app/public/vendor/fonts-licences/NOTICE.txt +166 -0
  11. package/app/public/vendor/fonts-licences/OFL-1.1.txt +86 -0
  12. package/app/public/vendor/fonts.css +36 -84
  13. package/dist-pkg/boot/create-game.d.ts +499 -219
  14. package/dist-pkg/boot/create-game.js +3944 -562
  15. package/dist-pkg/core/a11y-sr.d.ts +25 -3
  16. package/dist-pkg/core/a11y-sr.js +38 -19
  17. package/dist-pkg/core/accessible-label.d.ts +17 -0
  18. package/dist-pkg/core/accessible-label.js +37 -0
  19. package/dist-pkg/core/accommodation-subjects.d.ts +26 -0
  20. package/dist-pkg/core/accommodation-subjects.js +32 -0
  21. package/dist-pkg/core/accommodations.d.ts +125 -0
  22. package/dist-pkg/core/accommodations.js +195 -0
  23. package/dist-pkg/core/actions.d.ts +108 -55
  24. package/dist-pkg/core/actions.js +122 -71
  25. package/dist-pkg/core/calm-mode.d.ts +31 -0
  26. package/dist-pkg/core/calm-mode.js +47 -0
  27. package/dist-pkg/core/camera-cycle.d.ts +15 -0
  28. package/dist-pkg/core/camera-cycle.js +7 -0
  29. package/dist-pkg/core/caption-duration.d.ts +15 -0
  30. package/dist-pkg/core/caption-duration.js +19 -0
  31. package/dist-pkg/core/cartridge-problems.d.ts +34 -0
  32. package/dist-pkg/core/cartridge-problems.js +53 -0
  33. package/dist-pkg/core/constants.d.ts +0 -54
  34. package/dist-pkg/core/constants.js +9 -76
  35. package/dist-pkg/core/contract.d.ts +142 -164
  36. package/dist-pkg/core/contract.js +222 -208
  37. package/dist-pkg/core/dom-query.d.ts +4 -4
  38. package/dist-pkg/core/dom-query.js +12 -20
  39. package/dist-pkg/core/entity.d.ts +62 -77
  40. package/dist-pkg/core/entity.js +18 -32
  41. package/dist-pkg/core/escape-html.d.ts +9 -10
  42. package/dist-pkg/core/escape-html.js +16 -20
  43. package/dist-pkg/core/flash-threshold.d.ts +17 -0
  44. package/dist-pkg/core/flash-threshold.js +113 -0
  45. package/dist-pkg/core/game-speed.d.ts +11 -0
  46. package/dist-pkg/core/game-speed.js +16 -0
  47. package/dist-pkg/core/genres.d.ts +20 -0
  48. package/dist-pkg/core/genres.js +44 -0
  49. package/dist-pkg/core/i18n.d.ts +71 -60
  50. package/dist-pkg/core/i18n.js +186 -200
  51. package/dist-pkg/core/loop.d.ts +17 -6
  52. package/dist-pkg/core/loop.js +26 -26
  53. package/dist-pkg/core/pause-icon-catalogue.d.ts +15 -0
  54. package/dist-pkg/core/pause-icon-catalogue.js +54 -0
  55. package/dist-pkg/core/ring.d.ts +17 -0
  56. package/dist-pkg/core/ring.js +29 -0
  57. package/dist-pkg/core/rng.d.ts +7 -12
  58. package/dist-pkg/core/rng.js +23 -53
  59. package/dist-pkg/core/route.d.ts +26 -26
  60. package/dist-pkg/core/route.js +126 -121
  61. package/dist-pkg/core/scenes.d.ts +37 -40
  62. package/dist-pkg/core/scenes.js +41 -43
  63. package/dist-pkg/core/screens.d.ts +4 -4
  64. package/dist-pkg/core/screens.js +11 -16
  65. package/dist-pkg/core/session-clock.d.ts +23 -0
  66. package/dist-pkg/core/session-clock.js +37 -0
  67. package/dist-pkg/core/setting-defaults.d.ts +61 -0
  68. package/dist-pkg/core/setting-defaults.js +66 -0
  69. package/dist-pkg/core/speech-rate.d.ts +29 -0
  70. package/dist-pkg/core/speech-rate.js +47 -0
  71. package/dist-pkg/core/state.d.ts +118 -118
  72. package/dist-pkg/core/state.js +322 -297
  73. package/dist-pkg/core/visual-cycles.d.ts +30 -0
  74. package/dist-pkg/core/visual-cycles.js +52 -0
  75. package/dist-pkg/core/visual-state.d.ts +13 -0
  76. package/dist-pkg/core/visual-state.js +6 -0
  77. package/dist-pkg/educational/activities-registry.d.ts +1 -1
  78. package/dist-pkg/educational/activities-registry.js +9 -8
  79. package/dist-pkg/educational/adaptive-engine.d.ts +11 -11
  80. package/dist-pkg/educational/adaptive-engine.js +17 -17
  81. package/dist-pkg/educational/segment-bar.d.ts +12 -12
  82. package/dist-pkg/educational/segment-bar.js +9 -9
  83. package/dist-pkg/i18n/en.js +324 -223
  84. package/dist-pkg/i18n/es.js +323 -223
  85. package/dist-pkg/i18n/pt.js +348 -226
  86. package/dist-pkg/input/default-bindings.d.ts +37 -38
  87. package/dist-pkg/input/default-bindings.js +127 -144
  88. package/dist-pkg/input/devices.d.ts +7 -7
  89. package/dist-pkg/input/devices.js +17 -16
  90. package/dist-pkg/input/edges.d.ts +23 -32
  91. package/dist-pkg/input/edges.js +23 -28
  92. package/dist-pkg/input/empathy-filter.d.ts +22 -0
  93. package/dist-pkg/input/empathy-filter.js +34 -0
  94. package/dist-pkg/input/face-map.d.ts +96 -0
  95. package/dist-pkg/input/face-map.js +255 -0
  96. package/dist-pkg/input/face-signals.d.ts +40 -0
  97. package/dist-pkg/input/face-signals.js +48 -0
  98. package/dist-pkg/input/gamepad.d.ts +195 -145
  99. package/dist-pkg/input/gamepad.js +383 -556
  100. package/dist-pkg/input/gaze-cycle.d.ts +64 -0
  101. package/dist-pkg/input/gaze-cycle.js +133 -0
  102. package/dist-pkg/input/gaze-relative.d.ts +68 -0
  103. package/dist-pkg/input/gaze-relative.js +142 -0
  104. package/dist-pkg/input/hand-map.d.ts +28 -0
  105. package/dist-pkg/input/hand-map.js +142 -0
  106. package/dist-pkg/input/input-cooldown.d.ts +17 -0
  107. package/dist-pkg/input/input-cooldown.js +39 -0
  108. package/dist-pkg/input/key-default.d.ts +30 -0
  109. package/dist-pkg/input/key-default.js +60 -0
  110. package/dist-pkg/input/keyboard-runtime.d.ts +15 -21
  111. package/dist-pkg/input/keyboard-runtime.js +23 -27
  112. package/dist-pkg/input/keyboard.d.ts +68 -63
  113. package/dist-pkg/input/keyboard.js +83 -105
  114. package/dist-pkg/input/keydown.d.ts +123 -137
  115. package/dist-pkg/input/keydown.js +284 -289
  116. package/dist-pkg/input/latch-edge.d.ts +33 -21
  117. package/dist-pkg/input/latch-edge.js +34 -35
  118. package/dist-pkg/input/latch-scope.d.ts +51 -50
  119. package/dist-pkg/input/latch-scope.js +61 -82
  120. package/dist-pkg/input/latch-store.d.ts +26 -30
  121. package/dist-pkg/input/latch-store.js +42 -50
  122. package/dist-pkg/input/latch-sync.d.ts +29 -29
  123. package/dist-pkg/input/latch-sync.js +25 -25
  124. package/dist-pkg/input/latch.d.ts +14 -17
  125. package/dist-pkg/input/latch.js +29 -37
  126. package/dist-pkg/input/pad-defaults.d.ts +13 -16
  127. package/dist-pkg/input/pad-defaults.js +21 -28
  128. package/dist-pkg/input/pad-reading.d.ts +76 -0
  129. package/dist-pkg/input/pad-reading.js +169 -0
  130. package/dist-pkg/input/pad-wizard.d.ts +99 -0
  131. package/dist-pkg/input/pad-wizard.js +256 -0
  132. package/dist-pkg/input/pointer-space.d.ts +19 -20
  133. package/dist-pkg/input/pointer-space.js +27 -32
  134. package/dist-pkg/input/pointer.d.ts +39 -40
  135. package/dist-pkg/input/pointer.js +42 -45
  136. package/dist-pkg/input/state.d.ts +101 -89
  137. package/dist-pkg/input/state.js +54 -134
  138. package/dist-pkg/input/switch-scan.d.ts +59 -0
  139. package/dist-pkg/input/switch-scan.js +67 -0
  140. package/dist-pkg/input/synthetic-source.d.ts +42 -0
  141. package/dist-pkg/input/synthetic-source.js +57 -0
  142. package/dist-pkg/input/touch-bindings.d.ts +127 -116
  143. package/dist-pkg/input/touch-bindings.js +158 -173
  144. package/dist-pkg/input/touch.d.ts +147 -72
  145. package/dist-pkg/input/touch.js +362 -126
  146. package/dist-pkg/input/transport-in-use.d.ts +107 -0
  147. package/dist-pkg/input/transport-in-use.js +130 -0
  148. package/dist-pkg/input/transports.d.ts +90 -117
  149. package/dist-pkg/input/transports.js +104 -106
  150. package/dist-pkg/input/virtual-controller.d.ts +82 -0
  151. package/dist-pkg/input/virtual-controller.js +69 -0
  152. package/dist-pkg/input/vocabulary-migration.d.ts +50 -49
  153. package/dist-pkg/input/vocabulary-migration.js +80 -79
  154. package/dist-pkg/input/voice-map.d.ts +59 -0
  155. package/dist-pkg/input/voice-map.js +123 -0
  156. package/dist-pkg/platform/audio-ambient.d.ts +13 -2
  157. package/dist-pkg/platform/audio-ambient.js +14 -14
  158. package/dist-pkg/platform/audio-earcons.d.ts +20 -19
  159. package/dist-pkg/platform/audio-earcons.js +51 -42
  160. package/dist-pkg/platform/audio-jingles.js +9 -10
  161. package/dist-pkg/platform/audio-mixer.d.ts +14 -2
  162. package/dist-pkg/platform/audio-mixer.js +31 -39
  163. package/dist-pkg/platform/audio-sonar.d.ts +49 -152
  164. package/dist-pkg/platform/audio-sonar.js +124 -302
  165. package/dist-pkg/platform/audio.d.ts +62 -19
  166. package/dist-pkg/platform/audio.js +193 -168
  167. package/dist-pkg/platform/choose-by-voice.d.ts +70 -0
  168. package/dist-pkg/platform/choose-by-voice.js +157 -0
  169. package/dist-pkg/platform/flash-sampler.d.ts +19 -0
  170. package/dist-pkg/platform/flash-sampler.js +79 -0
  171. package/dist-pkg/platform/font-library.d.ts +77 -0
  172. package/dist-pkg/platform/font-library.js +98 -0
  173. package/dist-pkg/platform/font-library.json +721 -0
  174. package/dist-pkg/platform/heavy-catalogue.d.ts +77 -0
  175. package/dist-pkg/platform/heavy-catalogue.js +256 -0
  176. package/dist-pkg/platform/heavy-mirror.d.ts +20 -0
  177. package/dist-pkg/platform/heavy-mirror.js +73 -0
  178. package/dist-pkg/platform/heavy.d.ts +136 -0
  179. package/dist-pkg/platform/heavy.js +324 -0
  180. package/dist-pkg/platform/interruptible-speech.d.ts +23 -16
  181. package/dist-pkg/platform/interruptible-speech.js +77 -54
  182. package/dist-pkg/platform/kokoro-port.d.ts +27 -0
  183. package/dist-pkg/platform/kokoro-port.js +50 -0
  184. package/dist-pkg/platform/kokoro-runtime.d.ts +20 -0
  185. package/dist-pkg/platform/kokoro-runtime.js +52 -0
  186. package/dist-pkg/platform/kokoro.d.ts +70 -0
  187. package/dist-pkg/platform/kokoro.js +133 -0
  188. package/dist-pkg/platform/listener-scope.d.ts +12 -0
  189. package/dist-pkg/platform/listener-scope.js +90 -0
  190. package/dist-pkg/platform/locale-host.d.ts +14 -0
  191. package/dist-pkg/platform/locale-host.js +45 -0
  192. package/dist-pkg/platform/microphone.d.ts +51 -0
  193. package/dist-pkg/platform/microphone.js +118 -0
  194. package/dist-pkg/platform/onnx-runtime.d.ts +34 -0
  195. package/dist-pkg/platform/onnx-runtime.js +42 -0
  196. package/dist-pkg/platform/reading-in-worker.d.ts +64 -0
  197. package/dist-pkg/platform/reading-in-worker.js +125 -0
  198. package/dist-pkg/platform/reading-model.d.ts +94 -0
  199. package/dist-pkg/platform/reading-model.js +272 -0
  200. package/dist-pkg/platform/reading-runtime.d.ts +24 -0
  201. package/dist-pkg/platform/reading-runtime.js +164 -0
  202. package/dist-pkg/platform/reading-worker.d.ts +41 -0
  203. package/dist-pkg/platform/reading-worker.js +58 -0
  204. package/dist-pkg/platform/reading.d.ts +80 -0
  205. package/dist-pkg/platform/reading.js +136 -0
  206. package/dist-pkg/platform/speech-recognition.d.ts +60 -0
  207. package/dist-pkg/platform/speech-recognition.js +104 -0
  208. package/dist-pkg/platform/speech.d.ts +23 -1
  209. package/dist-pkg/platform/speech.js +29 -18
  210. package/dist-pkg/platform/storage-keys.d.ts +96 -0
  211. package/dist-pkg/platform/storage-keys.js +106 -0
  212. package/dist-pkg/platform/storage.d.ts +46 -111
  213. package/dist-pkg/platform/storage.js +104 -169
  214. package/dist-pkg/platform/tts.d.ts +85 -39
  215. package/dist-pkg/platform/tts.js +447 -127
  216. package/dist-pkg/platform/vision-loop.d.ts +23 -0
  217. package/dist-pkg/platform/vision-loop.js +56 -0
  218. package/dist-pkg/platform/vision.d.ts +132 -0
  219. package/dist-pkg/platform/vision.js +117 -0
  220. package/dist-pkg/platform/voice-listener.d.ts +40 -0
  221. package/dist-pkg/platform/voice-listener.js +88 -0
  222. package/dist-pkg/platform/voice-plan.d.ts +15 -98
  223. package/dist-pkg/platform/voice-plan.js +56 -143
  224. package/dist-pkg/platform/vosk-runtime.d.ts +96 -0
  225. package/dist-pkg/platform/vosk-runtime.js +151 -0
  226. package/dist-pkg/platform/vosk-vocabulary.d.ts +6 -0
  227. package/dist-pkg/platform/vosk-vocabulary.js +178 -0
  228. package/dist-pkg/render/canvas.d.ts +13 -7
  229. package/dist-pkg/render/canvas.js +13 -13
  230. package/dist-pkg/render/crt.d.ts +48 -12
  231. package/dist-pkg/render/crt.js +78 -80
  232. package/dist-pkg/render/cvd-matrices.d.ts +22 -18
  233. package/dist-pkg/render/cvd-matrices.js +37 -38
  234. package/dist-pkg/render/hc-role-data.d.ts +7 -7
  235. package/dist-pkg/render/hc-role-data.js +14 -14
  236. package/dist-pkg/render/high-contrast.d.ts +67 -56
  237. package/dist-pkg/render/high-contrast.js +226 -217
  238. package/dist-pkg/render/low-vision-drawing.d.ts +5 -0
  239. package/dist-pkg/render/low-vision-drawing.js +46 -0
  240. package/dist-pkg/render/lq-filter.d.ts +32 -20
  241. package/dist-pkg/render/lq-filter.js +59 -65
  242. package/dist-pkg/render/port.d.ts +86 -88
  243. package/dist-pkg/render/port.js +17 -23
  244. package/dist-pkg/render/screen-pipeline.d.ts +42 -42
  245. package/dist-pkg/render/screen-pipeline.js +80 -87
  246. package/dist-pkg/render/sprite-fx.d.ts +2 -1
  247. package/dist-pkg/render/sprite-fx.js +16 -14
  248. package/dist-pkg/render/viewports.d.ts +20 -15
  249. package/dist-pkg/render/viewports.js +83 -114
  250. package/dist-pkg/render/viz-axes-labels.d.ts +47 -0
  251. package/dist-pkg/render/viz-axes-labels.js +88 -0
  252. package/dist-pkg/render/viz-axes.d.ts +89 -86
  253. package/dist-pkg/render/viz-axes.js +128 -116
  254. package/dist-pkg/render/viz-modes.d.ts +28 -29
  255. package/dist-pkg/render/viz-modes.js +40 -45
  256. package/dist-pkg/render/viz-refusal.d.ts +32 -0
  257. package/dist-pkg/render/viz-refusal.js +57 -0
  258. package/dist-pkg/render/viz-setters.d.ts +104 -66
  259. package/dist-pkg/render/viz-setters.js +182 -191
  260. package/dist-pkg/ui/aac-sets.d.ts +45 -0
  261. package/dist-pkg/ui/aac-sets.js +41 -0
  262. package/dist-pkg/ui/audio-choices.d.ts +68 -0
  263. package/dist-pkg/ui/audio-choices.js +98 -0
  264. package/dist-pkg/ui/audio-rows-that-apply.d.ts +12 -0
  265. package/dist-pkg/ui/audio-rows-that-apply.js +43 -0
  266. package/dist-pkg/ui/camera-control.d.ts +53 -0
  267. package/dist-pkg/ui/camera-control.js +48 -0
  268. package/dist-pkg/ui/changed-mark.d.ts +9 -8
  269. package/dist-pkg/ui/changed-mark.js +22 -53
  270. package/dist-pkg/ui/control-choices.d.ts +37 -0
  271. package/dist-pkg/ui/control-choices.js +84 -0
  272. package/dist-pkg/ui/debug-panel.d.ts +59 -43
  273. package/dist-pkg/ui/debug-panel.js +68 -69
  274. package/dist-pkg/ui/declared-words.d.ts +21 -0
  275. package/dist-pkg/ui/declared-words.js +66 -0
  276. package/dist-pkg/ui/dom.d.ts +10 -14
  277. package/dist-pkg/ui/dom.js +10 -47
  278. package/dist-pkg/ui/drawing-problems.d.ts +25 -0
  279. package/dist-pkg/ui/drawing-problems.js +94 -0
  280. package/dist-pkg/ui/eye-control.d.ts +36 -0
  281. package/dist-pkg/ui/eye-control.js +178 -0
  282. package/dist-pkg/ui/face-control.d.ts +25 -0
  283. package/dist-pkg/ui/face-control.js +183 -0
  284. package/dist-pkg/ui/focus-trap.d.ts +39 -49
  285. package/dist-pkg/ui/focus-trap.js +56 -65
  286. package/dist-pkg/ui/fonts.d.ts +157 -68
  287. package/dist-pkg/ui/fonts.js +305 -115
  288. package/dist-pkg/ui/footer-scroll-driver.d.ts +14 -0
  289. package/dist-pkg/ui/footer-scroll-driver.js +201 -0
  290. package/dist-pkg/ui/footer-scroll.d.ts +38 -0
  291. package/dist-pkg/ui/footer-scroll.js +55 -0
  292. package/dist-pkg/ui/game-options.d.ts +47 -0
  293. package/dist-pkg/ui/game-options.js +158 -0
  294. package/dist-pkg/ui/gaze-overlay.d.ts +64 -0
  295. package/dist-pkg/ui/gaze-overlay.js +165 -0
  296. package/dist-pkg/ui/hand-control.d.ts +25 -0
  297. package/dist-pkg/ui/hand-control.js +143 -0
  298. package/dist-pkg/ui/help-panel.d.ts +87 -0
  299. package/dist-pkg/ui/help-panel.js +242 -0
  300. package/dist-pkg/ui/hud-bands.d.ts +62 -0
  301. package/dist-pkg/ui/hud-bands.js +146 -0
  302. package/dist-pkg/ui/hud-row.d.ts +34 -0
  303. package/dist-pkg/ui/hud-row.js +80 -0
  304. package/dist-pkg/ui/hud.d.ts +73 -73
  305. package/dist-pkg/ui/hud.js +94 -98
  306. package/dist-pkg/ui/item-announcement.d.ts +13 -12
  307. package/dist-pkg/ui/item-announcement.js +25 -26
  308. package/dist-pkg/ui/layout.d.ts +103 -28
  309. package/dist-pkg/ui/layout.js +117 -99
  310. package/dist-pkg/ui/libras-avatar-clip.d.ts +30 -0
  311. package/dist-pkg/ui/libras-avatar-clip.js +86 -0
  312. package/dist-pkg/ui/libras-avatar-load.d.ts +52 -0
  313. package/dist-pkg/ui/libras-avatar-load.js +134 -0
  314. package/dist-pkg/ui/libras-avatar-plan.d.ts +102 -0
  315. package/dist-pkg/ui/libras-avatar-plan.js +211 -0
  316. package/dist-pkg/ui/libras-avatar-player.d.ts +28 -0
  317. package/dist-pkg/ui/libras-avatar-player.js +226 -0
  318. package/dist-pkg/ui/libras-avatar-stage.d.ts +37 -0
  319. package/dist-pkg/ui/libras-avatar-stage.js +208 -0
  320. package/dist-pkg/ui/libras-glosses.d.ts +28 -0
  321. package/dist-pkg/ui/libras-glosses.js +161 -0
  322. package/dist-pkg/ui/locale-flags.d.ts +16 -0
  323. package/dist-pkg/ui/locale-flags.js +30 -0
  324. package/dist-pkg/ui/loop-crash.d.ts +17 -17
  325. package/dist-pkg/ui/loop-crash.js +33 -62
  326. package/dist-pkg/ui/menu-intent.d.ts +61 -0
  327. package/dist-pkg/ui/menu-intent.js +88 -0
  328. package/dist-pkg/ui/menu-items.d.ts +20 -0
  329. package/dist-pkg/ui/menu-items.js +51 -0
  330. package/dist-pkg/ui/menu-nav.d.ts +98 -92
  331. package/dist-pkg/ui/menu-nav.js +398 -286
  332. package/dist-pkg/ui/mobility-choices.d.ts +26 -0
  333. package/dist-pkg/ui/mobility-choices.js +41 -0
  334. package/dist-pkg/ui/motion-choices.d.ts +31 -0
  335. package/dist-pkg/ui/motion-choices.js +68 -0
  336. package/dist-pkg/ui/motion-scene.d.ts +24 -19
  337. package/dist-pkg/ui/motion-scene.js +29 -61
  338. package/dist-pkg/ui/mount-panel.d.ts +81 -0
  339. package/dist-pkg/ui/mount-panel.js +61 -0
  340. package/dist-pkg/ui/panel-shell.d.ts +65 -31
  341. package/dist-pkg/ui/panel-shell.js +92 -66
  342. package/dist-pkg/ui/panel-widgets.d.ts +150 -0
  343. package/dist-pkg/ui/panel-widgets.js +294 -0
  344. package/dist-pkg/ui/pause-buttons.d.ts +35 -0
  345. package/dist-pkg/ui/pause-buttons.js +66 -0
  346. package/dist-pkg/ui/pause-icons.d.ts +261 -347
  347. package/dist-pkg/ui/pause-icons.js +671 -601
  348. package/dist-pkg/ui/pause-markup.d.ts +86 -0
  349. package/dist-pkg/ui/pause-markup.js +125 -0
  350. package/dist-pkg/ui/reach-notice.d.ts +22 -23
  351. package/dist-pkg/ui/reach-notice.js +55 -58
  352. package/dist-pkg/ui/scan-overlay.d.ts +23 -0
  353. package/dist-pkg/ui/scan-overlay.js +50 -0
  354. package/dist-pkg/ui/screen-text.d.ts +25 -0
  355. package/dist-pkg/ui/screen-text.js +152 -0
  356. package/dist-pkg/ui/session-clock.d.ts +32 -0
  357. package/dist-pkg/ui/session-clock.js +67 -0
  358. package/dist-pkg/ui/settings-aac.d.ts +70 -0
  359. package/dist-pkg/ui/settings-aac.js +208 -0
  360. package/dist-pkg/ui/settings-audio.d.ts +97 -114
  361. package/dist-pkg/ui/settings-audio.js +493 -425
  362. package/dist-pkg/ui/settings-controls.d.ts +53 -96
  363. package/dist-pkg/ui/settings-controls.js +143 -215
  364. package/dist-pkg/ui/settings-empathy.d.ts +39 -30
  365. package/dist-pkg/ui/settings-empathy.js +53 -60
  366. package/dist-pkg/ui/settings-mobility.d.ts +192 -0
  367. package/dist-pkg/ui/settings-mobility.js +332 -0
  368. package/dist-pkg/ui/settings-motion.d.ts +91 -70
  369. package/dist-pkg/ui/settings-motion.js +287 -198
  370. package/dist-pkg/ui/settings-panel.d.ts +58 -45
  371. package/dist-pkg/ui/settings-panel.js +189 -94
  372. package/dist-pkg/ui/settings-typo.d.ts +29 -78
  373. package/dist-pkg/ui/settings-typo.js +158 -129
  374. package/dist-pkg/ui/settings-visual.d.ts +29 -87
  375. package/dist-pkg/ui/settings-visual.js +240 -193
  376. package/dist-pkg/ui/shell.d.ts +112 -135
  377. package/dist-pkg/ui/shell.js +148 -217
  378. package/dist-pkg/ui/simulation-list.d.ts +27 -0
  379. package/dist-pkg/ui/simulation-list.js +76 -0
  380. package/dist-pkg/ui/simulation-over-the-world.d.ts +23 -0
  381. package/dist-pkg/ui/simulation-over-the-world.js +131 -0
  382. package/dist-pkg/ui/simulation-refusal.d.ts +5 -31
  383. package/dist-pkg/ui/simulation-refusal.js +8 -56
  384. package/dist-pkg/ui/switchable-control.d.ts +11 -0
  385. package/dist-pkg/ui/switchable-control.js +19 -0
  386. package/dist-pkg/ui/title.d.ts +3 -12
  387. package/dist-pkg/ui/title.js +49 -18
  388. package/dist-pkg/ui/top-band.d.ts +26 -0
  389. package/dist-pkg/ui/top-band.js +96 -0
  390. package/dist-pkg/ui/typo-choices.d.ts +71 -0
  391. package/dist-pkg/ui/typo-choices.js +85 -0
  392. package/dist-pkg/ui/visual-axes-panel.d.ts +11 -47
  393. package/dist-pkg/ui/visual-axes-panel.js +12 -94
  394. package/dist-pkg/ui/visual-choices.d.ts +77 -0
  395. package/dist-pkg/ui/visual-choices.js +107 -0
  396. package/dist-pkg/ui/vlibras.d.ts +77 -10
  397. package/dist-pkg/ui/vlibras.js +130 -81
  398. package/dist-pkg/ui/voice-control.d.ts +68 -0
  399. package/dist-pkg/ui/voice-control.js +276 -0
  400. package/dist-pkg/ui/voice-settings.d.ts +95 -0
  401. package/dist-pkg/ui/voice-settings.js +352 -0
  402. package/dist-pkg/ui/where-the-child-is.d.ts +31 -0
  403. package/dist-pkg/ui/where-the-child-is.js +70 -0
  404. package/docs/CREDITS.md +300 -44
  405. package/docs/LICENSES.md +189 -145
  406. package/package.json +51 -27
  407. package/scripts/check-cartridge.mjs +78 -0
  408. package/scripts/game-build.d.mts +25 -0
  409. package/scripts/game-build.mjs +144 -0
  410. package/scripts/heavy-into-the-delivery.mjs +388 -0
  411. package/scripts/libras-avatar.json +680 -0
  412. package/scripts/libras-avatar.mjs +246 -0
  413. package/scripts/libras-glosses/gloss.py +95 -0
  414. package/scripts/libras-glosses/pyproject.toml +32 -0
  415. package/scripts/libras-glosses/uv.lock +781 -0
  416. package/scripts/libras-glosses.mjs +351 -0
  417. package/scripts/licences/Apache-2.0.txt +176 -0
  418. package/scripts/licences/GPL-3.0.txt +674 -0
  419. package/scripts/licences/MIT.txt +17 -0
  420. package/scripts/licences/OFL-1.1.txt +86 -0
  421. package/scripts/licences/UFL-1.0.txt +96 -0
  422. package/scripts/licences/fonts.mjs +389 -0
  423. package/scripts/licences/third-party.mjs +301 -0
  424. package/scripts/licences/vosk-browser.NOTICE.txt +268 -0
  425. package/app/public/vendor/fonts/comicneue-400.woff2 +0 -0
  426. package/app/public/vendor/fonts/comicneue-700.woff2 +0 -0
  427. package/app/public/vendor/fonts/fondamento-400-ext.woff2 +0 -0
  428. package/app/public/vendor/fonts/fondamento-400.woff2 +0 -0
  429. package/app/public/vendor/fonts/inter-400.woff2 +0 -0
  430. package/app/public/vendor/fonts/inter-700.woff2 +0 -0
  431. package/app/public/vendor/fonts/lato-400.woff2 +0 -0
  432. package/app/public/vendor/fonts/lato-700.woff2 +0 -0
  433. package/app/public/vendor/fonts/literata-400.woff2 +0 -0
  434. package/app/public/vendor/fonts/literata-700.woff2 +0 -0
  435. package/app/public/vendor/fonts/newsreader-400.woff2 +0 -0
  436. package/app/public/vendor/fonts/newsreader-700.woff2 +0 -0
  437. package/app/public/vendor/fonts/opendyslexic-400.woff2 +0 -0
  438. package/app/public/vendor/fonts/opensans-400.woff2 +0 -0
  439. package/app/public/vendor/fonts/opensans-700.woff2 +0 -0
  440. package/app/public/vendor/fonts/pinyon-400.woff2 +0 -0
  441. package/app/public/vendor/fonts/pressstart-400.woff2 +0 -0
  442. package/app/public/vendor/fonts/quattro-400.woff2 +0 -0
  443. package/app/public/vendor/fonts/quattro-700.woff2 +0 -0
  444. package/app/public/vendor/fonts/sourcesans-400.woff2 +0 -0
  445. package/app/public/vendor/fonts/sourcesans-700.woff2 +0 -0
  446. package/app/public/vendor/fonts/sourceserif-400.woff2 +0 -0
  447. package/app/public/vendor/fonts/sourceserif-700.woff2 +0 -0
  448. package/app/public/vendor/fonts/ufmag-400.woff2 +0 -0
  449. package/dist-pkg/core/anel.d.ts +0 -17
  450. package/dist-pkg/core/anel.js +0 -31
  451. package/dist-pkg/core/collision.d.ts +0 -21
  452. package/dist-pkg/core/collision.js +0 -62
  453. package/dist-pkg/core/layers.d.ts +0 -63
  454. package/dist-pkg/core/layers.js +0 -95
  455. package/dist-pkg/core/letter-grid.d.ts +0 -55
  456. package/dist-pkg/core/letter-grid.js +0 -116
  457. package/dist-pkg/core/password.d.ts +0 -34
  458. package/dist-pkg/core/password.js +0 -205
  459. package/dist-pkg/core/rotulo-acessivel.d.ts +0 -17
  460. package/dist-pkg/core/rotulo-acessivel.js +0 -41
  461. package/dist-pkg/core/run-state.d.ts +0 -115
  462. package/dist-pkg/core/run-state.js +0 -40
  463. package/dist-pkg/core/tiles.d.ts +0 -12
  464. package/dist-pkg/core/tiles.js +0 -61
  465. package/dist-pkg/core/world.d.ts +0 -4
  466. package/dist-pkg/core/world.js +0 -58
  467. package/dist-pkg/input/origem-sintetica.d.ts +0 -44
  468. package/dist-pkg/input/origem-sintetica.js +0 -60
  469. package/dist-pkg/input/transporte-em-uso.d.ts +0 -101
  470. package/dist-pkg/input/transporte-em-uso.js +0 -130
  471. package/dist-pkg/platform/audio-nav.d.ts +0 -51
  472. package/dist-pkg/platform/audio-nav.js +0 -99
  473. package/dist-pkg/platform/guide-intensity.d.ts +0 -40
  474. package/dist-pkg/platform/guide-intensity.js +0 -73
  475. package/dist-pkg/platform/pesados-catalogo.d.ts +0 -14
  476. package/dist-pkg/platform/pesados-catalogo.js +0 -177
  477. package/dist-pkg/platform/pesados.d.ts +0 -31
  478. package/dist-pkg/platform/pesados.js +0 -75
  479. package/dist-pkg/platform/vozes-prontas.d.ts +0 -28
  480. package/dist-pkg/platform/vozes-prontas.js +0 -61
  481. package/dist-pkg/render/camera.d.ts +0 -58
  482. package/dist-pkg/render/camera.js +0 -105
  483. package/dist-pkg/render/cenario-data.d.ts +0 -127
  484. package/dist-pkg/render/cenario-data.js +0 -145
  485. package/dist-pkg/render/city-tex.d.ts +0 -63
  486. package/dist-pkg/render/city-tex.js +0 -228
  487. package/dist-pkg/render/city-tiles.d.ts +0 -11
  488. package/dist-pkg/render/city-tiles.js +0 -140
  489. package/dist-pkg/render/draw.d.ts +0 -149
  490. package/dist-pkg/render/draw.js +0 -231
  491. package/dist-pkg/render/fx.d.ts +0 -63
  492. package/dist-pkg/render/fx.js +0 -123
  493. package/dist-pkg/render/minimap.d.ts +0 -11
  494. package/dist-pkg/render/minimap.js +0 -94
  495. package/dist-pkg/render/parallax.d.ts +0 -85
  496. package/dist-pkg/render/parallax.js +0 -158
  497. package/dist-pkg/render/player-anim.d.ts +0 -71
  498. package/dist-pkg/render/player-anim.js +0 -152
  499. package/dist-pkg/render/recycling-tex.d.ts +0 -48
  500. package/dist-pkg/render/recycling-tex.js +0 -164
  501. package/dist-pkg/render/scene-city.d.ts +0 -77
  502. package/dist-pkg/render/scene-city.js +0 -181
  503. package/dist-pkg/render/scene-parallax.d.ts +0 -72
  504. package/dist-pkg/render/scene-parallax.js +0 -426
  505. package/dist-pkg/render/scene-sky.d.ts +0 -126
  506. package/dist-pkg/render/scene-sky.js +0 -295
  507. package/dist-pkg/render/set-cenario.d.ts +0 -54
  508. package/dist-pkg/render/set-cenario.js +0 -103
  509. package/dist-pkg/render/textures.d.ts +0 -75
  510. package/dist-pkg/render/textures.js +0 -240
  511. package/dist-pkg/render/title-scene.d.ts +0 -46
  512. package/dist-pkg/render/title-scene.js +0 -75
  513. package/dist-pkg/render/weather.d.ts +0 -96
  514. package/dist-pkg/render/weather.js +0 -171
  515. package/dist-pkg/render/wheelchair-sprites.d.ts +0 -32
  516. package/dist-pkg/render/wheelchair-sprites.js +0 -69
  517. package/dist-pkg/render/world-tex.d.ts +0 -18
  518. package/dist-pkg/render/world-tex.js +0 -87
  519. package/dist-pkg/ui/activities-menu.d.ts +0 -258
  520. package/dist-pkg/ui/activities-menu.js +0 -648
  521. package/dist-pkg/ui/caa-sets.d.ts +0 -39
  522. package/dist-pkg/ui/caa-sets.js +0 -65
  523. package/dist-pkg/ui/latch-refusal.d.ts +0 -32
  524. package/dist-pkg/ui/latch-refusal.js +0 -60
  525. package/dist-pkg/ui/map-hub.d.ts +0 -56
  526. package/dist-pkg/ui/map-hub.js +0 -138
  527. package/dist-pkg/ui/settings-caa.d.ts +0 -45
  528. package/dist-pkg/ui/settings-caa.js +0 -137
  529. package/dist-pkg/ui/settings-motor.d.ts +0 -175
  530. package/dist-pkg/ui/settings-motor.js +0 -342
  531. package/dist-pkg/ui/webcam.d.ts +0 -7
  532. package/dist-pkg/ui/webcam.js +0 -93
@@ -1,131 +1,76 @@
1
1
  // SPDX-License-Identifier: AGPL-3.0-or-later
2
- // platform/audio-sonar — NAVEGAÇÃO SONORA, a metade de `audio-nav` que serve a QUALQUER gênero (item 19).
2
+ // platform/audio-sonar — NAVIGATION BY SOUND, the part of audio navigation that serves ANY genre (item 19).
3
3
  //
4
- // ========================= O ACHADO 9, VIRADO CORTE =========================
5
- // O segundo consumidor registrou, e não contornou:
4
+ // ========================= A FINDING, TURNED INTO A CUT =========================
5
+ // A second consumer recorded it and did not work around it: the sonar could not be used by anything but a platformer.
6
+ // Its context asked for tiles, a solid test, a hitbox, the tile size, a coin array and a scenery — a quiz would have had
7
+ // to invent fake tiles, a fake hitbox and a fake scenery to ask "point at the nearest option". The module was TWO
8
+ // modules under one name.
6
9
  //
7
- // "O SONAR NÃO PODE SER USADO POR QUEM NÃO É PLATAFORMA… O ctx de `platform/audio-nav` pede 19 coisas, e
8
- // seis delas são de plataforma pura — `tileAt`, `solidAt`, `BOX`, `TILE`, `getCoins`, `getCenario`. Um
9
- // quiz teria de inventar tiles falsos, uma caixa de colisão falsa e um cenário falso para pedir 'aponte
10
- // a alternativa mais próxima'. E o módulo é DOIS módulos com um nome só."
10
+ // This is one of them: what navigates by SOUND — pointing at the nearest target, the looping beacon, the pan by relative
11
+ // position and the question "does this child need audio cues?". The CANE and BLIND SWIMMING, which read tiles, floor and
12
+ // hitbox, are the platformer's and live in its repository (ADR-0228, note CC). So is the continuous audio GUIDE, which
13
+ // is that game's decision: it left this module for the platformer's `platform/audio-guide` (ADR-0257, note DZ).
11
14
  //
12
- // Estes são os dois. Aqui fica o que navega por SOM: apontar o alvo mais perto, o beacon em laço, o pan pela
13
- // posição relativa e a pergunta "esta criança precisa de pista sonora?". Em `audio-nav` ficam a BENGALA e o
14
- // NADO CEGO, que leem tile, chão e caixa de colisão — plataforma, e sem disfarce.
15
+ // ========================= WHAT REPLACED THE PLATFORMER THINGS =========================
16
+ // None of them crossed over. The sonar used to ask the game for an array of coins and filter by taken/owner; now it
17
+ // receives the CONTRACT (ADR-0030):
15
18
  //
16
- // ========================= O QUE SUBSTITUIU AS SEIS COISAS DE PLATAFORMA =========================
17
- // Nenhuma delas atravessou. O sonar perguntava ao jogo por um array de moedas e filtrava `taken`/`owner`;
18
- // agora ele recebe o CONTRATO (ADR-0030):
19
+ // · the coins + the filter → `targetsOf(i)`, the "target" half of field 5. The game hands over the spots that still
20
+ // count for that player, and never says what they are.
21
+ // · the tile size (the ruler of "near") → `topology()` + `distance()`, the metric declared in field 1. In a
22
+ // platformer it is pixels over `unit`; on a grid, king's steps; in a quiz, a difference of index.
23
+ // · the target's name → `nameAt(spot)`, field 3. It is what lets the announcement say "coin", "question" or "box"
24
+ // without the engine knowing any of the three.
19
25
  //
20
- // · `getCoins()` + o filtro → `targetsOf(i)`, a metade "alvo" do campo 5. O jogo entrega os pontos que
21
- // ainda contam para aquele jogador, e nunca diz o que eles são.
22
- // · `TILE` (a régua de "perto") → `topology()` + `distance()`, a métrica declarada no campo 1. Numa
23
- // plataforma são pixels sobre `unit`; numa grade, passos de rei; num quiz, diferença de índice.
24
- // · `t('sr.nav.coin')` (o nome do alvo) → `nameAt(spot)`, campo 3. É o que faz o anúncio dizer "moeda",
25
- // "pergunta" ou "caixa" sem a engine conhecer nenhum dos três.
26
+ // ⚠️ AND ONE WAS LEFT, THE LAST AND THE WORST: the pan measured the stereo width as `LOGICAL_W * 0.55` — the SCREEN's
27
+ // width. The `wx` it divides comes from the TOPOLOGY, and dividing a world measure by a screen's width only works when
28
+ // both use the same ruler. Measured building a football game (#121): on a 90-METRE pitch, a team-mate ten metres to the
29
+ // right gives `10 / 176 = 0.057` — mono, in practice. The sonar would be **right and inaudible**. For the platformer it
30
+ // was true by chance (its world is measured in pixels) and for `grid`/`hotspots` it was vacuous, which is why it was
31
+ // never seen.
26
32
  //
27
- // ⚠️ E SOBRAVA UMA, QUE ERA A ÚLTIMA E A PIOR: o pan media a largura do estéreo em `LOGICAL_W * 0.55` — a
28
- // largura da TELA. Escrevi aqui que ela era «da tela e não do gênero, e por isso entra por ctx». A frase
29
- // estava certa sobre a origem e errada sobre a consequência: o `wx` que ela divide vem da TOPOLOGIA, e
30
- // dividir uma medida de mundo pela largura de um ecrã só funciona quando as duas usam a mesma régua.
33
+ // The stereo width comes from the declared metric: `PAN_PACES * step`, where the step is the continuous space's `unit`,
34
+ // one cell on a grid, and nothing in a list — which has no space.
31
35
  //
32
- // Medido ao construir o `game-soccer` (#121): num campo de 90 METROS, um colega dez metros à direita dá
33
- // `10 / 176 = 0,057` — mono, na prática. O sonar ficaria **certo e inaudível**, que é a mesma classe de
34
- // defeito que o quiz registou como «certo e inútil». Para a plataforma era verdade por acaso (o mundo dela é
35
- // medido em pixels) e para `grid`/`hotspots` era vácuo, e é por isso que nunca se viu.
36
- //
37
- // A largura do estéreo passa a vir da métrica declarada: `PAN_PACES * passo`, onde o passo é o `unit` do
38
- // contínuo, uma célula na grade, e nada na lista — que não tem espaço.
39
- //
40
- // ========================= SEM I/O NO IMPORT =========================
41
- // Nada aqui toca `window` fora de `playerCtx`, que é chamada e não importada. Roda no project `node`.
36
+ // ========================= NO I/O AT IMPORT =========================
37
+ // Nothing here touches `window`: a player's own context comes from the injected `newContext` (ADR-0232 D4). It runs in the
38
+ // `node` project.
42
39
  import { distance, bearing } from '../core/contract.js';
43
- import { t } from '../core/i18n.js';
44
- // O GUIA (#84 item 2) é feito destes dois, e de mais nada: a ROTA diz quantos passos faltam contornando
45
- // parede, e a INTENSIDADE traduz esse número em brilho e volume. Nenhum dos dois toca no Web Audio; a fiação
46
- // — a única parte que toca — é o `updateGuide` lá em baixo, e é por isso que o desenho é conferível em `node`.
47
- import { rotaAte } from '../core/route.js';
48
- import { intensidadeDoGuia, CORTE_LONGE, PASSOS_ATE_O_FUNDO } from './guide-intensity.js';
49
40
  /**
50
- * Quantos PASSOS da métrica declarada saturam o estéreo. Além disto, "à direita" é só à direita.
41
+ * How many STEPS of the declared metric saturate the stereo. Beyond this, "to the right" is just to the right.
51
42
  *
52
- * ⚠️ ONZE NÃO É NÚMERO NOVO — é o que a plataforma sempre teve, relido na régua certa. O denominador antigo
53
- * era `LOGICAL_W * 0.55 = 320 × 0,55 = 176` pixels, e a plataforma declara `unit: TILE` = 16: são **exatamente
54
- * 11 tiles**. Reescrever em passos preserva o que essa criança já ouve, letra por letra, e passa a dizer o
55
- * mesmo em qualquer gênero — 11 casas num tabuleiro, 11 metros num campo.
43
+ * ⚠️ ELEVEN IS NOT A NEW NUMBER — it is what the platformer always had, reread on the right ruler. The old denominator was
44
+ * `LOGICAL_W * 0.55 = 320 × 0.55 = 176` pixels, and the platformer declares `unit: TILE` = 16: **exactly 11 tiles**.
45
+ * Rewriting it in steps keeps what that child already hears, and says the same in any genre — 11 squares on a board,
46
+ * 11 metres on a pitch.
56
47
  *
57
- * E encaixa na régua que o resto do módulo já usa: `chaveDeDistancia` corta "muito perto" em 4 passos e
58
- * "perto" em 9. O estéreo satura logo depois de a coisa passar a ser "longe", que é onde a direção deixa de
59
- * precisar de mais precisão.
48
+ * And it fits the ruler the rest of the module uses: `distanceKey` cuts "very near" at 4 steps and "near" at 9. The
49
+ * stereo saturates just after the thing becomes "far", which is where direction stops needing more precision.
60
50
  */
61
51
  export const PAN_PACES = 11;
62
52
  /**
63
- * Quanto vale UM passo, em unidades do mundo. Zero = este espaço não tem lado.
53
+ * What ONE step is worth, in world units. Zero = this space has no sides.
64
54
  *
65
- * Contínuo: o `unit` declarado. Grade: uma célula, por definição. Lista: nada — `hotspots` é uma ordem, não
66
- * uma geometria, e inventar-lhe uma largura de estéreo seria apontar para um lado que não existe.
55
+ * Continuous: the declared `unit`. Grid: one cell, by definition. List: nothing — `hotspots` is an order, not a geometry,
56
+ * and inventing a stereo width for it would point at a side that does not exist.
67
57
  */
68
- export function passoDoMundo(topo) {
69
- return topo.kind === 'continuous' ? topo.unit : topo.kind === 'grid' ? 1 : 0;
58
+ export function worldStep(shape) {
59
+ return shape.kind === 'continuous' ? shape.unit : shape.kind === 'grid' ? 1 : 0;
70
60
  }
71
- /**
72
- * ⚠️ O TIMBRE TEM DE TER HARMÓNICOS, e isto é requisito técnico, não gosto.
73
- *
74
- * O eixo do #84 item 2 é o BRILHO, e brilho é um passa-baixo a abrir e a fechar. **Um passa-baixo sobre uma
75
- * onda `sine` não faz absolutamente nada**: a senoide não tem nada acima da fundamental para o filtro cortar,
76
- * e o guia ficaria com um eixo morto e só o volume a trabalhar. A dente-de-serra é a mais rica das quatro
77
- * ondas do Web Audio — tem TODOS os harmónicos —, e é por isso que ela é a escolha.
78
- *
79
- * E ela resolve, de graça, a outra restrição do plano: o sonar e a bengala usam `sine`. Um timbre diferente
80
- * era exigência de não colidirem no mesmo canal; aqui o timbre diferente É o mecanismo.
81
- */
82
- export const GUIA_TIPO = 'sawtooth';
83
- /**
84
- * A fundamental do guia, fixa.
85
- *
86
- * ⚠️ FIXA DE PROPÓSITO: a ALTURA já é a linguagem do sonar (`380 + 740 * near`, mais perto = mais agudo). Se o
87
- * guia também subisse de tom, os dois estariam a dizer a mesma coisa pelo mesmo meio, e quem ouve os dois ao
88
- * mesmo tempo não teria como separá-los. O guia diz distância por brilho; o sonar, por altura.
89
- */
90
- export const GUIA_HZ = 220;
91
- /**
92
- * Quantos quadros entre dois cálculos de rota.
93
- *
94
- * ⚠️ A ROTA É UMA BUSCA EM LARGURA, e o `__incl.update(dt)` conta QUADROS: correr uma BFS a cada quadro num
95
- * mapa de plataforma gasta o orçamento do quadro inteiro no aparelho-alvo (Positivo/Chromebook, pilar 1). Doze
96
- * quadros são ~0,2 s a 60 fps — mais depressa do que a criança anda um passo, e o som não espera por eles: a
97
- * intensidade é reescrita TODO quadro, com o `passos` que a última rota deixou.
98
- */
99
- export const QUADROS_ENTRE_ROTAS = 12;
100
- /**
101
- * O tecto de pontos da rota do guia. Bem abaixo dos 4096 do `core/route`, e o próprio módulo diz porquê:
102
- * «uma pista por quadro tolera muito menos do que um cálculo ao carregar a fase». Estourar devolve `null`, que
103
- * é «não sei» — e o guia cai na reta, que ainda soa.
104
- */
105
- export const ORCAMENTO_DA_ROTA = 1024;
106
- /**
107
- * O ganho de base do guia, antes de a intensidade e o volume mestre o multiplicarem.
108
- *
109
- * ⚠️ MAIS BAIXO DO QUE O BIPE QUE ELE SUBSTITUI (0,11), e não por engano: um som que **nunca para** é
110
- * percebido como mais alto do que um transiente do mesmo pico, e cansa por permanência em vez de por
111
- * intensidade — exactamente o que o modo TEA existe para não fazer.
112
- */
113
- export const GUIA_VOL = 0.06;
114
- /** Constante de tempo do `setTargetAtTime`. Curta o bastante para acompanhar o passo, longa o bastante para
115
- * que a mudança seja um deslize e não um degrau — um degrau a cada rota seria um bipe outra vez. */
116
- export const TAU_DO_GUIA = 0.08;
117
61
  export function createAudioSonar(ctx) {
118
- let _sonarCount = 0, _guideCount = 0;
119
- /** AudioContext do jogador (para o `setSinkId` no dispositivo dele), ou null → contexto global. */
62
+ const { t } = ctx;
63
+ let _sonarCount = 0;
64
+ /** The player's AudioContext (for `setSinkId` on their device), or null → the global context. */
120
65
  function playerCtx(pl) {
121
66
  if (!pl || !pl.audioSink)
122
67
  return null;
123
68
  try {
124
69
  if (!pl._ac) {
125
- const AC = window.AudioContext || window.webkitAudioContext;
126
- if (!AC)
70
+ const ac = ctx.newContext();
71
+ if (!ac)
127
72
  return null;
128
- pl._ac = new AC();
73
+ pl._ac = ac;
129
74
  pl._acOut = pl._ac.createGain();
130
75
  pl._acOut.connect(pl._ac.destination);
131
76
  if (pl._ac.setSinkId)
@@ -140,245 +85,122 @@ export function createAudioSonar(ctx) {
140
85
  }
141
86
  }
142
87
  function panFor(wx, pl) {
143
- const passo = passoDoMundo(ctx.topology());
144
- // `hotspots` não tem espaço, logo não tem lado. O `bearing` já responde `none` pelo mesmo motivo, e
145
- // centrar é a única resposta honesta — um pan calculado sobre índices de lista aponta para nada.
146
- if (!(passo > 0))
88
+ const pace = worldStep(ctx.topology());
89
+ // `hotspots` has no space, so no side. `bearing` already answers `none` for the same reason, and centring is the only
90
+ // honest answer — a pan computed over list indices points at nothing.
91
+ if (!(pace > 0))
147
92
  return 0;
148
- return Math.max(-1, Math.min(1, (wx - pl.x) / (PAN_PACES * passo)));
93
+ return Math.max(-1, Math.min(1, (wx - pl.x) / (PAN_PACES * pace)));
149
94
  }
150
95
  /**
151
- * Visão comprometida? Guarda e guia só existem quando a resposta é sim (ou no modo cego).
96
+ * Impaired sight? A game's audio cues — its edge guard, its guide — ask this, and exist only when the answer is yes (or in
97
+ * blind mode).
152
98
  *
153
- * ⚠️ A METADE VISUAL PASSOU A SER INJECTADA (#104), e o módulo ficou MENOR em vez de migrado. Ele
154
- * consultava `ctx.VIZ_BY_KEY[pl.viz]` — uma tabela de modos de RENDER, atravessada por uma chave de
155
- * render, dentro de `platform/`. A #104 obrigava a escolher: ou este ficheiro passava a importar
156
- * `render/viz-axes` (uma aresta ao contrário: medido, `render/` importa de `platform/` em cinco pontos e o
157
- * inverso em nenhum), ou deixava de saber o que é um modo visual.
99
+ * ⚠️ THE VISUAL HALF IS INJECTED (#104), and the module got SMALLER instead of migrating. It used to consult a table of
100
+ * RENDER modes, walked with a render key, from inside `platform/`. The choice was: import `render/` (an edge the wrong
101
+ * way — `render/` imports `platform/`, never the reverse), or stop knowing what a visual mode is.
158
102
  *
159
- * A segunda é a certa, e é o movimento que o `touch.ts` já nomeia como «o mesmo do achado 10
160
- * (`isNavigable`): injetar o BOOLEANO, não o estado». O que este módulo precisa de saber é «esta criança
161
- * precisa de pista sonora», e isso não é uma pergunta sobre tabelas de filtro — é uma pergunta que a raiz
162
- * de composição responde, porque é ela que conhece os dois eixos.
103
+ * The second is right, and it is the move of `isNavigable`: inject the BOOLEAN, not the state. What this module needs to
104
+ * know is "does this child need audio cues", and that is not a question about filter tables — the composition root
105
+ * answers it, because it knows the two axes.
163
106
  *
164
- * O que FICA aqui é a regra que é mesmo deste módulo: **o modo cego liga as pistas para toda a gente**,
165
- * independentemente do que a visão diga.
107
+ * What STAYS here is the rule that really is this module's: **blind mode turns the cues on for everyone**, whatever
108
+ * sight says.
166
109
  */
167
110
  function needsAudioCues(pl) {
168
- return ctx.getModoCego() || ctx.visaoComprometida(pl);
111
+ return ctx.getBlindMode() || ctx.visionImpaired(pl);
169
112
  }
170
113
  /**
171
- * O alvo mais perto deste jogador, na MÉTRICA DECLARADA — e `null` se não houver nenhum.
172
- *
173
- * Era um laço sobre `getCoins()` com `if (cn.taken || cn.owner !== pl.i) continue` e `Math.hypot`. As três
174
- * coisas que ele sabia sobre o jogo (que alvos são moedas, que moedas têm dono, que distância é euclidiana
175
- * em pixels) viraram uma pergunta ao contrato e uma chamada a `distance`.
176
- */
177
- /**
178
- * O RUMO EM PALAVRAS, na língua de quem joga e no referencial que o JOGO declarou.
114
+ * THE BEARING IN WORDS, in the player's language and in the frame the GAME declared.
179
115
  *
180
- * ⚠️ O QUE ISTO SUBSTITUI ERA UM DEFEITO DE ACESSIBILIDADE, não um detalhe de estilo. O sonar calculava o
181
- * lado à mão, de `x` cru, com zona morta de ±4:
116
+ * ⚠️ WHAT THIS REPLACED WAS AN ACCESSIBILITY DEFECT, not a style detail. The sonar computed the side by hand, from a raw
117
+ * `x`, with a ±4 dead zone:
182
118
  *
183
- * alvo.at.x < pl.x - 4 ? 'left' : alvo.at.x > pl.x + 4 ? 'right' : 'ahead'
119
+ * target.at.x < pl.x - 4 ? 'left' : target.at.x > pl.x + 4 ? 'right' : 'ahead'
184
120
  *
185
- * Três palavras onde o contrato tem oito — e MISTURANDO REFERENCIAIS: *esquerda/direita* é relativo à TELA,
186
- * *à frente* é relativo ao CORPO, e quem ouve não tem como saber de que origem cada uma fala. Pior: tudo o
187
- * que estivesse acima ou abaixo da criança virava «à frente», que é justamente a informação que mais falta
188
- * a quem não vê a tela — apagada por uma zona morta.
121
+ * Three words where the contract has eight — and MIXING FRAMES: left/right is relative to the SCREEN, ahead is relative
122
+ * to the BODY, and a listener cannot know which origin each one speaks from. Worse: everything above or below the child
123
+ * became "ahead", exactly the information most missing for someone who cannot see the screen — erased by a dead zone.
189
124
  *
190
- * ⚠️ E O REFERENCIAL É DO JOGO. Num tabuleiro diz-se «a nordeste»; numa plataforma 2D vista de lado, norte
191
- * não quer dizer nada, e o que se diz é «às 2 horas».
125
+ * ⚠️ AND THE FRAME IS THE GAME'S. On a board one says "to the north-east"; in a 2D platformer seen from the side, north
126
+ * means nothing, and what one says is "at 2 o'clock".
192
127
  */
193
- function emPalavras(r) {
128
+ function inWords(r) {
194
129
  if (r.kind === 'none')
195
130
  return t('sr.nav.here');
196
- // Uma chave com `{h}` e não doze — mas a forma do singular é sua, porque «às 1 horas» não é português
197
- // (nem «a las 1» é espanhol). Em inglês as duas coincidem, e coincidir não é motivo para não a ter.
131
+ // One key with `{h}` and not twelve — but the singular has its own, because "at 1 hours" is not a sentence in any of
132
+ // the three languages the way the plural key would write it. Where two forms coincide, having both costs nothing.
198
133
  if (r.kind === 'clock')
199
134
  return r.hour === 1 ? t('sr.nav.clockOne') : t('sr.nav.clock', { h: r.hour });
200
135
  return t('sr.nav.dir.' + r.heading);
201
136
  }
202
- function alvoMaisProximo(pl) {
203
- const topo = ctx.topology();
204
- const aqui = { x: pl.x, y: pl.y };
205
- let melhor = null, bd = Infinity;
206
- for (const alvo of ctx.targetsOf(pl.i)) {
207
- const d = distance(topo, aqui, alvo);
137
+ /**
138
+ * This player's nearest target, in the DECLARED METRIC — and `null` if there is none.
139
+ *
140
+ * It was a loop over coins that skipped the taken and the unowned and measured with `Math.hypot`. The three things it
141
+ * knew about the game (that targets are coins, that coins have owners, that distance is Euclidean in pixels) became a
142
+ * question to the contract and a call to `distance`.
143
+ */
144
+ function nearestSpot(pl) {
145
+ const shape = ctx.topology();
146
+ const here = { x: pl.x, y: pl.y };
147
+ let nearest = null, bd = Infinity;
148
+ for (const target of ctx.targetsOf(pl.i)) {
149
+ const d = distance(shape, here, target);
208
150
  if (d < bd) {
209
151
  bd = d;
210
- melhor = alvo;
152
+ nearest = target;
211
153
  }
212
154
  }
213
- return melhor ? { at: melhor, d: bd } : null;
155
+ return nearest ? { at: nearest, d: bd } : null;
214
156
  }
215
157
  /**
216
- * "Perto" em PASSOS da métrica declarada, e não em pixels.
158
+ * "Near" in STEPS of the declared metric, not in pixels.
217
159
  *
218
- * Os limiares de 4 e 9 tiles do original viram 4 e 9 UNIDADES: numa plataforma com `unit = TILE` a conta é
219
- * a mesma de antes, letra por letra; numa grade são quatro e nove casas; num quiz, quatro e nove itens de
220
- * distância na lista. É a mesma frase para a criança em qualquer gênero, que é o ponto do contrato.
160
+ * The original thresholds of 4 and 9 tiles become 4 and 9 UNITS: in a platformer with `unit = TILE` the sum is the same
161
+ * as before; on a grid it is four and nine squares; in a quiz, four and nine items away in the list. The same sentence
162
+ * for the child in any genre, which is the contract's point.
163
+ */
164
+ const distanceKey = (d) => d < 4 ? 'sr.nav.veryClose' : d < 9 ? 'sr.nav.close' : 'sr.nav.far';
165
+ /**
166
+ * THE SONAR: a tone that points, and words (ADR-0234). The tone is the same with or without text on screen — pitch says how
167
+ * near the nearest target is, the pan which side, and a low tone that there is none. The WORDS are what is on the screen
168
+ * when there is text there, read now; only a screen with no text the engine can read gets the navigation sentence.
221
169
  */
222
- const chaveDeDistancia = (d) => d < 4 ? 'sr.nav.veryClose' : d < 9 ? 'sr.nav.close' : 'sr.nav.far';
223
170
  function sonar(pl) {
224
171
  _sonarCount++;
225
172
  const pc = playerCtx(pl);
226
- const alvo = alvoMaisProximo(pl);
227
- // A chave era `sr.nav.noCoinNear` — "Nenhuma moeda por perto." Um sonar que não sabe mais o que é o alvo
228
- // não pode dizer o nome dele no caso em que NÃO HÁ alvo nenhum: virou "Nada por perto.", que é verdade em
229
- // qualquer gênero. Foi o gate de fixtures que cobrou, ao acusar a palavra dentro do teste novo.
230
- if (!alvo) {
173
+ const target = nearestSpot(pl);
174
+ if (target)
175
+ ctx.tonePan(380 + 740 * Math.max(0, 1 - target.d / 12), 0.16, 'sonar', panFor(target.at.x, pl), 0.26, 'sine', pc); // nearer = higher
176
+ else
231
177
  ctx.tonePan(300, 0.2, 'sonar', 0, 0.2, 'sine', pc);
178
+ const onScreen = ctx.screenText?.() ?? '';
179
+ if (onScreen) {
180
+ ctx.srSay(onScreen);
181
+ ctx.narrate(onScreen, pl.i);
182
+ return;
183
+ }
184
+ // A sonar that no longer knows what the target is cannot name it when there is NO target at all: it says "nothing
185
+ // nearby", which is true in any genre.
186
+ if (!target) {
232
187
  ctx.srSay(t('sr.nav.noTargetNear'));
233
188
  return;
234
189
  }
235
- const pan = panFor(alvo.at.x, pl), near = Math.max(0, 1 - alvo.d / 12);
236
- ctx.tonePan(380 + 740 * near, 0.16, 'sonar', pan, 0.26, 'sine', pc); // mais perto = mais agudo
237
- // O NOME vem do jogo (campo 3). Antes era `t('sr.nav.coin')` — a engine dizia "moeda" porque só conhecia
238
- // moedas. O fallback existe para o jogo que declara alvo sem nome: melhor "alvo" do que uma chave crua.
239
- const nome = ctx.nameAt(alvo.at);
240
- const corpo = t('sr.nav.sonarFound', {
241
- alvo: nome ? nome.text : t('sr.nav.target'),
242
- lado: emPalavras(bearing(ctx.topology(), { x: pl.x, y: pl.y }, alvo.at)),
243
- dist: t(chaveDeDistancia(alvo.d)),
190
+ // The NAME comes from the game (field 3); the engine used to say "coin" because it only knew coins. The fallback is
191
+ // for a game that declares a target without a name: "target" is better than a raw key.
192
+ const name = ctx.nameAt(target.at);
193
+ const foundSentence = t('sr.nav.sonarFound', {
194
+ alvo: name ? name.text : t('sr.nav.target'),
195
+ lado: inWords(bearing(ctx.topology(), { x: pl.x, y: pl.y }, target.at)),
196
+ dist: t(distanceKey(target.d)),
244
197
  });
245
- const msg = (ctx.getNumPlayers() > 1 ? t('sr.player.prefix', { n: pl.i + 1 }) : '') + corpo;
198
+ const msg = (ctx.getNumPlayers() > 1 ? t('sr.player.prefix', { n: pl.i + 1 }) : '') + foundSentence;
246
199
  ctx.srSay(msg);
247
- ctx.narrate(msg);
248
- }
249
- /**
250
- * QUANTOS PASSOS FALTAM, e a resposta preferida é a que contorna parede.
251
- *
252
- * ⚠️ AS DUAS RESPOSTAS JÁ ESTÃO NA MESMA UNIDADE, e é a única razão pela qual esta função é uma linha em vez
253
- * de uma conversão: `rotaAte().passos` conta passos por definição, e `distance()` também devolve passos em
254
- * TODA topologia — ela própria divide pela `unit` no ramo contínuo. Dividir aqui outra vez pelo passo do
255
- * mundo era o erro à espera de ser cometido, e num jogo com `unit = 16` ele poria o guia no brilho máximo
256
- * para sempre. É o mesmo defeito que a #121 tirou do `panFor`: misturar régua de mundo com régua de ecrã.
257
- *
258
- * A rota perde-se de duas maneiras — jogo que não injectou `roleAt`, e orçamento estourado — e as duas caem
259
- * no mesmo recuo: a RETA. ⚠️ Ela mente atrás de parede (diz «perto» de um alvo que exige dar a volta), e é
260
- * por isso que é recuo e não escolha. Mas é o que o guia já dizia antes desta mudança, e continuar a dizê-lo
261
- * é estritamente melhor do que calar — calar afirmaria que não há alvo.
262
- */
263
- function passosAteOAlvo(pl, alvo) {
264
- const roleAt = ctx.roleAt;
265
- if (roleAt) {
266
- const rota = rotaAte({ topology: ctx.topology(), roleAt, orcamento: ORCAMENTO_DA_ROTA }, { x: pl.x, y: pl.y }, [alvo.at]);
267
- if (rota)
268
- return rota.passos;
269
- }
270
- return alvo.d;
271
- }
272
- /** Acende o grafo contínuo deste jogador. `null` = não deu (sem contexto, ou motor sem Web Audio). */
273
- function ligarGuia(pl) {
274
- const pc = playerCtx(pl);
275
- const ac = pc ? pc.ac : ctx.getAudioCtx();
276
- if (!ac)
277
- return null;
278
- try {
279
- const osc = ac.createOscillator(), filtro = ac.createBiquadFilter(), ganho = ac.createGain();
280
- osc.type = GUIA_TIPO;
281
- osc.frequency.value = GUIA_HZ;
282
- filtro.type = 'lowpass';
283
- filtro.frequency.value = CORTE_LONGE; // nasce no fundo da escala e sobe; nascer aberto seria um susto
284
- ganho.gain.value = 0; // e nasce calado, para não estalar ao ligar
285
- let saida = ganho;
286
- let panner = null;
287
- if (ac.createStereoPanner) {
288
- panner = ac.createStereoPanner();
289
- ganho.connect(panner);
290
- saida = panner;
291
- }
292
- osc.connect(filtro).connect(ganho);
293
- saida.connect(pc ? pc.out : (ctx.catNode?.('guide') || ctx.audioOut?.() || ac.destination));
294
- osc.start();
295
- // `desdeARota` nasce no tecto para que a PRIMEIRA volta já meça a rota, em vez de soar doze quadros
296
- // com um `passos` inventado.
297
- return { ac, osc, filtro, ganho, panner, desdeARota: QUADROS_ENTRE_ROTAS, passos: PASSOS_ATE_O_FUNDO, pan: 0 };
298
- }
299
- catch (e) {
300
- return null;
301
- }
302
- }
303
- /**
304
- * Apaga o grafo — e ele TEM de ser apagado, porque um oscilador que fica é a diferença entre esta forma e a
305
- * anterior. O bipe morria sozinho ao fim de 0,12 s; este toca até alguém o parar. Sem esta função, desligar
306
- * a categoria `guide` no mixer deixaria o som a tocar, e trocar de modo visual deixaria um segundo grafo a
307
- * somar-se ao primeiro.
308
- *
309
- * Desce em rampa (não corta) porque um corte seco num oscilador vivo é um clique — um transiente, que é
310
- * precisamente o que este item existe para tirar do ouvido da criança.
311
- */
312
- function desligarGuia(pl) {
313
- const g = pl._guia;
314
- if (!g)
315
- return;
316
- pl._guia = null;
317
- try {
318
- const agora = g.ac.currentTime;
319
- g.ganho.gain.setTargetAtTime(0, agora, 0.05);
320
- g.osc.stop(agora + 0.3);
321
- }
322
- catch (e) { /* noop */ }
323
- }
324
- /**
325
- * A PRESENÇA CONTÍNUA, um quadro de cada vez (#84 item 2).
326
- *
327
- * ⚠️ O QUE SAIU DAQUI FOI UM BIPE: um `triangle` de 0,12 s a cada 48 quadros, para sempre, independente de a
328
- * criança se mexer ou de algo ter mudado. O veredicto do Dev: «um ping é a pior escolha possível, tenebroso
329
- * para quem tem TEA». O que entra não dispara nada — o som já está lá, e muda de brilho.
330
- *
331
- * ⚠️ E CALAR CONTINUA A SER UMA AFIRMAÇÃO, com um significado só: NÃO HÁ ALVO. É por isso que «sem alvo»
332
- * apaga o grafo e «longe» não: o piso do `guide-intensity` (`VOL_LONGE`) existe exactamente para que a
333
- * criança não confunda «está longe» com «não há nada para achar».
334
- */
335
- function updateGuide() {
336
- const cat = ctx.getAudioCat();
337
- const ligado = !!ctx.getAudioCtx() && ctx.getSoundOn() && !!cat && !!cat.guide && cat.guide.on;
338
- const vol = ctx.getVolume ? ctx.getVolume() : 1;
339
- for (const pl of ctx.getPlayers()) {
340
- if (!ligado || !needsAudioCues(pl)) {
341
- desligarGuia(pl);
342
- continue;
343
- }
344
- let g = pl._guia;
345
- if (!g) {
346
- // ⚠️ A PERGUNTA «HÁ ALVO?» VEM ANTES DE ACENDER, e o gate cobrou-a: com o grafo a nascer primeiro, um
347
- // jogador sem alvo criava um oscilador, media a rota, não achava nada e apagava-o — SESSENTA VEZES
348
- // POR SEGUNDO. O bipe não tinha este problema porque não tinha nada que durasse; foi a permanência
349
- // que o trouxe. `alvoMaisProximo` é um laço sobre `targetsOf`, não a BFS: perguntar por quadro custa
350
- // zero quando a lista está vazia, que é exactamente o caso em questão.
351
- if (!alvoMaisProximo(pl))
352
- continue;
353
- g = pl._guia = ligarGuia(pl);
354
- if (!g)
355
- continue;
356
- }
357
- if (++g.desdeARota >= QUADROS_ENTRE_ROTAS) {
358
- g.desdeARota = 0;
359
- const alvo = alvoMaisProximo(pl);
360
- if (!alvo) {
361
- desligarGuia(pl);
362
- continue;
363
- }
364
- g.passos = passosAteOAlvo(pl, alvo);
365
- g.pan = panFor(alvo.at.x, pl);
366
- }
367
- // TODO quadro, e não só quando a rota é nova: é isto que faz a mudança ser um deslize.
368
- const i = intensidadeDoGuia(g.passos);
369
- try {
370
- const agora = g.ac.currentTime;
371
- g.filtro.frequency.setTargetAtTime(i.corte, agora, TAU_DO_GUIA);
372
- g.ganho.gain.setTargetAtTime(GUIA_VOL * i.volume * vol, agora, TAU_DO_GUIA);
373
- g.panner?.pan.setTargetAtTime(g.pan, agora, TAU_DO_GUIA);
374
- }
375
- catch (e) { /* noop */ }
376
- _guideCount++;
377
- }
200
+ ctx.narrate(msg, pl.i);
378
201
  }
379
202
  return {
380
- playerCtx, panFor, needsAudioCues, sonar, updateGuide,
203
+ playerCtx, panFor, needsAudioCues, sonar,
381
204
  get sonarCount() { return _sonarCount; },
382
- get guideCount() { return _guideCount; },
383
205
  };
384
206
  }