@reicek/neataptic-ts 0.1.21 → 0.1.23

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 (361) hide show
  1. package/.github/agents/boundary-mapper.agent.md +31 -0
  2. package/.github/agents/docs-scout.agent.md +29 -0
  3. package/.github/agents/plan-scout.agent.md +31 -0
  4. package/.github/agents/solid-split.agent.md +143 -0
  5. package/.github/copilot-instructions.md +119 -0
  6. package/.github/skills/solid-split-playbook/SKILL.md +220 -0
  7. package/.github/skills/solid-split-playbook/assets/docs-checklist.md +34 -0
  8. package/.github/skills/solid-split-playbook/assets/split-plan-template.md +48 -0
  9. package/.github/skills/solid-split-playbook/assets/split-workflow-checklist.md +51 -0
  10. package/.github/skills/trace-analyzer-extension/SKILL.md +63 -0
  11. package/.github/skills/trace-analyzer-extension/assets/extension-checklist.md +24 -0
  12. package/.github/skills/trace-analyzer-extension/references/analyzer-extension-workflow.md +101 -0
  13. package/.github/skills/trace-audit-reporting/SKILL.md +96 -0
  14. package/.github/skills/trace-audit-reporting/assets/performance-report-template.md +123 -0
  15. package/.github/skills/trace-audit-reporting/references/trace-analysis-workflow.md +132 -0
  16. package/package.json +7 -3
  17. package/plans/ES2023 migration +13 -8
  18. package/plans/Evolution_Training_Interoperability_Contracts.md +1 -1
  19. package/plans/Flappy_Bird_Folder_Documentation_Pass.md +53 -0
  20. package/plans/Flappy_Evolution_Worker_Documentation_Pass.md +58 -0
  21. package/plans/Interactive_Examples_and_Learning_Path.md +10 -2
  22. package/plans/Memory_Optimization.md +3 -3
  23. package/plans/README.md +63 -0
  24. package/plans/Roadmap.md +15 -3
  25. package/plans/asciiMaze_SOLID_split.done.md +130 -0
  26. package/plans/flappy_bird_SOLID_split.done.md +67 -0
  27. package/scripts/analyze-trace.ts +590 -0
  28. package/scripts/assets/theme.css +221 -34
  29. package/scripts/copy-examples.mjs +9 -5
  30. package/scripts/export-onnx.mjs +3 -3
  31. package/scripts/generate-bench-tables.mjs +10 -10
  32. package/scripts/generate-bench-tables.ts +10 -10
  33. package/scripts/generate-docs.ts +1415 -449
  34. package/scripts/render-docs-html.ts +15 -8
  35. package/src/README.md +127 -222
  36. package/src/architecture/README.md +117 -184
  37. package/src/architecture/architect.ts +6 -0
  38. package/src/architecture/layer/README.md +38 -38
  39. package/src/architecture/network/README.md +49 -31
  40. package/src/architecture/network/activate/README.md +77 -77
  41. package/src/architecture/network/connect/README.md +15 -13
  42. package/src/architecture/network/deterministic/README.md +7 -7
  43. package/src/architecture/network/evolve/README.md +44 -44
  44. package/src/architecture/network/gating/README.md +20 -20
  45. package/src/architecture/network/genetic/README.md +51 -51
  46. package/src/architecture/network/mutate/README.md +97 -97
  47. package/src/architecture/network/network.types.ts +39 -0
  48. package/src/architecture/network/onnx/README.md +264 -264
  49. package/src/architecture/network/prune/README.md +39 -39
  50. package/src/architecture/network/remove/README.md +26 -26
  51. package/src/architecture/network/serialize/README.md +56 -56
  52. package/src/architecture/network/serialize/network.serialize.json.utils.ts +1 -0
  53. package/src/architecture/network/serialize/network.serialize.utils.ts +6 -1
  54. package/src/architecture/network/serialize/network.serialize.utils.types.ts +1 -1
  55. package/src/architecture/network/slab/README.md +61 -61
  56. package/src/architecture/network/standalone/README.md +24 -24
  57. package/src/architecture/network/stats/README.md +9 -9
  58. package/src/architecture/network/topology/README.md +46 -46
  59. package/src/architecture/network/training/README.md +21 -21
  60. package/src/architecture/network.ts +114 -10
  61. package/src/methods/README.md +9 -87
  62. package/src/multithreading/README.md +8 -77
  63. package/src/multithreading/workers/README.md +2 -2
  64. package/src/multithreading/workers/browser/README.md +0 -6
  65. package/src/multithreading/workers/node/README.md +0 -3
  66. package/src/neat/README.md +623 -568
  67. package/src/neat/neat.evolve.population.utils.ts +29 -5
  68. package/src/neat/neat.helpers.ts +16 -0
  69. package/src/neat/neat.topology-intent.utils.ts +160 -0
  70. package/src/utils/README.md +18 -18
  71. package/test/examples/asciiMaze/README.md +59 -59
  72. package/test/examples/asciiMaze/asciiMaze.e2e.test.ts +14 -9
  73. package/test/examples/asciiMaze/browser-entry/README.md +196 -0
  74. package/test/examples/asciiMaze/browser-entry/browser-entry.abort.services.ts +95 -0
  75. package/test/examples/asciiMaze/browser-entry/browser-entry.constants.ts +23 -0
  76. package/test/examples/asciiMaze/browser-entry/browser-entry.curriculum.services.ts +115 -0
  77. package/test/examples/asciiMaze/browser-entry/browser-entry.globals.services.ts +106 -0
  78. package/test/examples/asciiMaze/browser-entry/browser-entry.host.services.ts +157 -0
  79. package/test/examples/asciiMaze/browser-entry/browser-entry.services.ts +14 -0
  80. package/test/examples/asciiMaze/browser-entry/browser-entry.ts +129 -0
  81. package/test/examples/asciiMaze/browser-entry/browser-entry.types.ts +120 -0
  82. package/test/examples/asciiMaze/browser-entry/browser-entry.utils.ts +98 -0
  83. package/test/examples/asciiMaze/browser-entry.ts +10 -576
  84. package/test/examples/asciiMaze/dashboardManager/README.md +276 -0
  85. package/test/examples/asciiMaze/dashboardManager/archive/README.md +16 -0
  86. package/test/examples/asciiMaze/dashboardManager/archive/dashboardManager.archive.services.ts +267 -0
  87. package/test/examples/asciiMaze/dashboardManager/dashboardManager.constants.ts +35 -0
  88. package/test/examples/asciiMaze/dashboardManager/dashboardManager.services.ts +103 -0
  89. package/test/examples/asciiMaze/dashboardManager/dashboardManager.ts +181 -0
  90. package/test/examples/asciiMaze/dashboardManager/dashboardManager.types.ts +267 -0
  91. package/test/examples/asciiMaze/dashboardManager/dashboardManager.utils.ts +254 -0
  92. package/test/examples/asciiMaze/dashboardManager/live/README.md +14 -0
  93. package/test/examples/asciiMaze/dashboardManager/live/dashboardManager.live.services.ts +264 -0
  94. package/test/examples/asciiMaze/dashboardManager/telemetry/README.md +47 -0
  95. package/test/examples/asciiMaze/dashboardManager/telemetry/dashboardManager.telemetry.services.ts +513 -0
  96. package/test/examples/asciiMaze/dashboardManager.ts +13 -2335
  97. package/test/examples/asciiMaze/evolutionEngine/README.md +1058 -0
  98. package/test/examples/asciiMaze/evolutionEngine/curriculumPhase.ts +90 -0
  99. package/test/examples/asciiMaze/evolutionEngine/engineState.constants.ts +36 -0
  100. package/test/examples/asciiMaze/evolutionEngine/engineState.ts +58 -513
  101. package/test/examples/asciiMaze/evolutionEngine/engineState.types.ts +212 -0
  102. package/test/examples/asciiMaze/evolutionEngine/engineState.utils.ts +301 -0
  103. package/test/examples/asciiMaze/evolutionEngine/evolutionEngine.types.ts +445 -0
  104. package/test/examples/asciiMaze/evolutionEngine/evolutionLoop.ts +81 -50
  105. package/test/examples/asciiMaze/evolutionEngine/optionsAndSetup.ts +2 -4
  106. package/test/examples/asciiMaze/evolutionEngine/populationDynamics.ts +17 -33
  107. package/test/examples/asciiMaze/evolutionEngine/populationPruning.ts +1 -1
  108. package/test/examples/asciiMaze/evolutionEngine/rngAndTiming.ts +1 -2
  109. package/test/examples/asciiMaze/evolutionEngine/sampling.ts +1 -1
  110. package/test/examples/asciiMaze/evolutionEngine/scratchPools.ts +2 -5
  111. package/test/examples/asciiMaze/evolutionEngine/setupHelpers.ts +30 -37
  112. package/test/examples/asciiMaze/evolutionEngine/telemetryMetrics.ts +16 -58
  113. package/test/examples/asciiMaze/evolutionEngine/trainingWarmStart.ts +2 -2
  114. package/test/examples/asciiMaze/evolutionEngine.ts +55 -55
  115. package/test/examples/asciiMaze/fitness.ts +2 -2
  116. package/test/examples/asciiMaze/fitness.types.ts +65 -0
  117. package/test/examples/asciiMaze/interfaces.ts +64 -1352
  118. package/test/examples/asciiMaze/mazeMovement/README.md +356 -0
  119. package/test/examples/asciiMaze/mazeMovement/finalization/README.md +49 -0
  120. package/test/examples/asciiMaze/mazeMovement/finalization/mazeMovement.finalization.ts +138 -0
  121. package/test/examples/asciiMaze/mazeMovement/mazeMovement.constants.ts +101 -0
  122. package/test/examples/asciiMaze/mazeMovement/mazeMovement.services.ts +230 -0
  123. package/test/examples/asciiMaze/mazeMovement/mazeMovement.ts +299 -0
  124. package/test/examples/asciiMaze/mazeMovement/mazeMovement.types.ts +185 -0
  125. package/test/examples/asciiMaze/mazeMovement/mazeMovement.utils.ts +153 -0
  126. package/test/examples/asciiMaze/mazeMovement/policy/README.md +91 -0
  127. package/test/examples/asciiMaze/mazeMovement/policy/mazeMovement.policy.ts +467 -0
  128. package/test/examples/asciiMaze/mazeMovement/runtime/README.md +95 -0
  129. package/test/examples/asciiMaze/mazeMovement/runtime/mazeMovement.runtime.ts +354 -0
  130. package/test/examples/asciiMaze/mazeMovement/shaping/README.md +124 -0
  131. package/test/examples/asciiMaze/mazeMovement/shaping/mazeMovement.shaping.ts +459 -0
  132. package/test/examples/asciiMaze/mazeMovement.ts +12 -2978
  133. package/test/examples/flappy_bird/README.md +193 -88
  134. package/test/examples/flappy_bird/browser-entry/README.md +1441 -0
  135. package/test/examples/flappy_bird/browser-entry/browser-entry.host.utils.ts +4 -324
  136. package/test/examples/flappy_bird/browser-entry/browser-entry.network-view.utils.ts +9 -396
  137. package/test/examples/flappy_bird/browser-entry/browser-entry.playback.utils.ts +6 -714
  138. package/test/examples/flappy_bird/browser-entry/browser-entry.render.types.ts +26 -3
  139. package/test/examples/flappy_bird/browser-entry/browser-entry.runtime.types.ts +16 -1
  140. package/test/examples/flappy_bird/browser-entry/browser-entry.simulation.types.ts +39 -5
  141. package/test/examples/flappy_bird/browser-entry/browser-entry.spawn.utils.ts +11 -31
  142. package/test/examples/flappy_bird/browser-entry/browser-entry.stats.types.ts +32 -4
  143. package/test/examples/flappy_bird/browser-entry/browser-entry.ts +11 -0
  144. package/test/examples/flappy_bird/browser-entry/browser-entry.types.ts +8 -0
  145. package/test/examples/flappy_bird/browser-entry/browser-entry.visualization.types.ts +50 -7
  146. package/test/examples/flappy_bird/browser-entry/browser-entry.visualization.utils.ts +21 -893
  147. package/test/examples/flappy_bird/browser-entry/browser-entry.worker.types.ts +91 -10
  148. package/test/examples/flappy_bird/browser-entry/host/README.md +318 -0
  149. package/test/examples/flappy_bird/browser-entry/host/host.canvas.service.ts +16 -0
  150. package/test/examples/flappy_bird/browser-entry/host/host.constants.ts +20 -0
  151. package/test/examples/flappy_bird/browser-entry/host/host.dom.service.ts +10 -0
  152. package/test/examples/flappy_bird/browser-entry/host/host.resize.service.ts +1 -295
  153. package/test/examples/flappy_bird/browser-entry/host/host.stats.service.ts +14 -0
  154. package/test/examples/flappy_bird/browser-entry/host/host.ts +592 -6
  155. package/test/examples/flappy_bird/browser-entry/host/host.types.ts +13 -0
  156. package/test/examples/flappy_bird/browser-entry/host/resize/README.md +309 -0
  157. package/test/examples/flappy_bird/browser-entry/host/resize/host.resize.service.constants.ts +47 -0
  158. package/test/examples/flappy_bird/browser-entry/host/resize/host.resize.service.services.ts +392 -0
  159. package/test/examples/flappy_bird/browser-entry/host/resize/host.resize.service.ts +132 -0
  160. package/test/examples/flappy_bird/browser-entry/host/resize/host.resize.service.types.ts +92 -0
  161. package/test/examples/flappy_bird/browser-entry/host/resize/host.resize.service.utils.ts +272 -0
  162. package/test/examples/flappy_bird/browser-entry/network-view/README.md +389 -0
  163. package/test/examples/flappy_bird/browser-entry/network-view/network-view.draw.service.ts +13 -0
  164. package/test/examples/flappy_bird/browser-entry/network-view/network-view.labels.utils.ts +12 -0
  165. package/test/examples/flappy_bird/browser-entry/network-view/network-view.layout.utils.ts +14 -0
  166. package/test/examples/flappy_bird/browser-entry/network-view/network-view.topology.utils.ts +267 -0
  167. package/test/examples/flappy_bird/browser-entry/network-view/network-view.ts +823 -7
  168. package/test/examples/flappy_bird/browser-entry/network-view/network-view.types.ts +11 -0
  169. package/test/examples/flappy_bird/browser-entry/playback/README.md +845 -0
  170. package/test/examples/flappy_bird/browser-entry/playback/background/README.md +355 -0
  171. package/test/examples/flappy_bird/browser-entry/playback/background/ground-grid/README.md +1068 -0
  172. package/test/examples/flappy_bird/browser-entry/playback/background/ground-grid/playback.background.ground-grid.batch.services.ts +64 -0
  173. package/test/examples/flappy_bird/browser-entry/playback/background/ground-grid/playback.background.ground-grid.cache.services.ts +207 -0
  174. package/test/examples/flappy_bird/browser-entry/playback/background/ground-grid/playback.background.ground-grid.constants.ts +197 -0
  175. package/test/examples/flappy_bird/browser-entry/playback/background/ground-grid/playback.background.ground-grid.geometry.batch.utils.ts +114 -0
  176. package/test/examples/flappy_bird/browser-entry/playback/background/ground-grid/playback.background.ground-grid.geometry.layout.utils.test.ts +96 -0
  177. package/test/examples/flappy_bird/browser-entry/playback/background/ground-grid/playback.background.ground-grid.geometry.layout.utils.ts +204 -0
  178. package/test/examples/flappy_bird/browser-entry/playback/background/ground-grid/playback.background.ground-grid.geometry.services.ts +49 -0
  179. package/test/examples/flappy_bird/browser-entry/playback/background/ground-grid/playback.background.ground-grid.geometry.utils.ts +313 -0
  180. package/test/examples/flappy_bird/browser-entry/playback/background/ground-grid/playback.background.ground-grid.layer.services.ts +81 -0
  181. package/test/examples/flappy_bird/browser-entry/playback/background/ground-grid/playback.background.ground-grid.math.utils.test.ts +33 -0
  182. package/test/examples/flappy_bird/browser-entry/playback/background/ground-grid/playback.background.ground-grid.math.utils.ts +201 -0
  183. package/test/examples/flappy_bird/browser-entry/playback/background/ground-grid/playback.background.ground-grid.pulse.selection.utils.ts +171 -0
  184. package/test/examples/flappy_bird/browser-entry/playback/background/ground-grid/playback.background.ground-grid.pulse.timing.utils.ts +124 -0
  185. package/test/examples/flappy_bird/browser-entry/playback/background/ground-grid/playback.background.ground-grid.pulse.utils.test.ts +279 -0
  186. package/test/examples/flappy_bird/browser-entry/playback/background/ground-grid/playback.background.ground-grid.pulse.utils.ts +132 -0
  187. package/test/examples/flappy_bird/browser-entry/playback/background/ground-grid/playback.background.ground-grid.scene.services.ts +26 -0
  188. package/test/examples/flappy_bird/browser-entry/playback/background/ground-grid/playback.background.ground-grid.services.ts +65 -0
  189. package/test/examples/flappy_bird/browser-entry/playback/background/ground-grid/playback.background.ground-grid.ts +48 -0
  190. package/test/examples/flappy_bird/browser-entry/playback/background/ground-grid/playback.background.ground-grid.types.ts +342 -0
  191. package/test/examples/flappy_bird/browser-entry/playback/background/ground-grid/playback.background.ground-grid.utils.ts +10 -0
  192. package/test/examples/flappy_bird/browser-entry/playback/background/playback.background.cache.services.ts +96 -0
  193. package/test/examples/flappy_bird/browser-entry/playback/background/playback.background.constants.ts +127 -0
  194. package/test/examples/flappy_bird/browser-entry/playback/background/playback.background.draw.services.ts +184 -0
  195. package/test/examples/flappy_bird/browser-entry/playback/background/playback.background.scene.services.ts +64 -0
  196. package/test/examples/flappy_bird/browser-entry/playback/background/playback.background.services.ts +6 -0
  197. package/test/examples/flappy_bird/browser-entry/playback/background/playback.background.ts +53 -0
  198. package/test/examples/flappy_bird/browser-entry/playback/background/playback.background.types.ts +105 -0
  199. package/test/examples/flappy_bird/browser-entry/playback/background/playback.background.utils.ts +100 -0
  200. package/test/examples/flappy_bird/browser-entry/playback/frame-render/README.md +541 -0
  201. package/test/examples/flappy_bird/browser-entry/playback/frame-render/playback.frame-render.bird.utils.ts +180 -0
  202. package/test/examples/flappy_bird/browser-entry/playback/frame-render/playback.frame-render.canvas.services.ts +77 -0
  203. package/test/examples/flappy_bird/browser-entry/playback/frame-render/playback.frame-render.entity.services.ts +167 -0
  204. package/test/examples/flappy_bird/browser-entry/playback/frame-render/playback.frame-render.scene.services.ts +57 -0
  205. package/test/examples/flappy_bird/browser-entry/playback/frame-render/playback.frame-render.service.test.ts +176 -0
  206. package/test/examples/flappy_bird/browser-entry/playback/frame-render/playback.frame-render.service.ts +113 -0
  207. package/test/examples/flappy_bird/browser-entry/playback/frame-render/playback.frame-render.services.ts +35 -0
  208. package/test/examples/flappy_bird/browser-entry/playback/frame-render/playback.frame-render.trail.utils.ts +248 -0
  209. package/test/examples/flappy_bird/browser-entry/playback/frame-render/playback.frame-render.types.ts +103 -0
  210. package/test/examples/flappy_bird/browser-entry/playback/frame-render/playback.frame-render.utils.ts +11 -0
  211. package/test/examples/flappy_bird/browser-entry/playback/playback.constants.ts +1 -1
  212. package/test/examples/flappy_bird/browser-entry/playback/playback.frame-render.service.ts +10 -0
  213. package/test/examples/flappy_bird/browser-entry/playback/playback.iteration.services.ts +192 -0
  214. package/test/examples/flappy_bird/browser-entry/playback/playback.loop.service.ts +12 -0
  215. package/test/examples/flappy_bird/browser-entry/playback/playback.orchestration.types.ts +78 -0
  216. package/test/examples/flappy_bird/browser-entry/playback/playback.render.pipe-outline.service.ts +128 -0
  217. package/test/examples/flappy_bird/browser-entry/playback/playback.render.service.ts +1 -116
  218. package/test/examples/flappy_bird/browser-entry/playback/playback.session.services.ts +184 -0
  219. package/test/examples/flappy_bird/browser-entry/playback/playback.snapshot.utils.test.ts +121 -0
  220. package/test/examples/flappy_bird/browser-entry/playback/playback.snapshot.utils.ts +8 -0
  221. package/test/examples/flappy_bird/browser-entry/playback/playback.starfield.layer.services.ts +36 -0
  222. package/test/examples/flappy_bird/browser-entry/playback/playback.starfield.service.ts +11 -128
  223. package/test/examples/flappy_bird/browser-entry/playback/playback.starfield.services.ts +268 -0
  224. package/test/examples/flappy_bird/browser-entry/playback/playback.starfield.types.ts +91 -0
  225. package/test/examples/flappy_bird/browser-entry/playback/playback.starfield.utils.ts +11 -4
  226. package/test/examples/flappy_bird/browser-entry/playback/playback.trail.utils.ts +9 -86
  227. package/test/examples/flappy_bird/browser-entry/playback/playback.ts +75 -7
  228. package/test/examples/flappy_bird/browser-entry/playback/playback.types.ts +12 -9
  229. package/test/examples/flappy_bird/browser-entry/playback/playback.worker-channel.utils.ts +11 -123
  230. package/test/examples/flappy_bird/browser-entry/playback/snapshot/README.md +55 -0
  231. package/test/examples/flappy_bird/browser-entry/playback/snapshot/playback.snapshot.services.ts +103 -0
  232. package/test/examples/flappy_bird/browser-entry/playback/snapshot/playback.snapshot.summary.utils.test.ts +45 -0
  233. package/test/examples/flappy_bird/browser-entry/playback/snapshot/playback.snapshot.summary.utils.ts +28 -0
  234. package/test/examples/flappy_bird/browser-entry/playback/trail/README.md +95 -0
  235. package/test/examples/flappy_bird/browser-entry/playback/trail/playback.trail.history.services.test.ts +35 -0
  236. package/test/examples/flappy_bird/browser-entry/playback/trail/playback.trail.history.services.ts +64 -0
  237. package/test/examples/flappy_bird/browser-entry/playback/trail/playback.trail.opacity.utils.test.ts +37 -0
  238. package/test/examples/flappy_bird/browser-entry/playback/trail/playback.trail.opacity.utils.ts +74 -0
  239. package/test/examples/flappy_bird/browser-entry/playback/worker-channel/README.md +71 -0
  240. package/test/examples/flappy_bird/browser-entry/playback/worker-channel/playback.worker-channel.request.services.ts +45 -0
  241. package/test/examples/flappy_bird/browser-entry/playback/worker-channel/playback.worker-channel.summary.services.ts +74 -0
  242. package/test/examples/flappy_bird/browser-entry/playback/worker-channel/playback.worker-channel.types.ts +53 -0
  243. package/test/examples/flappy_bird/browser-entry/runtime/README.md +304 -0
  244. package/test/examples/flappy_bird/browser-entry/runtime/runtime.browser-globals.service.ts +15 -0
  245. package/test/examples/flappy_bird/browser-entry/runtime/runtime.errors.ts +17 -0
  246. package/test/examples/flappy_bird/browser-entry/runtime/runtime.evolution-launch.service.ts +56 -0
  247. package/test/examples/flappy_bird/browser-entry/runtime/runtime.evolution-loop.service.ts +19 -0
  248. package/test/examples/flappy_bird/browser-entry/runtime/runtime.lifecycle.service.ts +96 -0
  249. package/test/examples/flappy_bird/browser-entry/runtime/runtime.startup.service.ts +92 -0
  250. package/test/examples/flappy_bird/browser-entry/runtime/runtime.telemetry.service.ts +24 -0
  251. package/test/examples/flappy_bird/browser-entry/runtime/runtime.ts +31 -121
  252. package/test/examples/flappy_bird/browser-entry/runtime/runtime.types.ts +65 -0
  253. package/test/examples/flappy_bird/browser-entry/visualization/README.md +568 -0
  254. package/test/examples/flappy_bird/browser-entry/visualization/visualization.colors.utils.ts +26 -0
  255. package/test/examples/flappy_bird/browser-entry/visualization/visualization.constants.ts +110 -0
  256. package/test/examples/flappy_bird/browser-entry/visualization/visualization.draw.service.ts +979 -19
  257. package/test/examples/flappy_bird/browser-entry/visualization/visualization.legend.utils.ts +157 -3
  258. package/test/examples/flappy_bird/browser-entry/visualization/visualization.topology.utils.ts +13 -27
  259. package/test/examples/flappy_bird/browser-entry/visualization/visualization.ts +7 -20
  260. package/test/examples/flappy_bird/browser-entry/visualization/visualization.types.ts +14 -0
  261. package/test/examples/flappy_bird/browser-entry/worker-channel/README.md +238 -0
  262. package/test/examples/flappy_bird/browser-entry/worker-channel/worker-channel.errors.ts +11 -0
  263. package/test/examples/flappy_bird/browser-entry/worker-channel/worker-channel.generation.service.ts +12 -0
  264. package/test/examples/flappy_bird/browser-entry/worker-channel/worker-channel.playback.service.test.ts +143 -0
  265. package/test/examples/flappy_bird/browser-entry/worker-channel/worker-channel.playback.service.ts +140 -14
  266. package/test/examples/flappy_bird/browser-entry/worker-channel/worker-channel.request.service.ts +27 -0
  267. package/test/examples/flappy_bird/browser-entry/worker-channel/worker-channel.ts +8 -0
  268. package/test/examples/flappy_bird/browser-entry/worker-channel/worker-channel.types.ts +23 -0
  269. package/test/examples/flappy_bird/browser-entry/worker-channel/worker-channel.url.service.ts +5 -0
  270. package/test/examples/flappy_bird/constants/README.md +1163 -0
  271. package/test/examples/flappy_bird/constants/constants.birds.ts +16 -38
  272. package/test/examples/flappy_bird/constants/constants.difficulty.ts +21 -0
  273. package/test/examples/flappy_bird/constants/constants.network-view.ts +24 -0
  274. package/test/examples/flappy_bird/constants/constants.network.ts +1 -1
  275. package/test/examples/flappy_bird/constants/constants.observation.ts +7 -0
  276. package/test/examples/flappy_bird/constants/constants.palette.ts +9 -2
  277. package/test/examples/flappy_bird/constants/constants.physics.ts +9 -0
  278. package/test/examples/flappy_bird/constants/constants.pipe-render.ts +3 -0
  279. package/test/examples/flappy_bird/constants/constants.pipes.ts +22 -3
  280. package/test/examples/flappy_bird/constants/constants.runtime.ts +28 -4
  281. package/test/examples/flappy_bird/constants/constants.starfield.ts +78 -3
  282. package/test/examples/flappy_bird/constants/constants.ts +6 -0
  283. package/test/examples/flappy_bird/environment/README.md +182 -0
  284. package/test/examples/flappy_bird/environment/environment.collision.utils.ts +7 -0
  285. package/test/examples/flappy_bird/environment/environment.constants.ts +16 -3
  286. package/test/examples/flappy_bird/environment/environment.observation.utils.ts +12 -19
  287. package/test/examples/flappy_bird/environment/environment.state.service.ts +10 -0
  288. package/test/examples/flappy_bird/environment/environment.step.service.ts +15 -66
  289. package/test/examples/flappy_bird/environment/environment.types.ts +14 -0
  290. package/test/examples/flappy_bird/evaluation/README.md +155 -0
  291. package/test/examples/flappy_bird/evaluation/evaluation.constants.ts +23 -4
  292. package/test/examples/flappy_bird/evaluation/evaluation.fitness.utils.ts +16 -1
  293. package/test/examples/flappy_bird/evaluation/evaluation.rollout.service.ts +7 -374
  294. package/test/examples/flappy_bird/evaluation/evaluation.seed.utils.ts +4 -0
  295. package/test/examples/flappy_bird/evaluation/evaluation.types.ts +18 -2
  296. package/test/examples/flappy_bird/evaluation/rollout/README.md +355 -0
  297. package/test/examples/flappy_bird/evaluation/rollout/evaluation.rollout.constants.ts +38 -0
  298. package/test/examples/flappy_bird/evaluation/rollout/evaluation.rollout.service.ts +71 -0
  299. package/test/examples/flappy_bird/evaluation/rollout/evaluation.rollout.services.ts +338 -0
  300. package/test/examples/flappy_bird/evaluation/rollout/evaluation.rollout.types.ts +69 -0
  301. package/test/examples/flappy_bird/evaluation/rollout/evaluation.rollout.utils.ts +399 -0
  302. package/test/examples/flappy_bird/flappy-evolution-worker/README.md +845 -0
  303. package/test/examples/flappy_bird/flappy-evolution-worker/flappy-evolution-worker.constants.ts +49 -7
  304. package/test/examples/flappy_bird/flappy-evolution-worker/flappy-evolution-worker.errors.ts +34 -3
  305. package/test/examples/flappy_bird/flappy-evolution-worker/flappy-evolution-worker.evolution.service.ts +22 -0
  306. package/test/examples/flappy_bird/flappy-evolution-worker/flappy-evolution-worker.playback.service.ts +62 -26
  307. package/test/examples/flappy_bird/flappy-evolution-worker/flappy-evolution-worker.protocol.service.ts +27 -1
  308. package/test/examples/flappy_bird/flappy-evolution-worker/flappy-evolution-worker.runtime.service.ts +23 -0
  309. package/test/examples/flappy_bird/flappy-evolution-worker/flappy-evolution-worker.simulation.frame.service.ts +378 -0
  310. package/test/examples/flappy_bird/flappy-evolution-worker/flappy-evolution-worker.simulation.types.ts +22 -0
  311. package/test/examples/flappy_bird/flappy-evolution-worker/flappy-evolution-worker.simulation.utils.ts +20 -203
  312. package/test/examples/flappy_bird/flappy-evolution-worker/flappy-evolution-worker.snapshot.utils.test.ts +94 -0
  313. package/test/examples/flappy_bird/flappy-evolution-worker/flappy-evolution-worker.snapshot.utils.ts +78 -13
  314. package/test/examples/flappy_bird/flappy-evolution-worker/flappy-evolution-worker.ts +235 -344
  315. package/test/examples/flappy_bird/flappy-evolution-worker/flappy-evolution-worker.types.ts +170 -22
  316. package/test/examples/flappy_bird/flappy-evolution-worker/flappy-evolution-worker.warm-start.service.ts +314 -0
  317. package/test/examples/flappy_bird/flappy.simulation.shared.utils.ts +17 -0
  318. package/test/examples/flappy_bird/flappyEnvironment.ts +21 -0
  319. package/test/examples/flappy_bird/flappyEvaluation.ts +12 -0
  320. package/test/examples/flappy_bird/flappyEvolution.worker.ts +7 -0
  321. package/test/examples/flappy_bird/index.ts +8 -2
  322. package/test/examples/flappy_bird/rng.ts +10 -0
  323. package/test/examples/flappy_bird/simulation-shared/README.md +518 -0
  324. package/test/examples/flappy_bird/simulation-shared/observation/README.md +255 -0
  325. package/test/examples/flappy_bird/simulation-shared/observation/observation.features.utils.ts +339 -0
  326. package/test/examples/flappy_bird/simulation-shared/observation/observation.ts +19 -0
  327. package/test/examples/flappy_bird/simulation-shared/observation/observation.vector.utils.ts +81 -0
  328. package/test/examples/flappy_bird/simulation-shared/simulation-shared.constants.ts +3 -0
  329. package/test/examples/flappy_bird/simulation-shared/simulation-shared.control.utils.ts +6 -0
  330. package/test/examples/flappy_bird/simulation-shared/simulation-shared.difficulty.utils.ts +9 -0
  331. package/test/examples/flappy_bird/simulation-shared/simulation-shared.errors.ts +10 -1
  332. package/test/examples/flappy_bird/simulation-shared/simulation-shared.memory.utils.ts +18 -0
  333. package/test/examples/flappy_bird/simulation-shared/simulation-shared.observation.utils.ts +7 -402
  334. package/test/examples/flappy_bird/simulation-shared/simulation-shared.spawn.utils.ts +36 -6
  335. package/test/examples/flappy_bird/{evaluation/evaluation.statistics.utils.ts → simulation-shared/simulation-shared.statistics.utils.ts} +30 -9
  336. package/test/examples/flappy_bird/simulation-shared/simulation-shared.types.ts +38 -5
  337. package/test/examples/flappy_bird/trainFlappyBird.ts +13 -0
  338. package/test/examples/flappy_bird/trainer/README.md +676 -0
  339. package/test/examples/flappy_bird/trainer/evaluation/README.md +253 -0
  340. package/test/examples/flappy_bird/trainer/evaluation/trainer.evaluation.service.constants.ts +15 -0
  341. package/test/examples/flappy_bird/trainer/evaluation/trainer.evaluation.service.services.ts +86 -0
  342. package/test/examples/flappy_bird/trainer/evaluation/trainer.evaluation.service.ts +187 -0
  343. package/test/examples/flappy_bird/trainer/evaluation/trainer.evaluation.service.types.ts +32 -0
  344. package/test/examples/flappy_bird/trainer/evaluation/trainer.evaluation.service.utils.ts +182 -0
  345. package/test/examples/flappy_bird/trainer/trainer.evaluation.service.ts +13 -0
  346. package/test/examples/flappy_bird/trainer/trainer.fitness.service.ts +23 -1
  347. package/test/examples/flappy_bird/trainer/trainer.loop.service.ts +17 -1
  348. package/test/examples/flappy_bird/trainer/trainer.report.service.services.ts +181 -0
  349. package/test/examples/flappy_bird/trainer/trainer.report.service.ts +136 -0
  350. package/test/examples/flappy_bird/trainer/trainer.selection.utils.ts +89 -0
  351. package/test/examples/flappy_bird/trainer/trainer.setup.service.ts +22 -0
  352. package/test/examples/flappy_bird/trainer/trainer.signals.service.ts +8 -0
  353. package/test/examples/flappy_bird/trainer/trainer.ts +38 -553
  354. package/test/examples/flappy_bird/trainer/trainer.types.ts +44 -7
  355. package/test/neat/neat.topology-intent.test.ts +129 -0
  356. package/test/network/network.topology-intent.test.ts +44 -0
  357. package/test/examples/flappy_bird/browser-entry/browser-entry.utils.ts +0 -12
  358. package/test/examples/flappy_bird/environment/environment.ts +0 -7
  359. package/test/examples/flappy_bird/evaluation/evaluation.ts +0 -7
  360. package/test/examples/flappy_bird/simulation-shared/simulation-shared.ts +0 -15
  361. package/test/examples/flappy_bird/trainer/trainer.statistics.utils.ts +0 -78
