browser-entry/playback

Public playback orchestration for the Flappy Bird browser demo.

Playback is the bridge between off-thread simulation and on-screen visualization. The worker advances the world and streams packed snapshots; this layer mirrors enough state locally to animate those snapshots at browser frame cadence, render trails and backgrounds, and emit HUD telemetry.

Minimal usage sketch:

const summary = await animatePopulationEpisode(
  canvas,
  context,
  evolutionWorker,
  (stats) => updateHud(stats),
);

browser-entry/playback/playback.ts

animatePopulationEpisode

animatePopulationEpisode(
  canvas: HTMLCanvasElement,
  context: CanvasRenderingContext2D,
  evolutionWorker: Worker,
  onFrameStats: (stats: PlaybackFrameStats) => void,
  onChampionChanged: ((event: PlaybackChampionChangedEvent) => void) | undefined,
): Promise<PlaybackEpisodeSummary>

Public playback entry point used by browser runtime orchestration.

Conceptually, this answers: "play one worker-produced episode on the canvas until it is done, and tell me what happened along the way".

Parameters:

Returns: Aggregate playback summary for the current episode.

Example:

const summary = await animatePopulationEpisode(
  canvas,
  context,
  evolutionWorker,
  (stats) => updateHud(stats),
);

animatePopulationEpisodeInternal

animatePopulationEpisodeInternal(
  canvas: HTMLCanvasElement,
  context: CanvasRenderingContext2D,
  evolutionWorker: Worker,
  onFrameStats: (stats: PlaybackFrameStats) => void,
  onChampionChanged: ((event: PlaybackChampionChangedEvent) => void) | undefined,
): Promise<PlaybackEpisodeSummary>

Internal playback orchestration entry retained for compatibility re-exports.

The implementation is shared with the public entry so legacy imports and the newer folderized surface behave identically.

Parameters:

Returns: Aggregate playback summary for the current episode.

PlaybackEpisodeSummary

Public aggregate playback summary returned after one episode completes.

The summary captures the headline outcomes of the just-finished population run without exposing all internal frame-by-frame details.

browser-entry/playback/playback.orchestration.types.ts

Playback orchestration contracts for the Flappy Bird browser demo.

These types describe the moving pieces of one playback episode: the public summary returned at the end, the mutable loop bookkeeping used while frames are streaming, and the session context mirrored locally in the browser.

PlaybackChampionChangedEvent

Event emitted when the current playback champion changes.

The event identifies which playback bird is currently highlighted as the red bird so the side-panel network view can stay synchronized with the renderer.

PlaybackEpisodeSummary

Public aggregate playback summary returned after one episode completes.

The summary captures the headline outcomes of the just-finished population run without exposing all internal frame-by-frame details.

PlaybackIterationContext

Shared dependencies and mutable state used by one playback iteration.

Grouping these fields into one context object keeps the iteration services declarative and avoids long parameter lists across the playback loop.

PlaybackLoopState

Mutable loop bookkeeping shared across playback iterations.

This is the browser-side state machine for the playback loop: how much simulation budget is being requested, whether the episode has finished, and what aggregate summary has been observed so far.

PlaybackMutableSummary

Mutable playback summary extended with latest leader telemetry fallbacks.

During playback the browser may need temporary "latest known" values before the worker emits final aggregate statistics, so the mutable form carries both final fields and rolling fallbacks.

PlaybackSessionContext

Shared mutable playback state mirrored locally while worker playback runs.

The worker remains the source of truth for simulation, but the browser keeps lightweight mirrored state for rendering, trail accumulation, and loop orchestration.

browser-entry/playback/playback.session.services.ts

Session initialization and summary-folding helpers for playback.

These services answer three orchestration questions:

  1. What viewport is the browser currently showing?
  2. What local mirror state should exist before the first worker snapshot?
  3. How should mutable loop state be folded back into a public summary?

createInitialPlaybackLoopState

createInitialPlaybackLoopState(): PlaybackLoopState

Creates the mutable loop state used while processing playback steps.

