@reicek/neataptic-ts 0.1.21 → 0.1.22
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.github/agents/boundary-mapper.agent.md +29 -0
- package/.github/agents/docs-scout.agent.md +29 -0
- package/.github/agents/plan-scout.agent.md +29 -0
- package/.github/agents/solid-split.agent.md +138 -0
- package/.github/copilot-instructions.md +103 -0
- package/package.json +6 -3
- package/plans/ES2023 migration +13 -8
- package/plans/Evolution_Training_Interoperability_Contracts.md +1 -1
- package/plans/Interactive_Examples_and_Learning_Path.md +10 -2
- package/plans/Memory_Optimization.md +3 -3
- package/plans/README.md +63 -0
- package/plans/Roadmap.md +15 -3
- package/plans/asciiMaze_SOLID_split.done.md +130 -0
- package/plans/flappy_bird_SOLID_split.done.md +67 -0
- package/scripts/assets/theme.css +221 -34
- package/scripts/copy-examples.mjs +9 -5
- package/scripts/export-onnx.mjs +3 -3
- package/scripts/generate-bench-tables.mjs +10 -10
- package/scripts/generate-bench-tables.ts +10 -10
- package/scripts/generate-docs.ts +1415 -449
- package/scripts/render-docs-html.ts +15 -8
- package/src/README.md +101 -223
- package/src/architecture/README.md +57 -185
- package/src/architecture/layer/README.md +38 -38
- package/src/architecture/network/README.md +33 -31
- package/src/architecture/network/activate/README.md +77 -77
- package/src/architecture/network/connect/README.md +15 -13
- package/src/architecture/network/deterministic/README.md +7 -7
- package/src/architecture/network/evolve/README.md +44 -44
- package/src/architecture/network/gating/README.md +20 -20
- package/src/architecture/network/genetic/README.md +51 -51
- package/src/architecture/network/mutate/README.md +97 -97
- package/src/architecture/network/onnx/README.md +264 -264
- package/src/architecture/network/prune/README.md +39 -39
- package/src/architecture/network/remove/README.md +26 -26
- package/src/architecture/network/serialize/README.md +56 -56
- package/src/architecture/network/slab/README.md +61 -61
- package/src/architecture/network/standalone/README.md +24 -24
- package/src/architecture/network/stats/README.md +9 -9
- package/src/architecture/network/topology/README.md +46 -46
- package/src/architecture/network/training/README.md +21 -21
- package/src/methods/README.md +9 -87
- package/src/multithreading/README.md +8 -77
- package/src/multithreading/workers/README.md +2 -2
- package/src/multithreading/workers/browser/README.md +0 -6
- package/src/multithreading/workers/node/README.md +0 -3
- package/src/neat/README.md +562 -568
- package/src/utils/README.md +18 -18
- package/test/examples/asciiMaze/README.md +59 -59
- package/test/examples/asciiMaze/asciiMaze.e2e.test.ts +14 -9
- package/test/examples/asciiMaze/browser-entry/README.md +196 -0
- package/test/examples/asciiMaze/browser-entry/browser-entry.abort.services.ts +95 -0
- package/test/examples/asciiMaze/browser-entry/browser-entry.constants.ts +23 -0
- package/test/examples/asciiMaze/browser-entry/browser-entry.curriculum.services.ts +115 -0
- package/test/examples/asciiMaze/browser-entry/browser-entry.globals.services.ts +106 -0
- package/test/examples/asciiMaze/browser-entry/browser-entry.host.services.ts +157 -0
- package/test/examples/asciiMaze/browser-entry/browser-entry.services.ts +14 -0
- package/test/examples/asciiMaze/browser-entry/browser-entry.ts +129 -0
- package/test/examples/asciiMaze/browser-entry/browser-entry.types.ts +120 -0
- package/test/examples/asciiMaze/browser-entry/browser-entry.utils.ts +98 -0
- package/test/examples/asciiMaze/browser-entry.ts +10 -576
- package/test/examples/asciiMaze/dashboardManager/README.md +276 -0
- package/test/examples/asciiMaze/dashboardManager/archive/README.md +16 -0
- package/test/examples/asciiMaze/dashboardManager/archive/dashboardManager.archive.services.ts +267 -0
- package/test/examples/asciiMaze/dashboardManager/dashboardManager.constants.ts +35 -0
- package/test/examples/asciiMaze/dashboardManager/dashboardManager.services.ts +103 -0
- package/test/examples/asciiMaze/dashboardManager/dashboardManager.ts +181 -0
- package/test/examples/asciiMaze/dashboardManager/dashboardManager.types.ts +267 -0
- package/test/examples/asciiMaze/dashboardManager/dashboardManager.utils.ts +254 -0
- package/test/examples/asciiMaze/dashboardManager/live/README.md +14 -0
- package/test/examples/asciiMaze/dashboardManager/live/dashboardManager.live.services.ts +264 -0
- package/test/examples/asciiMaze/dashboardManager/telemetry/README.md +47 -0
- package/test/examples/asciiMaze/dashboardManager/telemetry/dashboardManager.telemetry.services.ts +513 -0
- package/test/examples/asciiMaze/dashboardManager.ts +13 -2335
- package/test/examples/asciiMaze/evolutionEngine/README.md +1058 -0
- package/test/examples/asciiMaze/evolutionEngine/curriculumPhase.ts +90 -0
- package/test/examples/asciiMaze/evolutionEngine/engineState.constants.ts +36 -0
- package/test/examples/asciiMaze/evolutionEngine/engineState.ts +58 -513
- package/test/examples/asciiMaze/evolutionEngine/engineState.types.ts +212 -0
- package/test/examples/asciiMaze/evolutionEngine/engineState.utils.ts +301 -0
- package/test/examples/asciiMaze/evolutionEngine/evolutionEngine.types.ts +445 -0
- package/test/examples/asciiMaze/evolutionEngine/evolutionLoop.ts +81 -50
- package/test/examples/asciiMaze/evolutionEngine/optionsAndSetup.ts +2 -4
- package/test/examples/asciiMaze/evolutionEngine/populationDynamics.ts +17 -33
- package/test/examples/asciiMaze/evolutionEngine/populationPruning.ts +1 -1
- package/test/examples/asciiMaze/evolutionEngine/rngAndTiming.ts +1 -2
- package/test/examples/asciiMaze/evolutionEngine/sampling.ts +1 -1
- package/test/examples/asciiMaze/evolutionEngine/scratchPools.ts +2 -5
- package/test/examples/asciiMaze/evolutionEngine/setupHelpers.ts +30 -37
- package/test/examples/asciiMaze/evolutionEngine/telemetryMetrics.ts +16 -58
- package/test/examples/asciiMaze/evolutionEngine/trainingWarmStart.ts +2 -2
- package/test/examples/asciiMaze/evolutionEngine.ts +55 -55
- package/test/examples/asciiMaze/fitness.ts +2 -2
- package/test/examples/asciiMaze/fitness.types.ts +65 -0
- package/test/examples/asciiMaze/interfaces.ts +64 -1352
- package/test/examples/asciiMaze/mazeMovement/README.md +356 -0
- package/test/examples/asciiMaze/mazeMovement/finalization/README.md +49 -0
- package/test/examples/asciiMaze/mazeMovement/finalization/mazeMovement.finalization.ts +138 -0
- package/test/examples/asciiMaze/mazeMovement/mazeMovement.constants.ts +101 -0
- package/test/examples/asciiMaze/mazeMovement/mazeMovement.services.ts +230 -0
- package/test/examples/asciiMaze/mazeMovement/mazeMovement.ts +299 -0
- package/test/examples/asciiMaze/mazeMovement/mazeMovement.types.ts +185 -0
- package/test/examples/asciiMaze/mazeMovement/mazeMovement.utils.ts +153 -0
- package/test/examples/asciiMaze/mazeMovement/policy/README.md +91 -0
- package/test/examples/asciiMaze/mazeMovement/policy/mazeMovement.policy.ts +467 -0
- package/test/examples/asciiMaze/mazeMovement/runtime/README.md +95 -0
- package/test/examples/asciiMaze/mazeMovement/runtime/mazeMovement.runtime.ts +354 -0
- package/test/examples/asciiMaze/mazeMovement/shaping/README.md +124 -0
- package/test/examples/asciiMaze/mazeMovement/shaping/mazeMovement.shaping.ts +459 -0
- package/test/examples/asciiMaze/mazeMovement.ts +12 -2978
- package/test/examples/flappy_bird/Trace-20260309T191949.json +24124 -0
- package/test/examples/flappy_bird/browser-entry/README.md +1129 -0
- package/test/examples/flappy_bird/browser-entry/browser-entry.host.utils.ts +4 -324
- package/test/examples/flappy_bird/browser-entry/browser-entry.network-view.utils.ts +6 -399
- package/test/examples/flappy_bird/browser-entry/browser-entry.playback.utils.ts +1 -717
- package/test/examples/flappy_bird/browser-entry/browser-entry.spawn.utils.ts +11 -31
- package/test/examples/flappy_bird/browser-entry/browser-entry.visualization.utils.ts +15 -893
- package/test/examples/flappy_bird/browser-entry/host/README.md +307 -0
- package/test/examples/flappy_bird/browser-entry/host/host.resize.service.ts +1 -295
- package/test/examples/flappy_bird/browser-entry/host/host.ts +562 -6
- package/test/examples/flappy_bird/browser-entry/host/resize/README.md +274 -0
- package/test/examples/flappy_bird/browser-entry/host/resize/host.resize.service.constants.ts +31 -0
- package/test/examples/flappy_bird/browser-entry/host/resize/host.resize.service.services.ts +360 -0
- package/test/examples/flappy_bird/browser-entry/host/resize/host.resize.service.ts +117 -0
- package/test/examples/flappy_bird/browser-entry/host/resize/host.resize.service.types.ts +63 -0
- package/test/examples/flappy_bird/browser-entry/host/resize/host.resize.service.utils.ts +250 -0
- package/test/examples/flappy_bird/browser-entry/network-view/README.md +399 -0
- package/test/examples/flappy_bird/browser-entry/network-view/network-view.topology.utils.ts +255 -0
- package/test/examples/flappy_bird/browser-entry/network-view/network-view.ts +802 -7
- package/test/examples/flappy_bird/browser-entry/playback/README.md +684 -0
- package/test/examples/flappy_bird/browser-entry/playback/background/README.md +277 -0
- package/test/examples/flappy_bird/browser-entry/playback/background/ground-grid/README.md +770 -0
- package/test/examples/flappy_bird/browser-entry/playback/background/ground-grid/playback.background.ground-grid.cache.services.ts +178 -0
- package/test/examples/flappy_bird/browser-entry/playback/background/ground-grid/playback.background.ground-grid.constants.ts +107 -0
- package/test/examples/flappy_bird/browser-entry/playback/background/ground-grid/playback.background.ground-grid.geometry.utils.ts +518 -0
- package/test/examples/flappy_bird/browser-entry/playback/background/ground-grid/playback.background.ground-grid.math.utils.ts +117 -0
- package/test/examples/flappy_bird/browser-entry/playback/background/ground-grid/playback.background.ground-grid.pulse.utils.ts +233 -0
- package/test/examples/flappy_bird/browser-entry/playback/background/ground-grid/playback.background.ground-grid.services.ts +211 -0
- package/test/examples/flappy_bird/browser-entry/playback/background/ground-grid/playback.background.ground-grid.ts +48 -0
- package/test/examples/flappy_bird/browser-entry/playback/background/ground-grid/playback.background.ground-grid.types.ts +212 -0
- package/test/examples/flappy_bird/browser-entry/playback/background/ground-grid/playback.background.ground-grid.utils.ts +81 -0
- package/test/examples/flappy_bird/browser-entry/playback/background/playback.background.cache.services.ts +96 -0
- package/test/examples/flappy_bird/browser-entry/playback/background/playback.background.constants.ts +62 -0
- package/test/examples/flappy_bird/browser-entry/playback/background/playback.background.services.ts +244 -0
- package/test/examples/flappy_bird/browser-entry/playback/background/playback.background.ts +53 -0
- package/test/examples/flappy_bird/browser-entry/playback/background/playback.background.types.ts +68 -0
- package/test/examples/flappy_bird/browser-entry/playback/background/playback.background.utils.ts +100 -0
- package/test/examples/flappy_bird/browser-entry/playback/frame-render/README.md +310 -0
- package/test/examples/flappy_bird/browser-entry/playback/frame-render/playback.frame-render.service.ts +92 -0
- package/test/examples/flappy_bird/browser-entry/playback/frame-render/playback.frame-render.services.ts +272 -0
- package/test/examples/flappy_bird/browser-entry/playback/frame-render/playback.frame-render.types.ts +39 -0
- package/test/examples/flappy_bird/browser-entry/playback/frame-render/playback.frame-render.utils.ts +493 -0
- package/test/examples/flappy_bird/browser-entry/playback/playback.constants.ts +1 -1
- package/test/examples/flappy_bird/browser-entry/playback/playback.frame-render.service.ts +4 -0
- package/test/examples/flappy_bird/browser-entry/playback/playback.snapshot.utils.ts +44 -0
- package/test/examples/flappy_bird/browser-entry/playback/playback.starfield.service.ts +39 -122
- package/test/examples/flappy_bird/browser-entry/playback/playback.starfield.services.ts +272 -0
- package/test/examples/flappy_bird/browser-entry/playback/playback.starfield.types.ts +62 -0
- package/test/examples/flappy_bird/browser-entry/playback/playback.starfield.utils.ts +11 -4
- package/test/examples/flappy_bird/browser-entry/playback/playback.ts +409 -8
- package/test/examples/flappy_bird/browser-entry/playback/playback.types.ts +4 -12
- package/test/examples/flappy_bird/browser-entry/runtime/README.md +235 -0
- package/test/examples/flappy_bird/browser-entry/runtime/runtime.evolution-launch.service.ts +45 -0
- package/test/examples/flappy_bird/browser-entry/runtime/runtime.lifecycle.service.ts +81 -0
- package/test/examples/flappy_bird/browser-entry/runtime/runtime.startup.service.ts +74 -0
- package/test/examples/flappy_bird/browser-entry/runtime/runtime.ts +31 -121
- package/test/examples/flappy_bird/browser-entry/runtime/runtime.types.ts +36 -0
- package/test/examples/flappy_bird/browser-entry/visualization/README.md +557 -0
- package/test/examples/flappy_bird/browser-entry/visualization/visualization.constants.ts +110 -0
- package/test/examples/flappy_bird/browser-entry/visualization/visualization.draw.service.ts +957 -19
- package/test/examples/flappy_bird/browser-entry/visualization/visualization.legend.utils.ts +138 -3
- package/test/examples/flappy_bird/browser-entry/visualization/visualization.topology.utils.ts +3 -27
- package/test/examples/flappy_bird/browser-entry/visualization/visualization.ts +1 -23
- package/test/examples/flappy_bird/browser-entry/worker-channel/README.md +156 -0
- package/test/examples/flappy_bird/constants/README.md +1179 -0
- package/test/examples/flappy_bird/constants/constants.network-view.ts +24 -0
- package/test/examples/flappy_bird/constants/constants.palette.ts +7 -0
- package/test/examples/flappy_bird/constants/constants.starfield.ts +78 -3
- package/test/examples/flappy_bird/environment/README.md +143 -0
- package/test/examples/flappy_bird/environment/environment.observation.utils.ts +1 -19
- package/test/examples/flappy_bird/environment/environment.step.service.ts +3 -66
- package/test/examples/flappy_bird/evaluation/README.md +130 -0
- package/test/examples/flappy_bird/evaluation/evaluation.fitness.utils.ts +1 -1
- package/test/examples/flappy_bird/evaluation/evaluation.rollout.service.ts +5 -375
- package/test/examples/flappy_bird/evaluation/rollout/README.md +291 -0
- package/test/examples/flappy_bird/evaluation/rollout/evaluation.rollout.constants.ts +30 -0
- package/test/examples/flappy_bird/evaluation/rollout/evaluation.rollout.service.ts +58 -0
- package/test/examples/flappy_bird/evaluation/rollout/evaluation.rollout.services.ts +310 -0
- package/test/examples/flappy_bird/evaluation/rollout/evaluation.rollout.types.ts +56 -0
- package/test/examples/flappy_bird/evaluation/rollout/evaluation.rollout.utils.ts +368 -0
- package/test/examples/flappy_bird/flappy-evolution-worker/README.md +618 -0
- package/test/examples/flappy_bird/flappy-evolution-worker/flappy-evolution-worker.playback.service.ts +7 -7
- package/test/examples/flappy_bird/flappy-evolution-worker/flappy-evolution-worker.simulation.frame.service.ts +364 -0
- package/test/examples/flappy_bird/flappy-evolution-worker/flappy-evolution-worker.simulation.types.ts +14 -0
- package/test/examples/flappy_bird/flappy-evolution-worker/flappy-evolution-worker.simulation.utils.ts +4 -201
- package/test/examples/flappy_bird/flappy-evolution-worker/flappy-evolution-worker.ts +184 -345
- package/test/examples/flappy_bird/flappy-evolution-worker/flappy-evolution-worker.warm-start.service.ts +291 -0
- package/test/examples/flappy_bird/flappy.simulation.shared.utils.ts +5 -0
- package/test/examples/flappy_bird/simulation-shared/README.md +417 -0
- package/test/examples/flappy_bird/simulation-shared/observation/README.md +183 -0
- package/test/examples/flappy_bird/simulation-shared/observation/observation.features.utils.ts +301 -0
- package/test/examples/flappy_bird/simulation-shared/observation/observation.ts +9 -0
- package/test/examples/flappy_bird/simulation-shared/observation/observation.vector.utils.ts +59 -0
- package/test/examples/flappy_bird/simulation-shared/simulation-shared.observation.utils.ts +5 -403
- package/test/examples/flappy_bird/simulation-shared/simulation-shared.spawn.utils.ts +20 -6
- package/test/examples/flappy_bird/{evaluation/evaluation.statistics.utils.ts → simulation-shared/simulation-shared.statistics.utils.ts} +23 -8
- package/test/examples/flappy_bird/trainer/README.md +563 -0
- package/test/examples/flappy_bird/trainer/evaluation/README.md +199 -0
- package/test/examples/flappy_bird/trainer/evaluation/trainer.evaluation.service.constants.ts +9 -0
- package/test/examples/flappy_bird/trainer/evaluation/trainer.evaluation.service.services.ts +73 -0
- package/test/examples/flappy_bird/trainer/evaluation/trainer.evaluation.service.ts +165 -0
- package/test/examples/flappy_bird/trainer/evaluation/trainer.evaluation.service.types.ts +25 -0
- package/test/examples/flappy_bird/trainer/evaluation/trainer.evaluation.service.utils.ts +161 -0
- package/test/examples/flappy_bird/trainer/trainer.evaluation.service.ts +13 -0
- package/test/examples/flappy_bird/trainer/trainer.report.service.services.ts +181 -0
- package/test/examples/flappy_bird/trainer/trainer.report.service.ts +126 -0
- package/test/examples/flappy_bird/trainer/trainer.selection.utils.ts +89 -0
- package/test/examples/flappy_bird/trainer/trainer.ts +11 -553
- package/test/examples/flappy_bird/browser-entry/browser-entry.utils.ts +0 -12
- package/test/examples/flappy_bird/environment/environment.ts +0 -7
- package/test/examples/flappy_bird/evaluation/evaluation.ts +0 -7
- package/test/examples/flappy_bird/simulation-shared/simulation-shared.ts +0 -15
- package/test/examples/flappy_bird/trainer/trainer.statistics.utils.ts +0 -78
|
@@ -1,12 +1,111 @@
|
|
|
1
1
|
import Network from '../../../../../src/architecture/network';
|
|
2
2
|
import {
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
3
|
+
FLAPPY_NETWORK_ARCHITECTURE_COLUMN_SEPARATOR,
|
|
4
|
+
FLAPPY_NETWORK_ARCHITECTURE_LINE_SEPARATOR,
|
|
5
|
+
FLAPPY_NETWORK_BASELINE_HEIGHT_PX,
|
|
6
|
+
FLAPPY_NETWORK_EMPTY_HIDDEN_LAYER_LABEL,
|
|
7
|
+
FLAPPY_NETWORK_GRAPH_BOTTOM_PADDING_PX,
|
|
8
|
+
FLAPPY_NETWORK_GRAPH_INNER_PADDING_PX,
|
|
9
|
+
FLAPPY_NETWORK_GRAPH_LEFT_PADDING_PX,
|
|
10
|
+
FLAPPY_NETWORK_GRAPH_RIGHT_PADDING_PX,
|
|
11
|
+
FLAPPY_NETWORK_GRAPH_TOP_PADDING_PX,
|
|
12
|
+
FLAPPY_NETWORK_HIDDEN_LAYER_SEPARATOR,
|
|
13
|
+
FLAPPY_NETWORK_INFERRED_HIDDEN_LAYER_PREFIX,
|
|
14
|
+
FLAPPY_NETWORK_INPUT_GROUP_LABEL_BAND_GAP_PX,
|
|
15
|
+
FLAPPY_NETWORK_INPUT_GROUP_LABEL_BAND_WIDTH_PX,
|
|
16
|
+
FLAPPY_NETWORK_LAYER_COMPLEXITY_BASELINE_COUNT,
|
|
17
|
+
FLAPPY_NETWORK_LAYER_COMPLEXITY_HEIGHT_STEP_PX,
|
|
18
|
+
FLAPPY_NETWORK_LEGEND_GRAPH_GAP_PX,
|
|
19
|
+
FLAPPY_NETWORK_LEGEND_RIGHT_SIDE_THRESHOLD_RATIO,
|
|
20
|
+
FLAPPY_NETWORK_MAX_HEIGHT_PX,
|
|
21
|
+
FLAPPY_NETWORK_MAX_NODE_HEIGHT_PX,
|
|
22
|
+
FLAPPY_NETWORK_MAX_NODE_WIDTH_PX,
|
|
23
|
+
FLAPPY_NETWORK_MIN_HEIGHT_PX,
|
|
24
|
+
FLAPPY_NETWORK_MIN_INTER_NODE_GAP_PX,
|
|
25
|
+
FLAPPY_NETWORK_MIN_LABEL_HEIGHT_PX,
|
|
26
|
+
FLAPPY_NETWORK_MIN_DRAWABLE_SIZE_PX,
|
|
27
|
+
FLAPPY_NETWORK_MIN_NODE_FIT_HEIGHT_PX,
|
|
28
|
+
FLAPPY_NETWORK_MIN_NODE_HEIGHT_LABEL_EXTRA_PX,
|
|
29
|
+
FLAPPY_NETWORK_MIN_NODE_INNER_PADDING_PX,
|
|
30
|
+
FLAPPY_NETWORK_MIN_NODE_WIDTH_PX,
|
|
31
|
+
FLAPPY_NETWORK_NODE_DENSITY_BASELINE_COUNT,
|
|
32
|
+
FLAPPY_NETWORK_NODE_DENSITY_HEIGHT_STEP_PX,
|
|
33
|
+
FLAPPY_NETWORK_NODE_HEIGHT_DENSITY_DIVISOR,
|
|
34
|
+
FLAPPY_NETWORK_NODE_HEIGHT_DENSITY_MIN_DENOMINATOR,
|
|
35
|
+
FLAPPY_NETWORK_NODE_HEIGHT_LAYER_WIDTH_DIVISOR,
|
|
36
|
+
FLAPPY_NETWORK_NODE_HEIGHT_LAYER_WIDTH_MIN_DENOMINATOR,
|
|
37
|
+
FLAPPY_NETWORK_NODE_LAYOUT_PADDING_PX,
|
|
38
|
+
FLAPPY_NETWORK_NODE_WIDTH_LAYER_WIDTH_DIVISOR,
|
|
39
|
+
FLAPPY_NETWORK_NODE_WIDTH_LAYER_WIDTH_MIN_DENOMINATOR,
|
|
40
|
+
FLAPPY_NETWORK_NODE_WIDTH_TO_HEIGHT_RATIO,
|
|
41
|
+
FLAPPY_NETWORK_TOPOLOGY_HEIGHT_MULTIPLIER,
|
|
42
|
+
FLAPPY_UI_NETWORK_CANVAS_BACKGROUND,
|
|
43
|
+
FLAPPY_VIEWPORT_NETWORK_OVERLAY_HIDDEN_BREAKPOINT_PX,
|
|
44
|
+
} from '../../constants/constants';
|
|
45
|
+
import { clamp } from '../browser-entry.math.utils';
|
|
46
|
+
import type {
|
|
47
|
+
NetworkNodeDimensionsLike as NetworkNodeDimensions,
|
|
48
|
+
PositionedNetworkNodeLike as PositionedNetworkNode,
|
|
49
|
+
VisualNetworkConnectionLike,
|
|
50
|
+
} from '../browser-entry.types';
|
|
51
|
+
import {
|
|
52
|
+
drawBiasNodesLayer,
|
|
53
|
+
drawNetworkColorLegend,
|
|
54
|
+
drawWeightedConnectionsLayer,
|
|
55
|
+
} from '../visualization/visualization.draw.service';
|
|
56
|
+
import { resolveDefaultNetworkLegendLayout } from '../visualization/visualization.legend.utils';
|
|
57
|
+
import { resolveNetworkVisualizationColorScales } from '../visualization/visualization.colors.utils';
|
|
58
|
+
import type { NetworkVisualizationColorScales } from '../visualization/visualization.types';
|
|
59
|
+
import { drawInputGroupLabelBands } from './network-view.draw.service';
|
|
60
|
+
import {
|
|
61
|
+
centerPositionedNodesInDrawableArea,
|
|
62
|
+
positionNetworkNodes,
|
|
63
|
+
} from './network-view.layout.utils';
|
|
64
|
+
import { resolveNetworkVisualizationLayers } from './network-view.topology.utils';
|
|
65
|
+
|
|
66
|
+
type NetworkTopologySummary = {
|
|
67
|
+
networkLayers: ReturnType<typeof resolveNetworkVisualizationLayers>;
|
|
68
|
+
layerCount: number;
|
|
69
|
+
maximumLayerNodeCount: number;
|
|
70
|
+
};
|
|
71
|
+
|
|
72
|
+
type NetworkGraphPaddingContext = {
|
|
73
|
+
graphLeftPaddingPx: number;
|
|
74
|
+
graphTopPaddingPx: number;
|
|
75
|
+
graphRightPaddingPx: number;
|
|
76
|
+
graphBottomPaddingPx: number;
|
|
77
|
+
};
|
|
78
|
+
|
|
79
|
+
type NetworkVisualizationScene = NetworkGraphPaddingContext & {
|
|
80
|
+
canvasWidthPx: number;
|
|
81
|
+
canvasHeightPx: number;
|
|
82
|
+
architectureLabel: string;
|
|
83
|
+
colorScales: NetworkVisualizationColorScales;
|
|
84
|
+
hideNetworkOverlays: boolean;
|
|
85
|
+
adjustedGraphLeftPaddingPx: number;
|
|
86
|
+
adjustedGraphRightPaddingPx: number;
|
|
87
|
+
};
|
|
88
|
+
|
|
89
|
+
type NetworkDrawableArea = {
|
|
90
|
+
drawableWidthPx: number;
|
|
91
|
+
drawableHeightPx: number;
|
|
92
|
+
};
|
|
93
|
+
|
|
94
|
+
type PositionedNetworkGraphScene = {
|
|
95
|
+
centeredPositionedNodes: PositionedNetworkNode[];
|
|
96
|
+
positionByNodeIndex: Map<number, PositionedNetworkNode>;
|
|
97
|
+
runtimeConnections: VisualNetworkConnectionLike[];
|
|
98
|
+
nodeDimensions: NetworkNodeDimensions;
|
|
99
|
+
};
|
|
7
100
|
|
|
8
101
|
/**
|
|
9
102
|
* Draws a complete, layer-based visualization of the active network.
|
|
103
|
+
*
|
|
104
|
+
* @param context - Canvas 2D drawing context.
|
|
105
|
+
* @param network - Network to visualize.
|
|
106
|
+
* @param inputSize - Input-layer size.
|
|
107
|
+
* @param outputSize - Output-layer size.
|
|
108
|
+
* @returns Nothing.
|
|
10
109
|
*/
|
|
11
110
|
export function drawNetworkVisualization(
|
|
12
111
|
context: CanvasRenderingContext2D,
|
|
@@ -14,35 +113,731 @@ export function drawNetworkVisualization(
|
|
|
14
113
|
inputSize: number,
|
|
15
114
|
outputSize: number,
|
|
16
115
|
): void {
|
|
17
|
-
|
|
116
|
+
// Step 1: Resolve canvas, label, overlay, and padding state for this frame.
|
|
117
|
+
const networkVisualizationScene = resolveNetworkVisualizationScene(
|
|
118
|
+
context,
|
|
119
|
+
network,
|
|
120
|
+
inputSize,
|
|
121
|
+
outputSize,
|
|
122
|
+
);
|
|
123
|
+
|
|
124
|
+
// Step 2: Paint the base canvas background before graph layers are drawn.
|
|
125
|
+
paintNetworkVisualizationCanvasBase(context, networkVisualizationScene);
|
|
126
|
+
|
|
127
|
+
// Step 3: Resolve node layout, node dimensions, and connection lookup state.
|
|
128
|
+
const positionedNetworkGraphScene = resolvePositionedNetworkGraphScene(
|
|
129
|
+
networkVisualizationScene,
|
|
130
|
+
network,
|
|
131
|
+
inputSize,
|
|
132
|
+
outputSize,
|
|
133
|
+
);
|
|
134
|
+
|
|
135
|
+
// Step 4: Draw the graph layers and optional helper overlays.
|
|
136
|
+
drawPositionedNetworkGraph(
|
|
137
|
+
context,
|
|
138
|
+
networkVisualizationScene,
|
|
139
|
+
positionedNetworkGraphScene,
|
|
140
|
+
);
|
|
141
|
+
|
|
142
|
+
// Step 5: Draw the legend after the graph so the overlay stays visually on top.
|
|
143
|
+
drawNetworkColorLegend(
|
|
144
|
+
context,
|
|
145
|
+
networkVisualizationScene.architectureLabel,
|
|
146
|
+
networkVisualizationScene.colorScales,
|
|
147
|
+
);
|
|
18
148
|
}
|
|
19
149
|
|
|
20
150
|
/**
|
|
21
151
|
* Resolves responsive visualization canvas height from network shape.
|
|
152
|
+
*
|
|
153
|
+
* @param network - Network to visualize.
|
|
154
|
+
* @param inputSize - Input-layer size.
|
|
155
|
+
* @param outputSize - Output-layer size.
|
|
156
|
+
* @returns Recommended height in pixels.
|
|
22
157
|
*/
|
|
23
158
|
export function resolveNetworkVisualizationHeightPx(
|
|
24
159
|
network: Network | undefined,
|
|
25
160
|
inputSize: number,
|
|
26
161
|
outputSize: number,
|
|
27
162
|
): number {
|
|
28
|
-
|
|
163
|
+
// Step 1: Summarize layer count and density from the resolved topology.
|
|
164
|
+
const networkTopologySummary = resolveNetworkTopologySummary(
|
|
29
165
|
network,
|
|
30
166
|
inputSize,
|
|
31
167
|
outputSize,
|
|
32
168
|
);
|
|
169
|
+
|
|
170
|
+
// Step 2: Compute the minimum readable height required by the topology.
|
|
171
|
+
const topologyDrivenHeightPx = resolveTopologyDrivenHeightPx(
|
|
172
|
+
networkTopologySummary,
|
|
173
|
+
);
|
|
174
|
+
|
|
175
|
+
// Step 3: Blend topology minimums with density and complexity adjustments.
|
|
176
|
+
const recommendedHeightPx = resolveRecommendedNetworkHeightPx(
|
|
177
|
+
networkTopologySummary,
|
|
178
|
+
topologyDrivenHeightPx,
|
|
179
|
+
);
|
|
180
|
+
|
|
181
|
+
// Step 4: Clamp the result into the configured host panel range.
|
|
182
|
+
return clampRecommendedNetworkHeightPx(recommendedHeightPx);
|
|
33
183
|
}
|
|
34
184
|
|
|
35
185
|
/**
|
|
36
186
|
* Resolves compact architecture label text for headers and HUD rows.
|
|
187
|
+
*
|
|
188
|
+
* @param network - Network to describe.
|
|
189
|
+
* @param inputSize - Configured input size.
|
|
190
|
+
* @param outputSize - Configured output size.
|
|
191
|
+
* @returns Readable architecture label.
|
|
37
192
|
*/
|
|
38
193
|
export function resolveNetworkArchitectureLabel(
|
|
39
194
|
network: Network | undefined,
|
|
40
195
|
inputSize: number,
|
|
41
196
|
outputSize: number,
|
|
42
197
|
): string {
|
|
43
|
-
|
|
198
|
+
// Step 1: Fall back to a placeholder hidden-layer label when no network is active.
|
|
199
|
+
if (!network) {
|
|
200
|
+
return formatArchitectureLabel(
|
|
201
|
+
inputSize,
|
|
202
|
+
FLAPPY_NETWORK_EMPTY_HIDDEN_LAYER_LABEL,
|
|
203
|
+
outputSize,
|
|
204
|
+
inputSize + outputSize,
|
|
205
|
+
0,
|
|
206
|
+
);
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
// Step 2: Describe the active network and resolve the hidden-layer fragment.
|
|
210
|
+
const architectureDescriptor = network.describeArchitecture();
|
|
211
|
+
const hiddenLayersLabel = resolveHiddenLayersLabel(
|
|
212
|
+
architectureDescriptor.hiddenLayerSizes,
|
|
213
|
+
architectureDescriptor.source,
|
|
214
|
+
);
|
|
215
|
+
|
|
216
|
+
// Step 3: Compose the two-line architecture label from the descriptor values.
|
|
217
|
+
return formatArchitectureLabel(
|
|
218
|
+
inputSize,
|
|
219
|
+
hiddenLayersLabel,
|
|
220
|
+
outputSize,
|
|
221
|
+
architectureDescriptor.totalNodes,
|
|
222
|
+
architectureDescriptor.totalConnections,
|
|
223
|
+
);
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
/**
|
|
227
|
+
* Resolves all non-topology canvas state needed to draw the network view.
|
|
228
|
+
*
|
|
229
|
+
* @param context - Canvas 2D drawing context.
|
|
230
|
+
* @param network - Network to visualize.
|
|
231
|
+
* @param inputSize - Input-layer size.
|
|
232
|
+
* @param outputSize - Output-layer size.
|
|
233
|
+
* @returns Scene context for the current frame.
|
|
234
|
+
*/
|
|
235
|
+
function resolveNetworkVisualizationScene(
|
|
236
|
+
context: CanvasRenderingContext2D,
|
|
237
|
+
network: Network | undefined,
|
|
238
|
+
inputSize: number,
|
|
239
|
+
outputSize: number,
|
|
240
|
+
): NetworkVisualizationScene {
|
|
241
|
+
// Step 1: Resolve the shared canvas dimensions and overlay label state.
|
|
242
|
+
const canvasWidthPx = context.canvas.width;
|
|
243
|
+
const canvasHeightPx = context.canvas.height;
|
|
244
|
+
const architectureLabel = resolveNetworkArchitectureLabel(
|
|
44
245
|
network,
|
|
45
246
|
inputSize,
|
|
46
247
|
outputSize,
|
|
47
248
|
);
|
|
249
|
+
const colorScales = resolveNetworkVisualizationColorScales(network);
|
|
250
|
+
const graphPaddingContext = resolveBaseGraphPaddingContext();
|
|
251
|
+
const hideNetworkOverlays = shouldHideNetworkOverlays(context, canvasWidthPx);
|
|
252
|
+
|
|
253
|
+
// Step 2: Adjust graph-side padding when the legend is visible.
|
|
254
|
+
const adjustedGraphPaddingContext = resolveAdjustedGraphPaddingContext(
|
|
255
|
+
context,
|
|
256
|
+
network,
|
|
257
|
+
canvasWidthPx,
|
|
258
|
+
hideNetworkOverlays,
|
|
259
|
+
graphPaddingContext,
|
|
260
|
+
);
|
|
261
|
+
|
|
262
|
+
return {
|
|
263
|
+
canvasWidthPx,
|
|
264
|
+
canvasHeightPx,
|
|
265
|
+
architectureLabel,
|
|
266
|
+
colorScales,
|
|
267
|
+
hideNetworkOverlays,
|
|
268
|
+
graphTopPaddingPx: graphPaddingContext.graphTopPaddingPx,
|
|
269
|
+
graphBottomPaddingPx: graphPaddingContext.graphBottomPaddingPx,
|
|
270
|
+
graphLeftPaddingPx: graphPaddingContext.graphLeftPaddingPx,
|
|
271
|
+
graphRightPaddingPx: graphPaddingContext.graphRightPaddingPx,
|
|
272
|
+
adjustedGraphLeftPaddingPx: adjustedGraphPaddingContext.graphLeftPaddingPx,
|
|
273
|
+
adjustedGraphRightPaddingPx:
|
|
274
|
+
adjustedGraphPaddingContext.graphRightPaddingPx,
|
|
275
|
+
};
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
/**
|
|
279
|
+
* Paints the base network visualization canvas background.
|
|
280
|
+
*
|
|
281
|
+
* @param context - Canvas 2D drawing context.
|
|
282
|
+
* @param networkVisualizationScene - Frame scene context.
|
|
283
|
+
* @returns Nothing.
|
|
284
|
+
*/
|
|
285
|
+
function paintNetworkVisualizationCanvasBase(
|
|
286
|
+
context: CanvasRenderingContext2D,
|
|
287
|
+
networkVisualizationScene: NetworkVisualizationScene,
|
|
288
|
+
): void {
|
|
289
|
+
// Step 1: Clear the full canvas before repainting the current frame.
|
|
290
|
+
context.clearRect(
|
|
291
|
+
0,
|
|
292
|
+
0,
|
|
293
|
+
networkVisualizationScene.canvasWidthPx,
|
|
294
|
+
networkVisualizationScene.canvasHeightPx,
|
|
295
|
+
);
|
|
296
|
+
|
|
297
|
+
// Step 2: Fill the visualization panel background.
|
|
298
|
+
context.fillStyle = FLAPPY_UI_NETWORK_CANVAS_BACKGROUND;
|
|
299
|
+
context.fillRect(
|
|
300
|
+
0,
|
|
301
|
+
0,
|
|
302
|
+
networkVisualizationScene.canvasWidthPx,
|
|
303
|
+
networkVisualizationScene.canvasHeightPx,
|
|
304
|
+
);
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
/**
|
|
308
|
+
* Resolves positioned nodes, connection lookup state, and shared node dimensions.
|
|
309
|
+
*
|
|
310
|
+
* @param networkVisualizationScene - Frame scene context.
|
|
311
|
+
* @param network - Network to visualize.
|
|
312
|
+
* @param inputSize - Input-layer size.
|
|
313
|
+
* @param outputSize - Output-layer size.
|
|
314
|
+
* @returns Positioned graph scene.
|
|
315
|
+
*/
|
|
316
|
+
function resolvePositionedNetworkGraphScene(
|
|
317
|
+
networkVisualizationScene: NetworkVisualizationScene,
|
|
318
|
+
network: Network | undefined,
|
|
319
|
+
inputSize: number,
|
|
320
|
+
outputSize: number,
|
|
321
|
+
): PositionedNetworkGraphScene {
|
|
322
|
+
// Step 1: Resolve topology and drawable bounds for the current graph region.
|
|
323
|
+
const networkTopologySummary = resolveNetworkTopologySummary(
|
|
324
|
+
network,
|
|
325
|
+
inputSize,
|
|
326
|
+
outputSize,
|
|
327
|
+
);
|
|
328
|
+
const networkDrawableArea = resolveNetworkDrawableArea(
|
|
329
|
+
networkVisualizationScene,
|
|
330
|
+
);
|
|
331
|
+
const nodeDimensions = resolveNetworkNodeDimensionsFromTopologySummary(
|
|
332
|
+
networkTopologySummary,
|
|
333
|
+
networkDrawableArea.drawableWidthPx,
|
|
334
|
+
networkDrawableArea.drawableHeightPx,
|
|
335
|
+
);
|
|
336
|
+
|
|
337
|
+
// Step 2: Position nodes inside the padded drawable region and center them.
|
|
338
|
+
const positionedNodes = positionNetworkNodes(
|
|
339
|
+
networkTopologySummary.networkLayers,
|
|
340
|
+
networkVisualizationScene.adjustedGraphLeftPaddingPx,
|
|
341
|
+
networkVisualizationScene.graphTopPaddingPx,
|
|
342
|
+
networkDrawableArea.drawableWidthPx,
|
|
343
|
+
networkDrawableArea.drawableHeightPx,
|
|
344
|
+
FLAPPY_NETWORK_NODE_LAYOUT_PADDING_PX,
|
|
345
|
+
nodeDimensions,
|
|
346
|
+
);
|
|
347
|
+
const centeredPositionedNodes = centerPositionedNodesInDrawableArea(
|
|
348
|
+
positionedNodes,
|
|
349
|
+
networkVisualizationScene.adjustedGraphLeftPaddingPx,
|
|
350
|
+
networkVisualizationScene.graphTopPaddingPx,
|
|
351
|
+
networkDrawableArea.drawableWidthPx,
|
|
352
|
+
networkDrawableArea.drawableHeightPx,
|
|
353
|
+
FLAPPY_NETWORK_NODE_LAYOUT_PADDING_PX,
|
|
354
|
+
nodeDimensions,
|
|
355
|
+
);
|
|
356
|
+
|
|
357
|
+
// Step 3: Build the connection lookup state used by the drawing layers.
|
|
358
|
+
return {
|
|
359
|
+
centeredPositionedNodes,
|
|
360
|
+
positionByNodeIndex: createPositionByNodeIndex(centeredPositionedNodes),
|
|
361
|
+
runtimeConnections: resolveRuntimeConnections(network),
|
|
362
|
+
nodeDimensions,
|
|
363
|
+
};
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
/**
|
|
367
|
+
* Draws the positioned graph layers and optional guide overlays.
|
|
368
|
+
*
|
|
369
|
+
* @param context - Canvas 2D drawing context.
|
|
370
|
+
* @param networkVisualizationScene - Frame scene context.
|
|
371
|
+
* @param positionedNetworkGraphScene - Positioned graph scene.
|
|
372
|
+
* @returns Nothing.
|
|
373
|
+
*/
|
|
374
|
+
function drawPositionedNetworkGraph(
|
|
375
|
+
context: CanvasRenderingContext2D,
|
|
376
|
+
networkVisualizationScene: NetworkVisualizationScene,
|
|
377
|
+
positionedNetworkGraphScene: PositionedNetworkGraphScene,
|
|
378
|
+
): void {
|
|
379
|
+
// Step 1: Draw weighted connections beneath the node rectangles.
|
|
380
|
+
drawWeightedConnectionsLayer(
|
|
381
|
+
context,
|
|
382
|
+
positionedNetworkGraphScene.runtimeConnections,
|
|
383
|
+
positionedNetworkGraphScene.positionByNodeIndex,
|
|
384
|
+
networkVisualizationScene.colorScales.connectionScale,
|
|
385
|
+
);
|
|
386
|
+
|
|
387
|
+
// Step 2: Draw input-group label bands only when overlays are visible.
|
|
388
|
+
if (!networkVisualizationScene.hideNetworkOverlays) {
|
|
389
|
+
drawInputGroupLabelBands(
|
|
390
|
+
context,
|
|
391
|
+
positionedNetworkGraphScene.centeredPositionedNodes,
|
|
392
|
+
positionedNetworkGraphScene.nodeDimensions,
|
|
393
|
+
);
|
|
394
|
+
}
|
|
395
|
+
|
|
396
|
+
// Step 3: Draw node rectangles and bias labels over the connection layer.
|
|
397
|
+
drawBiasNodesLayer(
|
|
398
|
+
context,
|
|
399
|
+
positionedNetworkGraphScene.centeredPositionedNodes,
|
|
400
|
+
positionedNetworkGraphScene.nodeDimensions,
|
|
401
|
+
networkVisualizationScene.colorScales.biasScale,
|
|
402
|
+
);
|
|
403
|
+
}
|
|
404
|
+
|
|
405
|
+
/**
|
|
406
|
+
* Resolves the base graph padding before legend-aware adjustments are applied.
|
|
407
|
+
*
|
|
408
|
+
* @returns Base graph padding context.
|
|
409
|
+
*/
|
|
410
|
+
function resolveBaseGraphPaddingContext(): NetworkGraphPaddingContext {
|
|
411
|
+
// Step 1: Reserve the input-group label band to the left of the graph body.
|
|
412
|
+
const groupLabelBandReserveWidthPx =
|
|
413
|
+
FLAPPY_NETWORK_INPUT_GROUP_LABEL_BAND_WIDTH_PX +
|
|
414
|
+
FLAPPY_NETWORK_INPUT_GROUP_LABEL_BAND_GAP_PX +
|
|
415
|
+
FLAPPY_NETWORK_NODE_LAYOUT_PADDING_PX;
|
|
416
|
+
|
|
417
|
+
return {
|
|
418
|
+
graphLeftPaddingPx:
|
|
419
|
+
FLAPPY_NETWORK_GRAPH_LEFT_PADDING_PX + groupLabelBandReserveWidthPx,
|
|
420
|
+
graphTopPaddingPx: FLAPPY_NETWORK_GRAPH_TOP_PADDING_PX,
|
|
421
|
+
graphRightPaddingPx: FLAPPY_NETWORK_GRAPH_RIGHT_PADDING_PX,
|
|
422
|
+
graphBottomPaddingPx: FLAPPY_NETWORK_GRAPH_BOTTOM_PADDING_PX,
|
|
423
|
+
};
|
|
424
|
+
}
|
|
425
|
+
|
|
426
|
+
/**
|
|
427
|
+
* Determines whether responsive rules hide auxiliary network overlays.
|
|
428
|
+
*
|
|
429
|
+
* @param context - Canvas 2D drawing context.
|
|
430
|
+
* @param fallbackViewportWidthPx - Fallback viewport width.
|
|
431
|
+
* @returns True when overlays should be hidden.
|
|
432
|
+
*/
|
|
433
|
+
function shouldHideNetworkOverlays(
|
|
434
|
+
context: CanvasRenderingContext2D,
|
|
435
|
+
fallbackViewportWidthPx: number,
|
|
436
|
+
): boolean {
|
|
437
|
+
// Step 1: Prefer the browser viewport width and fall back to canvas width in tests.
|
|
438
|
+
const viewportWidthPx =
|
|
439
|
+
context.canvas.ownerDocument?.defaultView?.innerWidth ??
|
|
440
|
+
fallbackViewportWidthPx;
|
|
441
|
+
return viewportWidthPx < FLAPPY_VIEWPORT_NETWORK_OVERLAY_HIDDEN_BREAKPOINT_PX;
|
|
442
|
+
}
|
|
443
|
+
|
|
444
|
+
/**
|
|
445
|
+
* Adjusts graph-side padding to keep the floating legend from overlapping nodes.
|
|
446
|
+
*
|
|
447
|
+
* @param context - Canvas 2D drawing context.
|
|
448
|
+
* @param network - Network to visualize.
|
|
449
|
+
* @param canvasWidthPx - Canvas width.
|
|
450
|
+
* @param hideNetworkOverlays - Whether overlays are hidden.
|
|
451
|
+
* @param graphPaddingContext - Base graph padding context.
|
|
452
|
+
* @returns Adjusted graph padding context.
|
|
453
|
+
*/
|
|
454
|
+
function resolveAdjustedGraphPaddingContext(
|
|
455
|
+
context: CanvasRenderingContext2D,
|
|
456
|
+
network: Network | undefined,
|
|
457
|
+
canvasWidthPx: number,
|
|
458
|
+
hideNetworkOverlays: boolean,
|
|
459
|
+
graphPaddingContext: NetworkGraphPaddingContext,
|
|
460
|
+
): Pick<
|
|
461
|
+
NetworkGraphPaddingContext,
|
|
462
|
+
'graphLeftPaddingPx' | 'graphRightPaddingPx'
|
|
463
|
+
> {
|
|
464
|
+
// Step 1: Keep the base paddings unchanged when overlays are hidden.
|
|
465
|
+
if (hideNetworkOverlays) {
|
|
466
|
+
return {
|
|
467
|
+
graphLeftPaddingPx: graphPaddingContext.graphLeftPaddingPx,
|
|
468
|
+
graphRightPaddingPx: graphPaddingContext.graphRightPaddingPx,
|
|
469
|
+
};
|
|
470
|
+
}
|
|
471
|
+
|
|
472
|
+
// Step 2: Measure the legend and determine which half of the canvas it occupies.
|
|
473
|
+
const legendLayout = resolveDefaultNetworkLegendLayout(context, network);
|
|
474
|
+
const legendMidpointPx =
|
|
475
|
+
legendLayout.legendLeftPx +
|
|
476
|
+
legendLayout.legendWidthPx *
|
|
477
|
+
FLAPPY_NETWORK_LEGEND_RIGHT_SIDE_THRESHOLD_RATIO;
|
|
478
|
+
if (
|
|
479
|
+
legendMidpointPx >=
|
|
480
|
+
canvasWidthPx * FLAPPY_NETWORK_LEGEND_RIGHT_SIDE_THRESHOLD_RATIO
|
|
481
|
+
) {
|
|
482
|
+
return {
|
|
483
|
+
graphLeftPaddingPx: graphPaddingContext.graphLeftPaddingPx,
|
|
484
|
+
graphRightPaddingPx: Math.max(
|
|
485
|
+
graphPaddingContext.graphRightPaddingPx,
|
|
486
|
+
canvasWidthPx -
|
|
487
|
+
legendLayout.legendLeftPx +
|
|
488
|
+
FLAPPY_NETWORK_LEGEND_GRAPH_GAP_PX,
|
|
489
|
+
),
|
|
490
|
+
};
|
|
491
|
+
}
|
|
492
|
+
|
|
493
|
+
// Step 3: Otherwise, shift the graph body right so it clears a left-side legend.
|
|
494
|
+
return {
|
|
495
|
+
graphLeftPaddingPx: Math.max(
|
|
496
|
+
graphPaddingContext.graphLeftPaddingPx,
|
|
497
|
+
legendLayout.legendLeftPx +
|
|
498
|
+
legendLayout.legendWidthPx +
|
|
499
|
+
FLAPPY_NETWORK_LEGEND_GRAPH_GAP_PX,
|
|
500
|
+
),
|
|
501
|
+
graphRightPaddingPx: graphPaddingContext.graphRightPaddingPx,
|
|
502
|
+
};
|
|
503
|
+
}
|
|
504
|
+
|
|
505
|
+
/**
|
|
506
|
+
* Resolves the drawable graph area after scene padding is applied.
|
|
507
|
+
*
|
|
508
|
+
* @param networkVisualizationScene - Frame scene context.
|
|
509
|
+
* @returns Drawable area dimensions.
|
|
510
|
+
*/
|
|
511
|
+
function resolveNetworkDrawableArea(
|
|
512
|
+
networkVisualizationScene: NetworkVisualizationScene,
|
|
513
|
+
): NetworkDrawableArea {
|
|
514
|
+
// Step 1: Subtract side paddings while enforcing a positive drawable width.
|
|
515
|
+
const drawableWidthPx = Math.max(
|
|
516
|
+
FLAPPY_NETWORK_MIN_DRAWABLE_SIZE_PX,
|
|
517
|
+
networkVisualizationScene.canvasWidthPx -
|
|
518
|
+
networkVisualizationScene.adjustedGraphLeftPaddingPx -
|
|
519
|
+
networkVisualizationScene.adjustedGraphRightPaddingPx,
|
|
520
|
+
);
|
|
521
|
+
|
|
522
|
+
// Step 2: Subtract vertical paddings while enforcing a positive drawable height.
|
|
523
|
+
const drawableHeightPx = Math.max(
|
|
524
|
+
FLAPPY_NETWORK_MIN_DRAWABLE_SIZE_PX,
|
|
525
|
+
networkVisualizationScene.canvasHeightPx -
|
|
526
|
+
networkVisualizationScene.graphTopPaddingPx -
|
|
527
|
+
networkVisualizationScene.graphBottomPaddingPx,
|
|
528
|
+
);
|
|
529
|
+
|
|
530
|
+
return {
|
|
531
|
+
drawableWidthPx,
|
|
532
|
+
drawableHeightPx,
|
|
533
|
+
};
|
|
534
|
+
}
|
|
535
|
+
|
|
536
|
+
/**
|
|
537
|
+
* Resolves a reusable topology summary for layout and sizing helpers.
|
|
538
|
+
*
|
|
539
|
+
* @param network - Network to visualize.
|
|
540
|
+
* @param inputSize - Input-layer size.
|
|
541
|
+
* @param outputSize - Output-layer size.
|
|
542
|
+
* @returns Topology summary.
|
|
543
|
+
*/
|
|
544
|
+
function resolveNetworkTopologySummary(
|
|
545
|
+
network: Network | undefined,
|
|
546
|
+
inputSize: number,
|
|
547
|
+
outputSize: number,
|
|
548
|
+
): NetworkTopologySummary {
|
|
549
|
+
// Step 1: Resolve the layer groups once so downstream helpers share the same topology view.
|
|
550
|
+
const networkLayers = resolveNetworkVisualizationLayers(
|
|
551
|
+
network,
|
|
552
|
+
inputSize,
|
|
553
|
+
outputSize,
|
|
554
|
+
);
|
|
555
|
+
|
|
556
|
+
// Step 2: Summarize the topology density values used by sizing logic.
|
|
557
|
+
return {
|
|
558
|
+
networkLayers,
|
|
559
|
+
layerCount: Math.max(1, networkLayers.length),
|
|
560
|
+
maximumLayerNodeCount: Math.max(
|
|
561
|
+
1,
|
|
562
|
+
...networkLayers.map((layerNodes) => layerNodes.length),
|
|
563
|
+
),
|
|
564
|
+
};
|
|
565
|
+
}
|
|
566
|
+
|
|
567
|
+
/**
|
|
568
|
+
* Resolves node rectangle dimensions from topology density and drawable bounds.
|
|
569
|
+
*
|
|
570
|
+
* @param network - Network to visualize.
|
|
571
|
+
* @param inputSize - Input-layer size.
|
|
572
|
+
* @param outputSize - Output-layer size.
|
|
573
|
+
* @param drawableWidthPx - Drawable graph width.
|
|
574
|
+
* @param drawableHeightPx - Drawable graph height.
|
|
575
|
+
* @returns Node dimensions.
|
|
576
|
+
*/
|
|
577
|
+
function resolveNetworkNodeDimensions(
|
|
578
|
+
network: Network | undefined,
|
|
579
|
+
inputSize: number,
|
|
580
|
+
outputSize: number,
|
|
581
|
+
drawableWidthPx: number,
|
|
582
|
+
drawableHeightPx: number,
|
|
583
|
+
): NetworkNodeDimensions {
|
|
584
|
+
// Step 1: Resolve the shared topology summary once for the sizing helpers.
|
|
585
|
+
const networkTopologySummary = resolveNetworkTopologySummary(
|
|
586
|
+
network,
|
|
587
|
+
inputSize,
|
|
588
|
+
outputSize,
|
|
589
|
+
);
|
|
590
|
+
|
|
591
|
+
// Step 2: Delegate the actual sizing rules to the topology-aware helper.
|
|
592
|
+
return resolveNetworkNodeDimensionsFromTopologySummary(
|
|
593
|
+
networkTopologySummary,
|
|
594
|
+
drawableWidthPx,
|
|
595
|
+
drawableHeightPx,
|
|
596
|
+
);
|
|
597
|
+
}
|
|
598
|
+
|
|
599
|
+
/**
|
|
600
|
+
* Resolves node rectangle dimensions from topology density and drawable bounds.
|
|
601
|
+
*
|
|
602
|
+
* @param networkTopologySummary - Topology summary.
|
|
603
|
+
* @param drawableWidthPx - Drawable graph width.
|
|
604
|
+
* @param drawableHeightPx - Drawable graph height.
|
|
605
|
+
* @returns Node dimensions.
|
|
606
|
+
*/
|
|
607
|
+
function resolveNetworkNodeDimensionsFromTopologySummary(
|
|
608
|
+
networkTopologySummary: NetworkTopologySummary,
|
|
609
|
+
drawableWidthPx: number,
|
|
610
|
+
drawableHeightPx: number,
|
|
611
|
+
): NetworkNodeDimensions {
|
|
612
|
+
// Step 1: Resolve fit constraints from the available node stack height.
|
|
613
|
+
const availableNodeStackHeightPx = Math.max(
|
|
614
|
+
FLAPPY_NETWORK_MIN_DRAWABLE_SIZE_PX,
|
|
615
|
+
drawableHeightPx - FLAPPY_NETWORK_NODE_LAYOUT_PADDING_PX * 2,
|
|
616
|
+
);
|
|
617
|
+
const strictMaximumNodeHeightByFitPx = Math.max(
|
|
618
|
+
FLAPPY_NETWORK_MIN_NODE_FIT_HEIGHT_PX,
|
|
619
|
+
availableNodeStackHeightPx / networkTopologySummary.maximumLayerNodeCount,
|
|
620
|
+
);
|
|
621
|
+
const minimumNodeHeightPx =
|
|
622
|
+
FLAPPY_NETWORK_MIN_LABEL_HEIGHT_PX +
|
|
623
|
+
FLAPPY_NETWORK_MIN_NODE_HEIGHT_LABEL_EXTRA_PX;
|
|
624
|
+
const effectiveMinimumNodeHeightPx = Math.min(
|
|
625
|
+
minimumNodeHeightPx,
|
|
626
|
+
strictMaximumNodeHeightByFitPx,
|
|
627
|
+
);
|
|
628
|
+
|
|
629
|
+
// Step 2: Resolve the final node height from density, width, and fit constraints.
|
|
630
|
+
const nodeHeightPx = Math.max(
|
|
631
|
+
effectiveMinimumNodeHeightPx,
|
|
632
|
+
Math.min(
|
|
633
|
+
FLAPPY_NETWORK_MAX_NODE_HEIGHT_PX,
|
|
634
|
+
availableNodeStackHeightPx /
|
|
635
|
+
Math.max(
|
|
636
|
+
FLAPPY_NETWORK_NODE_HEIGHT_DENSITY_MIN_DENOMINATOR,
|
|
637
|
+
networkTopologySummary.maximumLayerNodeCount *
|
|
638
|
+
FLAPPY_NETWORK_NODE_HEIGHT_DENSITY_DIVISOR,
|
|
639
|
+
),
|
|
640
|
+
drawableWidthPx /
|
|
641
|
+
Math.max(
|
|
642
|
+
FLAPPY_NETWORK_NODE_HEIGHT_LAYER_WIDTH_MIN_DENOMINATOR,
|
|
643
|
+
networkTopologySummary.layerCount *
|
|
644
|
+
FLAPPY_NETWORK_NODE_HEIGHT_LAYER_WIDTH_DIVISOR,
|
|
645
|
+
),
|
|
646
|
+
strictMaximumNodeHeightByFitPx,
|
|
647
|
+
),
|
|
648
|
+
);
|
|
649
|
+
|
|
650
|
+
// Step 3: Resolve node width from the final height and layer-width cap.
|
|
651
|
+
return {
|
|
652
|
+
widthPx: Math.max(
|
|
653
|
+
FLAPPY_NETWORK_MIN_NODE_WIDTH_PX,
|
|
654
|
+
Math.min(
|
|
655
|
+
FLAPPY_NETWORK_MAX_NODE_WIDTH_PX,
|
|
656
|
+
nodeHeightPx * FLAPPY_NETWORK_NODE_WIDTH_TO_HEIGHT_RATIO,
|
|
657
|
+
drawableWidthPx /
|
|
658
|
+
Math.max(
|
|
659
|
+
FLAPPY_NETWORK_NODE_WIDTH_LAYER_WIDTH_MIN_DENOMINATOR,
|
|
660
|
+
networkTopologySummary.layerCount *
|
|
661
|
+
FLAPPY_NETWORK_NODE_WIDTH_LAYER_WIDTH_DIVISOR,
|
|
662
|
+
),
|
|
663
|
+
),
|
|
664
|
+
),
|
|
665
|
+
heightPx: nodeHeightPx,
|
|
666
|
+
};
|
|
667
|
+
}
|
|
668
|
+
|
|
669
|
+
/**
|
|
670
|
+
* Resolves the topology-driven minimum readable height.
|
|
671
|
+
*
|
|
672
|
+
* @param networkTopologySummary - Topology summary.
|
|
673
|
+
* @returns Minimum readable height in pixels.
|
|
674
|
+
*/
|
|
675
|
+
function resolveTopologyDrivenHeightPx(
|
|
676
|
+
networkTopologySummary: NetworkTopologySummary,
|
|
677
|
+
): number {
|
|
678
|
+
// Step 1: Resolve the minimum readable node side from label and padding requirements.
|
|
679
|
+
const minimumNodeSidePx =
|
|
680
|
+
FLAPPY_NETWORK_MIN_LABEL_HEIGHT_PX +
|
|
681
|
+
FLAPPY_NETWORK_MIN_NODE_INNER_PADDING_PX * 2;
|
|
682
|
+
|
|
683
|
+
// Step 2: Stack the densest layer using the minimum node size and inter-node gaps.
|
|
684
|
+
const minimumReadableStackHeightPx =
|
|
685
|
+
networkTopologySummary.maximumLayerNodeCount <= 1
|
|
686
|
+
? minimumNodeSidePx
|
|
687
|
+
: networkTopologySummary.maximumLayerNodeCount * minimumNodeSidePx +
|
|
688
|
+
(networkTopologySummary.maximumLayerNodeCount - 1) *
|
|
689
|
+
FLAPPY_NETWORK_MIN_INTER_NODE_GAP_PX;
|
|
690
|
+
|
|
691
|
+
// Step 3: Add graph padding so the stack fits within the full visualization panel.
|
|
692
|
+
return (
|
|
693
|
+
FLAPPY_NETWORK_GRAPH_TOP_PADDING_PX +
|
|
694
|
+
FLAPPY_NETWORK_GRAPH_BOTTOM_PADDING_PX +
|
|
695
|
+
FLAPPY_NETWORK_GRAPH_INNER_PADDING_PX +
|
|
696
|
+
minimumReadableStackHeightPx
|
|
697
|
+
);
|
|
698
|
+
}
|
|
699
|
+
|
|
700
|
+
/**
|
|
701
|
+
* Resolves the recommended panel height from topology and density adjustments.
|
|
702
|
+
*
|
|
703
|
+
* @param networkTopologySummary - Topology summary.
|
|
704
|
+
* @param topologyDrivenHeightPx - Minimum readable topology height.
|
|
705
|
+
* @returns Recommended panel height.
|
|
706
|
+
*/
|
|
707
|
+
function resolveRecommendedNetworkHeightPx(
|
|
708
|
+
networkTopologySummary: NetworkTopologySummary,
|
|
709
|
+
topologyDrivenHeightPx: number,
|
|
710
|
+
): number {
|
|
711
|
+
// Step 1: Resolve density and layer-complexity adjustments beyond the baseline topology.
|
|
712
|
+
const nodeDensityHeightPx =
|
|
713
|
+
Math.max(
|
|
714
|
+
0,
|
|
715
|
+
networkTopologySummary.maximumLayerNodeCount -
|
|
716
|
+
FLAPPY_NETWORK_NODE_DENSITY_BASELINE_COUNT,
|
|
717
|
+
) * FLAPPY_NETWORK_NODE_DENSITY_HEIGHT_STEP_PX;
|
|
718
|
+
const layerComplexityHeightPx =
|
|
719
|
+
Math.max(
|
|
720
|
+
0,
|
|
721
|
+
networkTopologySummary.layerCount -
|
|
722
|
+
FLAPPY_NETWORK_LAYER_COMPLEXITY_BASELINE_COUNT,
|
|
723
|
+
) * FLAPPY_NETWORK_LAYER_COMPLEXITY_HEIGHT_STEP_PX;
|
|
724
|
+
|
|
725
|
+
// Step 2: Choose the larger of the topology minimum and baseline complexity model.
|
|
726
|
+
return Math.max(
|
|
727
|
+
Math.ceil(
|
|
728
|
+
topologyDrivenHeightPx * FLAPPY_NETWORK_TOPOLOGY_HEIGHT_MULTIPLIER,
|
|
729
|
+
),
|
|
730
|
+
FLAPPY_NETWORK_BASELINE_HEIGHT_PX +
|
|
731
|
+
nodeDensityHeightPx +
|
|
732
|
+
layerComplexityHeightPx,
|
|
733
|
+
);
|
|
734
|
+
}
|
|
735
|
+
|
|
736
|
+
/**
|
|
737
|
+
* Clamps a recommended network height into the configured panel range.
|
|
738
|
+
*
|
|
739
|
+
* @param recommendedHeightPx - Recommended panel height.
|
|
740
|
+
* @returns Clamped panel height.
|
|
741
|
+
*/
|
|
742
|
+
function clampRecommendedNetworkHeightPx(recommendedHeightPx: number): number {
|
|
743
|
+
// Step 1: Clamp the height into the configured min/max bounds and round down for canvas sizing.
|
|
744
|
+
return Math.floor(
|
|
745
|
+
clamp(
|
|
746
|
+
recommendedHeightPx,
|
|
747
|
+
FLAPPY_NETWORK_MIN_HEIGHT_PX,
|
|
748
|
+
FLAPPY_NETWORK_MAX_HEIGHT_PX,
|
|
749
|
+
),
|
|
750
|
+
);
|
|
751
|
+
}
|
|
752
|
+
|
|
753
|
+
/**
|
|
754
|
+
* Builds a node-index lookup map for resolved positioned nodes.
|
|
755
|
+
*
|
|
756
|
+
* @param centeredPositionedNodes - Positioned nodes after centering.
|
|
757
|
+
* @returns Map keyed by node index.
|
|
758
|
+
*/
|
|
759
|
+
function createPositionByNodeIndex(
|
|
760
|
+
centeredPositionedNodes: PositionedNetworkNode[],
|
|
761
|
+
): Map<number, PositionedNetworkNode> {
|
|
762
|
+
// Step 1: Materialize a lookup map so connection rendering can resolve endpoints quickly.
|
|
763
|
+
return new Map<number, PositionedNetworkNode>(
|
|
764
|
+
centeredPositionedNodes.map((positionedNode) => [
|
|
765
|
+
positionedNode.node.index,
|
|
766
|
+
positionedNode,
|
|
767
|
+
]),
|
|
768
|
+
);
|
|
769
|
+
}
|
|
770
|
+
|
|
771
|
+
/**
|
|
772
|
+
* Resolves the runtime connection array from the active network.
|
|
773
|
+
*
|
|
774
|
+
* @param network - Network to visualize.
|
|
775
|
+
* @returns Runtime connection list.
|
|
776
|
+
*/
|
|
777
|
+
function resolveRuntimeConnections(
|
|
778
|
+
network: Network | undefined,
|
|
779
|
+
): VisualNetworkConnectionLike[] {
|
|
780
|
+
// Step 1: Fall back to an empty list when no network is active.
|
|
781
|
+
return ((network?.connections ?? []) as VisualNetworkConnectionLike[]) ?? [];
|
|
782
|
+
}
|
|
783
|
+
|
|
784
|
+
/**
|
|
785
|
+
* Formats the two-line architecture label used by the header and legend.
|
|
786
|
+
*
|
|
787
|
+
* @param architectureInputSize - Input layer size.
|
|
788
|
+
* @param hiddenLayersLabel - Hidden-layer description.
|
|
789
|
+
* @param architectureOutputSize - Output layer size.
|
|
790
|
+
* @param totalNodeCount - Total node count.
|
|
791
|
+
* @param totalConnectionCount - Total connection count.
|
|
792
|
+
* @returns Formatted architecture label.
|
|
793
|
+
*/
|
|
794
|
+
function formatArchitectureLabel(
|
|
795
|
+
architectureInputSize: number,
|
|
796
|
+
hiddenLayersLabel: string,
|
|
797
|
+
architectureOutputSize: number,
|
|
798
|
+
totalNodeCount: number,
|
|
799
|
+
totalConnectionCount: number,
|
|
800
|
+
): string {
|
|
801
|
+
// Step 1: Build the compact architecture row from input, hidden, and output sizes.
|
|
802
|
+
const architectureColumnsLabel = [
|
|
803
|
+
architectureInputSize,
|
|
804
|
+
hiddenLayersLabel,
|
|
805
|
+
architectureOutputSize,
|
|
806
|
+
].join(FLAPPY_NETWORK_ARCHITECTURE_COLUMN_SEPARATOR);
|
|
807
|
+
|
|
808
|
+
// Step 2: Build the totals row and join both lines into the final label block.
|
|
809
|
+
const architectureTotalsLabel = `(${totalNodeCount} nodes, ${totalConnectionCount} connections)`;
|
|
810
|
+
return [architectureColumnsLabel, architectureTotalsLabel].join(
|
|
811
|
+
FLAPPY_NETWORK_ARCHITECTURE_LINE_SEPARATOR,
|
|
812
|
+
);
|
|
813
|
+
}
|
|
814
|
+
|
|
815
|
+
/**
|
|
816
|
+
* Resolves the hidden-layer portion of the compact architecture label.
|
|
817
|
+
*
|
|
818
|
+
* @param hiddenLayerSizes - Hidden-layer sizes.
|
|
819
|
+
* @param architectureSource - Architecture source metadata.
|
|
820
|
+
* @returns Hidden-layer label.
|
|
821
|
+
*/
|
|
822
|
+
function resolveHiddenLayersLabel(
|
|
823
|
+
hiddenLayerSizes: number[],
|
|
824
|
+
architectureSource: 'layer-metadata' | 'graph-topology' | 'inferred',
|
|
825
|
+
): string {
|
|
826
|
+
// Step 1: Use the placeholder label when the network has no hidden layers.
|
|
827
|
+
if (hiddenLayerSizes.length === 0) {
|
|
828
|
+
return FLAPPY_NETWORK_EMPTY_HIDDEN_LAYER_LABEL;
|
|
829
|
+
}
|
|
830
|
+
|
|
831
|
+
// Step 2: Prefix inferred hidden layers so the label communicates uncertainty.
|
|
832
|
+
if (architectureSource === 'inferred') {
|
|
833
|
+
return hiddenLayerSizes
|
|
834
|
+
.map(
|
|
835
|
+
(hiddenLayerSize) =>
|
|
836
|
+
`${FLAPPY_NETWORK_INFERRED_HIDDEN_LAYER_PREFIX}${hiddenLayerSize}`,
|
|
837
|
+
)
|
|
838
|
+
.join(FLAPPY_NETWORK_HIDDEN_LAYER_SEPARATOR);
|
|
839
|
+
}
|
|
840
|
+
|
|
841
|
+
// Step 3: Join explicit hidden-layer sizes without inference prefixes.
|
|
842
|
+
return hiddenLayerSizes.join(FLAPPY_NETWORK_HIDDEN_LAYER_SEPARATOR);
|
|
48
843
|
}
|