@@ -0,0 +1,182 @@
1
+ import type { FlappySeedBatchEvaluation } from '../../flappyEvaluation';
2
+ import {
3
+ FLAPPY_TRAINER_FRAME_PRIMARY_BASE_SCORE,
4
+ FLAPPY_TRAINER_FRAME_PRIMARY_PIPE_WEIGHT,
5
+ FLAPPY_TRAINER_FRAME_PRIMARY_SURVIVAL_WEIGHT,
6
+ FLAPPY_TRAINER_FRAME_STABILITY_STDDEV_WEIGHT,
7
+ FLAPPY_TRAINER_PIPE_FALLBACK_PIPE_WEIGHT,
8
+ FLAPPY_TRAINER_PIPE_FILTER_TOLERANCE,
9
+ } from '../trainer.constants';
10
+ import type { FlappyTrainerNetwork } from '../trainer.types';
11
+ import {
12
+ FLAPPY_TRAINER_MIN_PIPE_PROGRESS,
13
+ FLAPPY_TRAINER_NEGATIVE_INFINITY_SCORE,
14
+ } from './trainer.evaluation.service.constants';
15
+ import type { PopulationAggregateScoringContext } from './trainer.evaluation.service.types';
16
+
17
+ /**
18
+ * Assigns refreshed frame-primary scores to the current population.
19
+ *
20
+ * Educational note:
21
+ * The trainer does not rank genomes purely by one raw metric. It combines pipe
22
+ * progress, survival, and stability into a provisional score so early-stage
23
+ * selection remains robust when several genomes are close in quality.
24
+ *
25
+ * @param population - Current population.
26
+ * @param aggregateByGenome - Aggregate cache keyed by genome.
27
+ * @param provisionalScoresByGenome - Mutable provisional score map.
28
+ * @returns Nothing.
29
+ */
30
+ export function assignFramePrimaryScores(
31
+ population: readonly FlappyTrainerNetwork[],
32
+ aggregateByGenome: ReadonlyMap<
33
+ FlappyTrainerNetwork,
34
+ FlappySeedBatchEvaluation
35
+ >,
36
+ provisionalScoresByGenome: Map<FlappyTrainerNetwork, number>,
37
+ ): void {
38
+ // Step 1: Resolve the aggregate scoring context shared by all genomes.
39
+ const populationAggregateScoringContext =
40
+ resolvePopulationAggregateScoringContext(population, aggregateByGenome);
41
+
42
+ // Step 2: Score each genome using the refreshed aggregate context.
43
+ for (const genome of population) {
44
+ const aggregate = aggregateByGenome.get(genome);
45
+ if (!aggregate) {
46
+ provisionalScoresByGenome.set(
47
+ genome,
48
+ FLAPPY_TRAINER_NEGATIVE_INFINITY_SCORE,
49
+ );
50
+ continue;
51
+ }
52
+
53
+ provisionalScoresByGenome.set(
54
+ genome,
55
+ scoreAggregateFramePrimary(
56
+ aggregate,
57
+ populationAggregateScoringContext.maximumMeanPipesPassed,
58
+ ),
59
+ );
60
+ }
61
+ }
62
+
63
+ /**
64
+ * Collects all currently available aggregate values.
65
+ *
66
+ * Only genomes with completed aggregate results are included. That lets the
67
+ * scoring helpers distinguish between genuinely weak genomes and genomes that
68
+ * simply have not yet reached a later stage.
69
+ *
70
+ * @param population - Current population.
71
+ * @param aggregateByGenome - Aggregate cache keyed by genome.
72
+ * @returns Collected aggregate values.
73
+ */
74
+ export function collectAggregateValues(
75
+ population: readonly FlappyTrainerNetwork[],
76
+ aggregateByGenome: ReadonlyMap<
77
+ FlappyTrainerNetwork,
78
+ FlappySeedBatchEvaluation
79
+ >,
80
+ ): FlappySeedBatchEvaluation[] {
81
+ const aggregateValues: FlappySeedBatchEvaluation[] = [];
82
+
83
+ // Step 1: Include only genomes that already have an aggregate in the cache.
84
+ for (const genome of population) {
85
+ const aggregate = aggregateByGenome.get(genome);
86
+ if (aggregate) {
87
+ aggregateValues.push(aggregate);
88
+ }
89
+ }
90
+
91
+ return aggregateValues;
92
+ }
93
+
94
+ /**
95
+ * Resolves the leading mean pipe-progress value across available aggregates.
96
+ *
97
+ * Mean pipe progress acts as the leading indicator for the frame-primary score:
98
+ * if a genome is far behind the current pipe leader, it falls back to a simpler
99
+ * progress-first score.
100
+ *
101
+ * @param aggregateValues - Aggregate values currently available.
102
+ * @returns Highest mean pipe-progress value.
103
+ */
104
+ export function resolveMaximumMeanPipesPassed(
105
+ aggregateValues: readonly FlappySeedBatchEvaluation[],
106
+ ): number {
107
+ // Step 1: Resolve the leading mean pipe-progress value across all aggregates.
108
+ return aggregateValues.reduce(
109
+ (bestPipeProgress, aggregate) =>
110
+ Math.max(bestPipeProgress, aggregate.meanPipesPassed),
111
+ FLAPPY_TRAINER_MIN_PIPE_PROGRESS,
112
+ );
113
+ }
114
+
115
+ /**
116
+ * Scores one aggregate using the frame-primary heuristic.
117
+ *
118
+ * Educational note:
119
+ * The heuristic intentionally mixes progress and stability. A genome that passes
120
+ * many pipes but has wildly inconsistent fitness across seeds is treated more
121
+ * cautiously than a similarly strong but steadier genome.
122
+ *
123
+ * @param aggregate - Aggregate evaluation result.
124
+ * @param maximumMeanPipesPassed - Best mean pipe progress in the population.
125
+ * @returns Provisional score.
126
+ */
127
+ export function scoreAggregateFramePrimary(
128
+ aggregate: FlappySeedBatchEvaluation,
129
+ maximumMeanPipesPassed: number,
130
+ ): number {
131
+ // Step 1: Resolve the stability penalty and pipe-progress eligibility filter.
132
+ const frameStabilityPenalty =
133
+ aggregate.fitnessStdDev * FLAPPY_TRAINER_FRAME_STABILITY_STDDEV_WEIGHT;
134
+ const passesPipeFilter =
135
+ aggregate.meanPipesPassed >=
136
+ maximumMeanPipesPassed - FLAPPY_TRAINER_PIPE_FILTER_TOLERANCE;
137
+
138
+ // Step 2: Use the full frame-primary score when the genome remains near the pipe leader.
139
+ if (passesPipeFilter) {
140
+ return (
141
+ FLAPPY_TRAINER_FRAME_PRIMARY_BASE_SCORE +
142
+ aggregate.meanFramesSurvived *
143
+ FLAPPY_TRAINER_FRAME_PRIMARY_SURVIVAL_WEIGHT +
144
+ aggregate.meanPipesPassed * FLAPPY_TRAINER_FRAME_PRIMARY_PIPE_WEIGHT -
145
+ frameStabilityPenalty
146
+ );
147
+ }
148
+
149
+ // Step 3: Fall back to the pipe-progress-first score for trailing genomes.
150
+ return (
151
+ aggregate.meanPipesPassed * FLAPPY_TRAINER_PIPE_FALLBACK_PIPE_WEIGHT +
152
+ aggregate.meanFramesSurvived -
153
+ frameStabilityPenalty
154
+ );
155
+ }
156
+
157
+ /**
158
+ * Resolves the aggregate scoring context used by frame-primary scoring.
159
+ *
160
+ * This precomputation step keeps the per-genome scoring loop lean and avoids
161
+ * recomputing population-wide maxima for every genome.
162
+ *
163
+ * @param population - Current population.
164
+ * @param aggregateByGenome - Aggregate cache keyed by genome.
165
+ * @returns Aggregate scoring context.
166
+ */
167
+ function resolvePopulationAggregateScoringContext(
168
+ population: readonly FlappyTrainerNetwork[],
169
+ aggregateByGenome: ReadonlyMap<
170
+ FlappyTrainerNetwork,
171
+ FlappySeedBatchEvaluation
172
+ >,
173
+ ): PopulationAggregateScoringContext {
174
+ // Step 1: Collect the currently available aggregate values.
175
+ const aggregateValues = collectAggregateValues(population, aggregateByGenome);
176
+
177
+ // Step 2: Resolve the highest mean pipe-progress value in the population.
178
+ return {
179
+ aggregateValues,
180
+ maximumMeanPipesPassed: resolveMaximumMeanPipesPassed(aggregateValues),
181
+ };
182
+ }
@@ -0,0 +1,13 @@
1
+ /**
2
+ * Trainer evaluation compatibility facade.
3
+ *
4
+ * The staged population-evaluation implementation now lives in the dedicated
5
+ * `trainer/evaluation/` submodule so orchestration, scoring helpers, internal
6
+ * contracts, and sub-services can evolve behind a focused boundary.
7
+ */
8
+ export {
9
+ commitPopulationScores,
10
+ evaluatePopulationFullStage,
11
+ evaluatePopulationQuickStage,
12
+ evaluatePopulationReevaluationStage,
13
+ } from './evaluation/trainer.evaluation.service';
@@ -7,7 +7,14 @@ import type {
7
7
  FlappyTrainerRuntimeState,
8
8
  } from './trainer.types';