This is the browser's running notebook for one episode: budget, completion flag, and the latest known aggregate outcome metrics.

Returns: Initialized loop state and aggregate summary values.

createInitialRenderState

createInitialRenderState(
  viewportDimensions: { visibleWorldWidthPx: number; visibleWorldHeightPx: number; },
): PopulationRenderState

Creates the initial render state used before the first worker snapshot.

The browser starts from an empty-but-shaped render state so rendering helpers can assume the object graph exists even before the worker has emitted any population geometry.

Parameters:

Returns: Initialized population render state.

createInitialTrailState

createInitialTrailState(): TrailState

Creates the initial trail state used before any snapshots have been applied.

Trails are purely visual history, so they begin empty and accumulate only as playback frames are observed.

Returns: Empty trail state for all birds.

initializePlaybackSessionContext

initializePlaybackSessionContext(
  canvas: HTMLCanvasElement,
  evolutionWorker: Worker,
): PlaybackSessionContext

Initializes worker playback and local state mirrors for one episode.

This is the point where the browser and worker agree on a fresh episode. The browser sends the initial viewport dimensions to the worker, then builds the local render and summary mirrors that will be updated as snapshots arrive.

Parameters:

Returns: Session context shared across the playback loop.

resolvePlaybackEpisodeSummary

resolvePlaybackEpisodeSummary(
  summary: PlaybackMutableSummary,
): PlaybackEpisodeSummary

Folds the mutable loop summary into the public playback summary shape.

The public summary is intentionally smaller than the internal loop state. It exposes the outcome, not the browser's intermediate bookkeeping.

Parameters:

Returns: Public playback episode summary.

resolvePlaybackViewportDimensions

resolvePlaybackViewportDimensions(
  canvas: HTMLCanvasElement,
): { visibleWorldWidthPx: number; visibleWorldHeightPx: number; }

Resolves the current visible playback viewport dimensions from the canvas.

Playback sizing is derived from the live canvas rather than a hard-coded constant so resizing can flow into the worker/session boundary cleanly.

Parameters:

Returns: Visible world width and height in pixels.

syncPlaybackViewportDimensions

syncPlaybackViewportDimensions(
  canvas: HTMLCanvasElement,
  renderState: PopulationRenderState,
): void

Synchronizes the render state viewport fields with the current canvas size.

Playback can continue while the canvas size changes, so the browser refreshes its local viewport mirror rather than assuming dimensions stay fixed.

Parameters:

Returns: Nothing.

browser-entry/playback/playback.loop.service.ts

Browser frame-pacing helpers for playback animation.

The playback loop advances worker simulation in batches but still presents frames at browser animation cadence. This module isolates the requestAnimationFrame dependency so playback orchestration can read more clearly and fail with a targeted error when RAF is unavailable.

nextAnimationFrame

nextAnimationFrame(): Promise<void>

Yields until the next browser animation frame.

In browser rendering terms, this is the pacing boundary between simulation work and visible painting.

Returns: Promise resolved on next animation frame.

browser-entry/playback/playback.iteration.services.ts

applyPlaybackStepSnapshot

applyPlaybackStepSnapshot(
  sessionContext: PlaybackSessionContext,
  snapshot: EvolutionPlaybackStepSnapshot,
): void

Applies the latest worker snapshot to render state and trail caches.

Parameters:

Returns: Nothing.

emitChampionChangedEvent

emitChampionChangedEvent(
  iterationContext: PlaybackIterationContext,
): void

Emits a champion-changed event when the red-bird champion changes.

The detector compares the newly resolved champion bird index against the previously displayed champion index. This keeps the side panel aligned with the red bird even when leadership changes because the old champion dies.

Parameters:

Returns: Nothing.

emitPlaybackChampionChanged

emitPlaybackChampionChanged(
  onChampionChanged: ((event: PlaybackChampionChangedEvent) => void) | undefined,
  championBirdIndex: number,
): void

Calls the optional playback champion-changed callback with a structured payload.

Parameters:

Returns: Nothing.

emitPlaybackFrameStats

emitPlaybackFrameStats(
  iterationContext: PlaybackIterationContext,
  playbackStepPayload: { requestId: number; snapshot: EvolutionPlaybackStepSnapshot; instrumentation?: { activationCallsPerFrame: number; simulationStepsPerRaf: number; } | undefined; done: boolean; averagePipesPassed?: number | undefined; p90FramesSurvived?: number | undefined; winnerPipesPassed?: number | undefined; winnerFramesSurvived?: number | undefined; },
): void

Resolves leader telemetry and emits the public frame-stats callback.

Parameters:

Returns: Nothing.

requestPlaybackStepPayload

requestPlaybackStepPayload(
  iterationContext: PlaybackIterationContext,
): Promise<{ requestId: number; snapshot: EvolutionPlaybackStepSnapshot; instrumentation?: { activationCallsPerFrame: number; simulationStepsPerRaf: number; } | undefined; done: boolean; averagePipesPassed?: number | undefined; p90FramesSurvived?: number | undefined; winnerPipesPassed?: number | undefined; winnerFramesSurvived?: number | undefined; }>

Requests one playback step batch from the evolution worker.

Parameters:

Returns: Worker playback step payload for the current iteration.

runPlaybackIteration

runPlaybackIteration(
  iterationContext: PlaybackIterationContext,
): Promise<void>

Executes one playback iteration from viewport sync through render pacing.

Parameters:

Returns: Nothing.

runPlaybackLoop

runPlaybackLoop(
  iterationContext: PlaybackIterationContext,
): Promise<void>

Runs playback iterations until the worker reports that the episode is done.

Parameters:

Returns: Nothing.

updatePlaybackLoopCompletion

updatePlaybackLoopCompletion(
  loopState: PlaybackLoopState,
  playbackStepPayload: { requestId: number; snapshot: EvolutionPlaybackStepSnapshot; instrumentation?: { activationCallsPerFrame: number; simulationStepsPerRaf: number; } | undefined; done: boolean; averagePipesPassed?: number | undefined; p90FramesSurvived?: number | undefined; winnerPipesPassed?: number | undefined; winnerFramesSurvived?: number | undefined; },
): void

Updates the loop summary when the worker reports playback completion.

Parameters:

Returns: Nothing.

browser-entry/playback/playback.frame-render.service.ts

Compatibility facade for playback frame rendering.

Older imports still reach the frame renderer through this file while the implementation now lives in the dedicated frame-render folder.

renderPopulationFrame

renderPopulationFrame(
  context: CanvasRenderingContext2D,
  renderState: PopulationRenderState,
  trailState: TrailState,
): void

Draws one simulation frame for the current population state.

The render order matters: background first, then pipes, then birds, then trails and overlays that should visually sit on top.

Parameters:

Returns: Nothing.

Example:

renderPopulationFrame(context, renderState, trailState);

updateTrailState

updateTrailState(
  trailState: TrailState,
  renderState: PopulationRenderState,
): void

Updates the trail cache from the latest frame snapshot.

The renderer intentionally keeps only a short champion trail instead of full history for every bird, which keeps the visual emphasis clear and the per-frame work small.

Parameters:

Returns: Nothing.

Example:

updateTrailState(trailState, renderState);

browser-entry/playback/playback.render.service.ts

drawPipeNeonOutline

drawPipeNeonOutline(
  context: CanvasRenderingContext2D,
  rectangleLeftPx: number,
  rectangleTopPx: number,
  rectangleWidthPx: number,
  rectangleHeightPx: number,
): void

Draws a simplified neon outline around a pipe rectangle.

Parameters:

Returns: Nothing.

browser-entry/playback/playback.render.utils.ts

PlaybackBirdRenderStyle

Pure render-style result for one bird body draw pass.

resolveBirdRenderStyle

resolveBirdRenderStyle(
  birdIndex: number,
  championBirdIndex: number,
): PlaybackBirdRenderStyle

Resolves opacity, body color, and champion marker for one bird.

Parameters:

Returns: Pure style payload used by the render service.

resolveChampionBirdIndex

resolveChampionBirdIndex(
  renderState: PopulationRenderState,
): number

Resolves the champion bird index for the current render frame.

Champion selection first prefers the primary winner resolver and then falls back to the first alive bird when no winner index is available.

Parameters:

Returns: Champion index or -1 when no bird is alive.

browser-entry/playback/playback.trail.utils.ts

clamp01

clamp01(
  value: number,
): number

Clamps a number to the inclusive [0, 1] range.

The trail renderer combines several normalized fade factors, so keeping this utility local to the module makes the intent obvious: every opacity channel must remain safe for direct canvas alpha use.

Parameters:

Returns: Clamped value.

pushChampionTrailPoint

pushChampionTrailPoint(
  trailPoints: TrailPoint[],
  frameIndex: number,
  yPosition: number,
): void

Appends one point to the champion-only short trail history.

The browser highlights the current leader with a shorter, denser trail than the rest of the flock. Using a dedicated helper keeps that policy explicit in the call site instead of scattering champion-specific retention numbers through the playback renderer.

Parameters:

Returns: Nothing.

pushTrailPoint

pushTrailPoint(
  trailPoints: TrailPoint[],
  frameIndex: number,
  yPosition: number,
  maxRetainedPoints: number,
): void

Appends one trail point while enforcing the maximum retained history length.

Playback trails are intentionally modeled as short rolling histories rather than unbounded path logs. That keeps the neon afterimage readable, prevents old turns from dominating the current frame, and avoids per-frame growth in a long-running browser session.

Parameters:

Returns: Nothing.

Example:

const trailPoints = [{ frameIndex: 10, yPx: 140 }];
pushTrailPoint(trailPoints, 11, 136, 2);

resolveEdgeOpacityFactor

resolveEdgeOpacityFactor(
  pointXPx: number,
  pointYPx: number,
  edgeBounds: PlaybackEdgeBounds,
): number

Converts distance-to-edge into a normalized opacity factor.

Trail points fade as they approach the viewport border so the rendered path feels cropped by the camera instead of abruptly chopped off. This mirrors the common animation principle of easing visual intensity near a frame boundary.

Returns 0 exactly on or beyond an edge and rises to 1 once distance exceeds the configured fade band.

Parameters:

Returns: Opacity multiplier in [0, 1].

Example:

const edgeOpacity = resolveEdgeOpacityFactor(120, 140, edgeBounds);
const ageOpacity = resolveTrailLifetimeOpacityFactor(3, 12);
const alpha = edgeOpacity * ageOpacity;

resolveTrailLifetimeOpacityFactor

resolveTrailLifetimeOpacityFactor(
  frameOffset: number,
  maxTrailFrameOffset: number,
): number

Converts trail age into a normalized opacity factor.

This helper implements the other half of the afterimage effect: recent trail samples should read as energetic and bright, while older samples should fade away smoothly so the viewer's eye stays anchored to the current flock motion.

Oldest retained history approaches 0 opacity; newest approaches 1.

Parameters:

Returns: Opacity multiplier in [0, 1].

browser-entry/playback/playback.constants.ts

cachedStarfieldTilesByHeight

Shared in-memory cache for pre-rendered parallax starfield tiles.

This cache is keyed by world height to avoid re-rendering identical offscreen tile strips across playback frames.

browser-entry/playback/playback.errors.ts

Error message emitted when playback requires RAF but it is unavailable.

PLAYBACK_ANIMATION_FRAME_UNAVAILABLE_ERROR_MESSAGE

Error message emitted when playback requires RAF but it is unavailable.

PlaybackAnimationFrameUnavailableError

Error thrown when a playback frame wait is requested without RAF support.

browser-entry/playback/playback.types.ts

Shared playback utility types for the browser-entry subsystem.

These types support rendering concerns that cut across multiple playback helpers, such as edge-aware trail fading and cached parallax backgrounds.

PlaybackEdgeBounds

Axis-aligned visible world bounds used for edge-aware trail fading.