9
9
 
10
- /** Callback dependencies required by the trainer fitness orchestration service. */
10
+ /**
11
+ * Callback dependencies required by the trainer fitness orchestration service.
12
+ *
13
+ * Educational note:
14
+ * The trainer evaluates whole populations in staged passes. This dependency bag
15
+ * keeps the top-level service declarative and makes each stage independently
16
+ * replaceable without rewriting the orchestration logic.
17
+ */
11
18
  export interface TrainerFitnessServiceDependencies {
12
19
  resolveGenerationEvaluationPlan: (
13
20
  generationIndex: number,
@@ -49,10 +56,16 @@ export interface TrainerFitnessServiceDependencies {
49
56
  /**
50
57
  * Attaches population-level staged evaluator to the NEAT controller.
51
58
  *
59
+ * This is the moment where the generic NEAT controller becomes a
60
+ * Flappy-specific trainer: a plain controller receives the staged population
61
+ * evaluator that understands shared-seed screening, full-pass scoring, and
62
+ * reevaluation.
63
+ *
52
64
  * @param neatController - Trainer NEAT controller.
53
65
  * @param trainerRuntimeState - Mutable trainer runtime state.
54
66
  * @param elitismCount - Number of elite genomes preserved each generation.
55
67
  * @param dependencies - Pure/impure helper callbacks used by the evaluator.
68
+ * @returns Nothing.
56
69
  */
57
70
  export function attachPopulationFitnessEvaluator(
58
71
  neatController: FlappyTrainerNeatController,
@@ -71,6 +84,15 @@ export function attachPopulationFitnessEvaluator(
71
84
  /**
72
85
  * Creates the asynchronous population fitness evaluator.
73
86
  *
87
+ * Educational note:
88
+ * The trainer uses staged evaluation to reduce luck. Genomes are first screened
89
+ * quickly, then the most promising ones receive more expensive evaluation, and
90
+ * the best candidates are reevaluated again for robustness.
91
+ *
92
+ * That strategy is closer to tournament design than to naive one-shot scoring:
93
+ * the same generation budget is spent unevenly so weak genomes are filtered out
94
+ * early and strong genomes are compared more carefully.
95
+ *
74
96
  * @param neatController - Trainer NEAT controller.
75
97
  * @param trainerRuntimeState - Mutable trainer runtime state.
76
98
  * @param elitismCount - Number of elite genomes preserved each generation.
@@ -11,7 +11,13 @@ import type {
11
11
  FlappyTrainerRuntimeState,
12
12
  } from './trainer.types';
13
13
 
14
- /** Callback signature for one-line generation logging. */
14
+ /**
15
+ * Callback signature for one-line generation logging.
16
+ *
17
+ * The loop owns evolution cadence, while the callback owns presentation.
18
+ * Keeping those concerns separate makes it easy to reuse the loop with richer
19
+ * reporting later.
20
+ */
15
21
  export type LogGenerationSummaryCallback = (
16
22
  generationLabel: number,
17
23
  mutationSchedule: FlappyMutationSchedule,
@@ -23,9 +29,15 @@ export type LogGenerationSummaryCallback = (
23
29
  /**
24
30
  * Runs the outer evolution loop until runtime stop is requested.
25
31
  *
32
+ * Educational note:
33
+ * This is the trainer's main heartbeat: resolve the current mutation schedule,
34
+ * evolve one generation, run a representative fallback rollout for logging, and
35
+ * emit a compact summary.
36
+ *
26
37
  * @param neatController - Trainer NEAT controller.
27
38
  * @param trainerRuntimeState - Mutable trainer runtime state.
28
39
  * @param logGenerationSummary - Callback that emits compact generation logs.
40
+ * @returns Promise resolved when the trainer has been stopped.
29
41
  */
30
42
  export async function runTrainerEvolutionLoop(
31
43
  neatController: FlappyTrainerNeatController,
@@ -55,8 +67,12 @@ export async function runTrainerEvolutionLoop(
55
67
  /**
56
68
  * Applies mutation schedule values to the NEAT controller options.
57
69
  *
70
+ * The schedule is resolved outside this helper so the loop can read as a clean
71
+ * "resolve -> apply -> evolve -> report" flow.
72
+ *
58
73
  * @param neatController - Trainer NEAT controller.
59
74
  * @param mutationSchedule - Mutation schedule for current generation.
75
+ * @returns Nothing.
60
76
  */
61
77
  function applyMutationSchedule(
62
78
  neatController: FlappyTrainerNeatController,
@@ -0,0 +1,181 @@
1
+ import {
2
+ evaluateFlappyFitnessAcrossSeeds,
3
+ rolloutEpisode,
4
+ type FlappyRolloutOptions,
5
+ type FlappySeedBatchEvaluation,
6
+ } from '../flappyEvaluation';
7
+ import {
8
+ FLAPPY_TRAINER_DUMMY_FLAP_OUTPUT,
9
+ FLAPPY_TRAINER_DUMMY_NETWORK_ID,
10
+ FLAPPY_TRAINER_DUMMY_NO_FLAP_OUTPUT,
11
+ } from './trainer.constants';
12
+ import type { FlappyTrainerNetwork } from './trainer.types';
13
+
14
+ /**
15
+ * Aggregate and representative rollout resolved for the best genome.
16
+ *
17
+ * Keeping these values together lets the report facade stay focused on
18
+ * orchestration while this helper module owns cache fallback behavior.
19
+ */
20
+ export interface ResolvedBestGenerationDetails {
21
+ bestAggregate: FlappySeedBatchEvaluation;
22
+ bestEpisode: ReturnType<typeof rolloutEpisode>;
23
+ }
24
+
25
+ /**
26
+ * Collects only finite scores from the current population.
27
+ *
28
+ * Unevaluated or invalid scores are intentionally skipped so percentile and
29
+ * standard deviation calculations operate on stable numeric inputs only.
30
+ *
31
+ * @param population - Current population.
32
+ * @returns Finite scores in population order.
33
+ * @example
34
+ * ```ts
35
+ * const scores = collectFiniteGenomeScores(population);
36
+ * ```
37
+ */
38
+ export function collectFiniteGenomeScores(
39
+ population: readonly FlappyTrainerNetwork[],
40
+ ): number[] {
41
+ const finiteScores: number[] = [];
42
+
43
+ for (const genome of population) {
44
+ const genomeScore = genome.score ?? Number.NEGATIVE_INFINITY;
45
+ if (Number.isFinite(genomeScore)) {
46
+ finiteScores.push(genomeScore);
47
+ }
48
+ }
49
+
50
+ return finiteScores;
51
+ }
52
+
53
+ /**
54
+ * Resolves cached or fallback best-of-generation details for reporting.
55
+ *
56
+ * The report layer needs both aggregate seed statistics and one representative
57
+ * episode. This helper centralizes the fallback rules so the service facade can
58
+ * remain a thin orchestration layer.
59
+ *
60
+ * @param population - Current population.
61
+ * @param bestGenome - Genome selected as generation best.
62
+ * @param aggregateByGenome - Cached aggregate evaluations keyed by genome.
63
+ * @param fallbackSeeds - Seeds used when the aggregate must be recomputed.
64
+ * @param fallbackRolloutOptions - Rollout options for fallback evaluation.
65
+ * @returns Aggregate metrics and a representative best-genome episode.
66
+ * @example
67
+ * ```ts
68
+ * const { bestAggregate, bestEpisode } = resolveBestGenerationDetails(
69
+ * population,
70
+ * bestGenome,
71
+ * aggregateByGenome,
72
+ * reevaluationSeeds,
73
+ * reevaluationRolloutOptions,
74
+ * );
75
+ * ```
76
+ */
77
+ export function resolveBestGenerationDetails(
78
+ population: readonly FlappyTrainerNetwork[],
79
+ bestGenome: FlappyTrainerNetwork | undefined,
80
+ aggregateByGenome: ReadonlyMap<
81
+ FlappyTrainerNetwork,
82
+ FlappySeedBatchEvaluation
83
+ >,
84
+ fallbackSeeds: readonly number[],
85
+ fallbackRolloutOptions: FlappyRolloutOptions,
86
+ ): ResolvedBestGenerationDetails {
87
+ return {
88
+ bestAggregate: resolveBestAggregate(
89
+ population,
90
+ bestGenome,
91
+ aggregateByGenome,
92
+ fallbackSeeds,
93
+ fallbackRolloutOptions,
94
+ ),
95
+ bestEpisode: resolveBestEpisode(
96
+ population,
97
+ bestGenome,
98
+ fallbackSeeds,
99
+ fallbackRolloutOptions,
100
+ ),
101
+ };
102
+ }
103
+
104
+ function resolveBestAggregate(
105
+ population: readonly FlappyTrainerNetwork[],
106
+ bestGenome: FlappyTrainerNetwork | undefined,
107
+ aggregateByGenome: ReadonlyMap<
108
+ FlappyTrainerNetwork,
109
+ FlappySeedBatchEvaluation
110
+ >,
111
+ fallbackSeeds: readonly number[],
112
+ fallbackRolloutOptions: FlappyRolloutOptions,
113
+ ): FlappySeedBatchEvaluation {
114
+ const fallbackGenome = resolveFallbackGenome(population, bestGenome);
115
+ if (!fallbackGenome) {
116
+ return buildEmptySeedBatchEvaluation();
117
+ }
118
+
119
+ const cachedAggregate = aggregateByGenome.get(fallbackGenome);
120
+ if (cachedAggregate) {
121
+ return cachedAggregate;
122
+ }
123
+
124
+ return evaluateFlappyFitnessAcrossSeeds(
125
+ fallbackGenome,
126
+ fallbackSeeds,
127
+ fallbackRolloutOptions,
128
+ );
129
+ }
130
+
131
+ function resolveBestEpisode(
132
+ population: readonly FlappyTrainerNetwork[],
133
+ bestGenome: FlappyTrainerNetwork | undefined,
134
+ fallbackSeeds: readonly number[],
135
+ fallbackRolloutOptions: FlappyRolloutOptions,
136
+ ): ReturnType<typeof rolloutEpisode> {
137
+ const fallbackGenome = resolveFallbackGenome(population, bestGenome);
138
+ if (!fallbackGenome) {
139
+ return rolloutEpisode(resolveDummyNetwork(), fallbackRolloutOptions);
140
+ }
141
+
142
+ const episodeSeed = fallbackSeeds[0];
143
+ return rolloutEpisode(fallbackGenome, {
144
+ ...fallbackRolloutOptions,
145
+ seed: episodeSeed,
146
+ });
147
+ }
148
+
149
+ function resolveFallbackGenome(
150
+ population: readonly FlappyTrainerNetwork[],
151
+ bestGenome: FlappyTrainerNetwork | undefined,
152
+ ): FlappyTrainerNetwork | undefined {
153
+ return bestGenome ?? population[0];
154
+ }
155
+
156
+ function buildEmptySeedBatchEvaluation(): FlappySeedBatchEvaluation {
157
+ return {
158
+ seedCount: 0,
159
+ meanFitness: 0,
160
+ medianFitness: 0,
161
+ p90Fitness: 0,
162
+ fitnessStdDev: 0,
163
+ robustFitness: 0,
164
+ meanPipesPassed: 0,
165
+ meanFramesSurvived: 0,
166
+ };
167
+ }
168
+
169
+ function resolveDummyNetwork(): FlappyTrainerNetwork {
170
+ return {
171
+ activate: activateWithoutFlap,
172
+ _id: FLAPPY_TRAINER_DUMMY_NETWORK_ID,
173
+ };
174
+ }
175
+
176
+ function activateWithoutFlap(): number[] {
177
+ return [
178
+ FLAPPY_TRAINER_DUMMY_NO_FLAP_OUTPUT,
179
+ FLAPPY_TRAINER_DUMMY_FLAP_OUTPUT,
180
+ ];
181
+ }
@@ -0,0 +1,136 @@
1
+ import {
2
+ rolloutEpisode,
3
+ type FlappySeedBatchEvaluation,
4
+ } from '../flappyEvaluation';
5
+ import {
6
+ FLAPPY_TRAINER_LOG_PARTS_DELIMITER,
7
+ FLAPPY_TRAINER_SCORE_MEDIAN_PERCENTILE,
8
+ FLAPPY_TRAINER_SCORE_P90_PERCENTILE,
9
+ } from './trainer.constants';
10
+ import type { FlappyMutationSchedule } from './trainer.evaluation-plan.utils';
11
+ import {
12
+ collectFiniteGenomeScores,
13
+ resolveBestGenerationDetails,
14
+ } from './trainer.report.service.services';
15
+ import { buildGenerationLogParts } from './trainer.reporting.utils';
16
+ import { resolveBestGenomeByScore } from './trainer.selection.utils';
17
+ import {
18
+ computeMean,
19
+ computePercentile,
20
+ computePopulationStandardDeviation,
21
+ } from '../flappy.simulation.shared.utils';
22
+ import type {
23
+ FlappyGenerationEvaluationPlan,
24
+ FlappyGenerationReport,
25
+ FlappyTrainerNetwork,
26
+ } from './trainer.types';
27
+
28
+ /**
29
+ * Builds a compact report for the current generation.
30
+ *
31
+ * Educational note:
32
+ * The trainer logs more than a single best score because single-number progress
33
+ * can hide instability. Mean, median, $p90$, and standard deviation reveal
34
+ * whether a generation is broadly improving or whether one lucky genome is
35
+ * masking a weak population.
36
+ *
37
+ * @param population - Current population.
38
+ * @param aggregateByGenome - Aggregate evaluation results keyed by genome.
39
+ * @param generationEvaluationPlan - Per-generation staged evaluation plan.
40
+ * @returns Aggregated generation report.
41
+ */
42
+ export function buildGenerationReport(
43
+ population: readonly FlappyTrainerNetwork[],
44
+ aggregateByGenome: ReadonlyMap<
45
+ FlappyTrainerNetwork,
46
+ FlappySeedBatchEvaluation
47
+ >,
48
+ generationEvaluationPlan: FlappyGenerationEvaluationPlan,
49
+ ): FlappyGenerationReport {
50
+ // Step 1: Collect stable numeric inputs for distribution statistics.
51
+ const finalScores = collectFiniteGenomeScores(population);
52
+ const scoreMean = computeMean(finalScores);
53
+ const scoreStdDev = computePopulationStandardDeviation(
54
+ finalScores,
55
+ scoreMean,
56
+ );
57
+
58
+ // Step 2: Resolve best-genome derived metrics through the report helper boundary.
59
+ const bestGenome = resolveBestGenomeByScore(population);
60
+ const { bestAggregate, bestEpisode } = resolveBestGenerationDetails(
61
+ population,
62
+ bestGenome,
63
+ aggregateByGenome,
64
+ generationEvaluationPlan.reevaluationSeeds,
65
+ generationEvaluationPlan.reevaluationRolloutOptions,
66
+ );
67
+
68
+ // Step 3: Fold the resolved metrics into the compact generation report.
69
+ return {
70
+ generationIndex: generationEvaluationPlan.generationIndex,
71
+ difficultyScale: generationEvaluationPlan.difficultyScale,
72
+ mutationRate: generationEvaluationPlan.mutationRate,
73
+ mutationAmount: generationEvaluationPlan.mutationAmount,
74
+ quickSeedCount: generationEvaluationPlan.quickSeeds.length,
75
+ fullSeedCount: generationEvaluationPlan.fullSeeds.length,
76
+ reevaluationSeedCount: generationEvaluationPlan.reevaluationSeeds.length,
77
+ evaluatedPopulationSize: population.length,
78
+ scoreMean,
79
+ scoreMedian: computePercentile(
80
+ finalScores,
81
+ FLAPPY_TRAINER_SCORE_MEDIAN_PERCENTILE,
82
+ ),
83
+ scoreP90: computePercentile(
84
+ finalScores,
85
+ FLAPPY_TRAINER_SCORE_P90_PERCENTILE,
86
+ ),
87
+ scoreStdDev,
88
+ bestRobustFitness: bestGenome?.score ?? Number.NaN,
89
+ bestMeanFitness: bestAggregate.meanFitness,
90
+ bestPipesPassed: bestEpisode.pipesPassed,
91
+ bestFramesSurvived: bestEpisode.framesSurvived,
92
+ };
93
+ }
94
+
95
+ /**
96
+ * Emits one compact generation log line.
97
+ *
98
+ * The emitted line is designed for long-running terminal sessions: dense enough
99
+ * to be useful, but stable enough that humans can visually scan progress over
100
+ * hundreds of generations.
101
+ *
102
+ * @param generationLabel - Current generation label.
103
+ * @param mutationSchedule - Active mutation schedule.
104
+ * @param report - Optional aggregated generation report.
105
+ * @param fittestGenome - Fittest genome returned by the NEAT controller.
106
+ * @param fallbackEpisode - Fallback representative rollout episode.
107
+ * @returns Nothing.
108
+ */
109
+ export function logGenerationSummary(
110
+ generationLabel: number,
111
+ mutationSchedule: FlappyMutationSchedule,
112
+ report: FlappyGenerationReport | undefined,
113
+ fittestGenome: FlappyTrainerNetwork,
114
+ fallbackEpisode: ReturnType<typeof rolloutEpisode>,
115
+ ): void {
116
+ const bestFitness =
117
+ report?.bestRobustFitness ??
118
+ (fittestGenome.score as number) ??
119
+ fallbackEpisode.fitness;
120
+ const bestPipesPassed =
121
+ report?.bestPipesPassed ?? fallbackEpisode.pipesPassed;
122
+ const bestFramesSurvived =
123
+ report?.bestFramesSurvived ?? fallbackEpisode.framesSurvived;
124
+
125
+ const logParts = buildGenerationLogParts(
126
+ generationLabel,
127
+ bestFitness,
128
+ bestPipesPassed,
129
+ bestFramesSurvived,
130
+ report,
131
+ mutationSchedule,
132
+ );
133
+
134
+ // eslint-disable-next-line no-console
135
+ console.log(logParts.join(FLAPPY_TRAINER_LOG_PARTS_DELIMITER));
136
+ }
@@ -0,0 +1,89 @@
1
+ import type { FlappyTrainerNetwork, ScoredGenomeEntry } from './trainer.types';
2
+
3
+ /**
4
+ * Returns top genomes ordered by current provisional score.
5
+ *
6
+ * @param population - Current trainer population.
7
+ * @param provisionalScoresByGenome - Optional map of staged provisional scores.
8
+ * @param targetCount - Maximum number of genomes to return.
9
+ * @returns Highest-scoring genomes in descending score order.
10
+ */
11
+ export function selectTopGenomesByScore(
12
+ population: readonly FlappyTrainerNetwork[],
13
+ provisionalScoresByGenome: ReadonlyMap<FlappyTrainerNetwork, number>,
14
+ targetCount: number,
15
+ ): FlappyTrainerNetwork[] {
16
+ const scoredEntries = buildScoredGenomeEntries(
17
+ population,
18
+ provisionalScoresByGenome,
19
+ );
20
+
21
+ scoredEntries.sort(compareScoredGenomeEntriesDescending);
22
+
23
+ const selectedGenomes: FlappyTrainerNetwork[] = [];
24
+ const maximumSelectionCount = Math.max(
25
+ 0,
26
+ Math.min(targetCount, scoredEntries.length),
27
+ );
28
+
29
+ let selectedIndex = 0;
30
+ while (selectedIndex < maximumSelectionCount) {
31
+ const scoredEntry = scoredEntries[selectedIndex];
32
+ if (scoredEntry) {
33
+ selectedGenomes.push(scoredEntry.genome);
34
+ }
35
+ selectedIndex += 1;
36
+ }
37
+
38
+ return selectedGenomes;
39
+ }
40
+
41
+ /**
42
+ * Resolves the best genome by current score.
43
+ *
44
+ * @param population - Current trainer population.
45
+ * @returns Highest-scoring genome or `undefined` when population is empty.
46
+ */
47
+ export function resolveBestGenomeByScore(
48
+ population: readonly FlappyTrainerNetwork[],
49
+ ): FlappyTrainerNetwork | undefined {
50
+ const scoredGenomes = buildScoredGenomeEntries(population, undefined);
51
+ scoredGenomes.sort(compareScoredGenomeEntriesDescending);
52
+ return scoredGenomes[0]?.genome;
53
+ }
54
+
55
+ function buildScoredGenomeEntries(
56
+ population: readonly FlappyTrainerNetwork[],
57
+ provisionalScoresByGenome:
58
+ | ReadonlyMap<FlappyTrainerNetwork, number>
59
+ | undefined,
60
+ ): ScoredGenomeEntry[] {
61
+ const scoredEntries: ScoredGenomeEntry[] = [];
62
+
63
+ for (const genome of population) {
64
+ const score = resolveGenomeScore(genome, provisionalScoresByGenome);
65
+ scoredEntries.push({ genome, score });
66
+ }
67
+
68
+ return scoredEntries;
69
+ }
70
+
71
+ function resolveGenomeScore(
72
+ genome: FlappyTrainerNetwork,
73
+ provisionalScoresByGenome:
74
+ | ReadonlyMap<FlappyTrainerNetwork, number>
75
+ | undefined,
76
+ ): number {
77
+ if (provisionalScoresByGenome) {
78
+ return provisionalScoresByGenome.get(genome) ?? Number.NEGATIVE_INFINITY;
79
+ }
80
+
81
+ return genome.score ?? Number.NEGATIVE_INFINITY;
82
+ }
83
+
84
+ function compareScoredGenomeEntriesDescending(
85
+ leftEntry: ScoredGenomeEntry,
86
+ rightEntry: ScoredGenomeEntry,
87
+ ): number {
88
+ return rightEntry.score - leftEntry.score;
89
+ }