Trail rendering needs a quick answer to "is this point still visually inside the active world rectangle?" so fading logic can taper paths near the edges instead of drawing abrupt cutoffs.

PlaybackStarfieldLayerSpec

Declarative recipe for building one cached starfield parallax layer.

Each layer spec describes how dense, bright, blurred, and fast one visual depth plane should feel.

StarTile

Shared type contract for starfield tile rendering layers.

A tile is pre-rendered and repeated horizontally to draw efficient parallax backgrounds during playback.

Separating the image type from the tile record lets the same starfield logic work with ordinary canvases and OffscreenCanvas when available.

browser-entry/playback/playback.starfield.types.ts

Starfield and parallax rendering contracts for playback backgrounds.

The playback view uses a cached layered starfield to add depth without paying a large per-frame rendering cost. These types define the tile, layer, and deterministic placement data needed for that effect.

CreateStarTileCanvasOptions

Input contract for pre-rendering one deterministic starfield tile.

The generated tile is cached and repeated horizontally during playback, so every field here affects both the visual look and the parallax cost.

PlaybackStarfieldLayerSpec

Declarative recipe for building one cached starfield parallax layer.

Each layer spec describes how dense, bright, blurred, and fast one visual depth plane should feel.

StarfieldCanvasDimensions

Normalized canvas dimensions used by browser and offscreen tile creation.

The creation path works with both HTMLCanvasElement and OffscreenCanvas, so dimensions are stored in a narrow shared shape rather than tied to one DOM type.

StarPlacement

Deterministic placement and appearance for one rendered star sprite.

Determinism matters here because cached starfield tiles should remain stable across redraws instead of sparkling randomly every frame.

StarTile

Shared type contract for starfield tile rendering layers.

A tile is pre-rendered and repeated horizontally to draw efficient parallax backgrounds during playback.

Separating the image type from the tile record lets the same starfield logic work with ordinary canvases and OffscreenCanvas when available.

StarTileImage

Shared type contract for starfield tile rendering layers.

A tile is pre-rendered and repeated horizontally to draw efficient parallax backgrounds during playback.

browser-entry/playback/playback.starfield.service.ts

resolveStarfieldTiles

resolveStarfieldTiles(
  visibleWorldHeightPx: number,
): readonly StarTile[]

Resolves (and lazily creates) cached starfield tile layers for the viewport.

Parameters:

Returns: Ordered far/mid/near starfield tiles.

browser-entry/playback/playback.starfield.services.ts

createCanvasSizeFallback

createCanvasSizeFallback(
  canvasDimensions: StarfieldCanvasDimensions,
): HTMLCanvasElement

Creates a size-only fallback so non-browser tests can skip rendering safely.

Parameters:

Returns: Minimal canvas-shaped object cast to the compatible return type.

createCompatibleCanvas

createCompatibleCanvas(
  widthPx: number,
  heightPx: number,
): HTMLCanvasElement | OffscreenCanvas

Creates a browser-compatible canvas with clamped integer dimensions.

Parameters:

Returns: Offscreen canvas when supported, otherwise a DOM canvas fallback.

createDocumentCanvasIfSupported

createDocumentCanvasIfSupported(
  canvasDimensions: StarfieldCanvasDimensions,
): HTMLCanvasElement | null

Creates a DOM canvas when document APIs are available.

Parameters:

Returns: DOM canvas instance or null when unavailable.

createOffscreenCanvasIfSupported

createOffscreenCanvasIfSupported(
  canvasDimensions: StarfieldCanvasDimensions,
): OffscreenCanvas | null

Creates an offscreen canvas when the current runtime supports it.

Parameters:

Returns: Offscreen canvas instance or null when unavailable.

createStarTileCanvas

createStarTileCanvas(
  options: CreateStarTileCanvasOptions,
): StarTileImage

Pre-renders a deterministic tile that can be reused across animation frames.

Parameters:

Returns: Canvas image source containing the rendered star strip.

initializeStarTileContext

initializeStarTileContext(
  options: { tileContext: CanvasRenderingContext2D | OffscreenCanvasRenderingContext2D; canvas: HTMLCanvasElement | OffscreenCanvas; },
): void

Clears the canvas and applies the neutral settings shared by all rendered stars.

Parameters:

Returns: Nothing. The provided context is mutated in place.

normalizeCanvasDimensions

normalizeCanvasDimensions(
  widthPx: number,
  heightPx: number,
): StarfieldCanvasDimensions

Normalizes requested canvas dimensions into positive integer pixel sizes.

Parameters:

Returns: Clamped integer dimensions safe for canvas allocation.

renderSeededStars

renderSeededStars(
  options: { tileContext: CanvasRenderingContext2D | OffscreenCanvasRenderingContext2D; seededRandom: () => number; canvasOptions: CreateStarTileCanvasOptions; },
): void

Draws all stars for one tile using a seeded random source.

Parameters:

Returns: Nothing. The provided context is mutated in place.

resetStarTileContext

resetStarTileContext(
  tileContext: CanvasRenderingContext2D | OffscreenCanvasRenderingContext2D,
): void

Restores neutral drawing state so later canvas consumers start from defaults.

Parameters:

Returns: Nothing. The provided context is mutated in place.

resolveStarPlacement

resolveStarPlacement(
  options: { seededRandom: () => number; tileWidthPx: number; tileHeightPx: number; minSizePx: number; maxSizePx: number; minAlpha: number; maxAlpha: number; },
): StarPlacement

Resolves one deterministic star placement and appearance from the seeded RNG.

Parameters:

Returns: Pixel location, square size, and alpha for one rendered star.

resolveStarTileContext

resolveStarTileContext(
  canvas: HTMLCanvasElement | OffscreenCanvas,
): CanvasRenderingContext2D | OffscreenCanvasRenderingContext2D | null

Resolves the rendering context used for star tile pre-rendering.

Parameters:

Returns: A 2D drawing context when rendering is supported.

browser-entry/playback/playback.starfield.layer.services.ts

createStarTile

createStarTile(
  layerSpec: PlaybackStarfieldLayerSpec,
  tileHeightPx: number,
): StarTile

Creates one cached tile layer from a declarative layer specification.

Parameters:

Returns: Cached tile metadata for parallax drawing.

browser-entry/playback/playback.render.pipe-outline.service.ts

drawPipeNeonOutline

drawPipeNeonOutline(
  context: CanvasRenderingContext2D,
  rectangleLeftPx: number,
  rectangleTopPx: number,
  rectangleWidthPx: number,
  rectangleHeightPx: number,
): void

Draws a simplified neon outline around a pipe rectangle.

Parameters:

Returns: Nothing.

resolveAlignedPipeOutlineRectangle

resolveAlignedPipeOutlineRectangle(
  input: { rectangleLeftPx: number; rectangleTopPx: number; rectangleWidthPx: number; rectangleHeightPx: number; },
): { alignedLeftPx: number; alignedTopPx: number; alignedWidthPx: number; alignedHeightPx: number; }

Resolves a pixel-aligned rectangle used by the pipe outline renderer.

Parameters:

Returns: Aligned rectangle ready for outline rendering.

resolvePipeOutlinePath

resolvePipeOutlinePath(
  alignedRectangle: { alignedLeftPx: number; alignedTopPx: number; alignedWidthPx: number; alignedHeightPx: number; },
): Path2D

Resolves the reusable outline path for one pipe body and its entrance rim.

Parameters:

Returns: Path containing the outer pipe outline and optional entrance rim.

browser-entry/playback/playback.snapshot.utils.ts

Compatibility facade for playback snapshot helpers.

Legacy imports still reach snapshot synchronization through this file while the implementation now lives in the dedicated snapshot folder.

applyPlaybackSnapshot

applyPlaybackSnapshot(
  renderState: PopulationRenderState,
  snapshot: EvolutionPlaybackStepSnapshot,
): void

Applies worker snapshot data to the mutable playback render state.

This is the top-level hydration step for one frame: copy scalar frame fields, then synchronize packed pipe and bird arrays into reusable browser-side objects.

Parameters:

Returns: Nothing.

resolveLeaderFramesSurvived

resolveLeaderFramesSurvived(
  renderState: PopulationRenderState,
): number

Resolves the maximum survived-frame count in the current render state.

This is the "leader frames survived" view of the current frame: the best raw frame count among all birds currently represented in the render state.

Parameters:

Returns: Maximum frames survived by any bird.

browser-entry/playback/playback.starfield.utils.ts

createSeededRandom

createSeededRandom(
  seed: number,
): () => number

Creates a deterministic pseudo-random generator for starfield tile layouts.

Parameters:

Returns: Function that yields values in the range [0, 1).

positiveModulo

positiveModulo(
  value: number,
  modulo: number,
): number

Resolves positive modulo suitable for horizontal tiling offsets.

Parameters:

Returns: Wrapped value in [0, modulo).

browser-entry/playback/playback.worker-channel.utils.ts

PlaybackStepPayload

Shared alias for the worker playback-step payload.

This keeps the playback worker-channel modules focused on playback semantics instead of long imported protocol names.

PlaybackStepRequest

Request payload for one playback-step worker call.

The browser asks the worker to advance simulation by a small batch of steps and to package the result for the current viewport dimensions.

resolvePlaybackCompletionSummary

resolvePlaybackCompletionSummary(
  playbackStepPayload: { requestId: number; snapshot: EvolutionPlaybackStepSnapshot; instrumentation?: { activationCallsPerFrame: number; simulationStepsPerRaf: number; } | undefined; done: boolean; averagePipesPassed?: number | undefined; p90FramesSurvived?: number | undefined; winnerPipesPassed?: number | undefined; winnerFramesSurvived?: number | undefined; },
  latestLeaderPipesPassed: number,
  latestLeaderFramesSurvived: number,
): { averagePipesPassed: number; p90FramesSurvived: number; winnerPipesPassed: number; winnerFramesSurvived: number; }

Resolves final playback summary values when the worker reports completion.

Some end-of-episode aggregates may be omitted from the worker payload, so the browser falls back to the latest leader values it has already observed during playback.

Parameters:

Returns: Final aggregate playback summary.

resolvePlaybackFrameStats

resolvePlaybackFrameStats(
  playbackStepPayload: { requestId: number; snapshot: EvolutionPlaybackStepSnapshot; instrumentation?: { activationCallsPerFrame: number; simulationStepsPerRaf: number; } | undefined; done: boolean; averagePipesPassed?: number | undefined; p90FramesSurvived?: number | undefined; winnerPipesPassed?: number | undefined; winnerFramesSurvived?: number | undefined; },
  frameIndex: number,
  activeBirdCount: number,
  leaderPipesPassed: number,
  leaderFramesSurvived: number,
): PlaybackFrameStats

Resolves HUD playback frame stats from worker payload and leader metrics.

The frame-stats payload combines browser-derived leader information with any instrumentation values provided by the worker.

Parameters:

Returns: Normalized per-frame HUD telemetry payload.

resolvePlaybackStepRequest

resolvePlaybackStepRequest(
  input: ResolvePlaybackStepRequestInput,
): ResolvePlaybackStepRequestResult

Resolves step count and request payload for the next worker playback batch.

This is the pacing bridge between browser rendering and worker simulation. Rather than sending a fixed step count every frame, the loop carries forward fractional remainder so long-term playback speed stays closer to the intended emulation rate.

Parameters:

Returns: Request payload plus carried-over fractional frame budget.

ResolvePlaybackStepRequestInput

Input used to resolve the next playback-step request and budget remainder.

Playback uses a fractional frame budget so browser render cadence and worker simulation cadence can be smoothed together over time.

ResolvePlaybackStepRequestResult

Output for the resolved playback-step request and frame-budget remainder.

The resolved request records both the integer step batch to send now and the leftover fractional budget to carry into the next render tick.

Generated from source JSDoc • GitHub