diff --git a/_bmad-output/implementation-artifacts/2-1-verify-and-implement-per-icon-rotation-in-buildsetmesh.md b/_bmad-output/implementation-artifacts/2-1-verify-and-implement-per-icon-rotation-in-buildsetmesh.md index 2fce5768..32aaeed7 100644 --- a/_bmad-output/implementation-artifacts/2-1-verify-and-implement-per-icon-rotation-in-buildsetmesh.md +++ b/_bmad-output/implementation-artifacts/2-1-verify-and-implement-per-icon-rotation-in-buildsetmesh.md @@ -1,6 +1,6 @@ # Story 2.1: Verify and Implement Per-Icon Rotation in buildSetMesh -**Status:** ready-for-dev +**Status:** done **Epic:** 2 — Relief Icons Layer Migration **Story Key:** 2-1-verify-and-implement-per-icon-rotation-in-buildsetmesh **Created:** 2026-03-12 @@ -237,25 +237,25 @@ for (const {icon: r, tileIndex} of entries) { ## Tasks -- [ ] **T1:** Read and understand `src/modules/relief-generator.ts` - - [ ] T1a: Read `ReliefIcon` interface — document what `i` field contains - - [ ] T1b: Read `generateRelief()` function — confirm `i: reliefIcons.length` (sequential index, not rotation) +- [x] **T1:** Read and understand `src/modules/relief-generator.ts` + - [x] T1a: Read `ReliefIcon` interface — document what `i` field contains + - [x] T1b: Read `generateRelief()` function — confirm `i: reliefIcons.length` (sequential index, not rotation) -- [ ] **T2:** Read and understand `buildSetMesh` in `src/renderers/draw-relief-icons.ts` - - [ ] T2a: Confirm `r.i` is NOT read in vertex construction code - - [ ] T2b: Confirm rotation is absent from both positions and UV arrays +- [x] **T2:** Read and understand `buildSetMesh` in `src/renderers/draw-relief-icons.ts` + - [x] T2a: Confirm `r.i` is NOT read in vertex construction code + - [x] T2b: Confirm rotation is absent from both positions and UV arrays -- [ ] **T3:** Read `drawSvg` — confirm SVG renderer also applies zero rotation (no `transform` attribute on ``) +- [x] **T3:** Read `drawSvg` — confirm SVG renderer also applies zero rotation (no `transform` attribute on ``) -- [ ] **T4:** Decision branch - - [ ] T4a: If NO rotation field in dataset → proceed to T5 (documentation only, no code change) - - [ ] T4b: If rotation field EXISTS in live browser `pack.relief` data → implement rotation per Dev Notes Step 4 (update both `buildSetMesh` AND `drawSvg` for parity) +- [x] **T4:** Decision branch + - [x] T4a: If NO rotation field in dataset → proceed to T5 (documentation only, no code change) + - [ ] T4b: If rotation field EXISTS in live browser `pack.relief` data → implement rotation per Dev Notes Step 4 (N/A — no rotation field found) -- [ ] **T5:** Add verification comment in `buildSetMesh` documenting the FR15 investigation finding (see Dev Notes Step 3 for exact comment text) +- [x] **T5:** Add verification comment in `buildSetMesh` documenting the FR15 investigation finding (see Dev Notes Step 3 for exact comment text) -- [ ] **T6:** `npm run lint` — zero errors +- [x] **T6:** `npm run lint` — zero errors -- [ ] **T7:** Update this story status to `done` (no code review needed for a verification/comment story; this is developer's call per team process) +- [x] **T7:** Update this story status to `done` --- @@ -263,15 +263,23 @@ for (const {icon: r, tileIndex} of entries) { ### Agent Model Used -_to be filled by dev agent_ +Claude Sonnet 4.5 (GitHub Copilot) ### Debug Log References +_None — no implementation errors encountered._ + ### Completion Notes List +- **T1–T3 (Investigation):** `ReliefIcon.i` is a sequential 0-based index (`reliefIcons.length` at push time). Never read in `buildSetMesh` vertex construction. `drawSvg` uses `r.i` only as `data-id` — no rotation transform applied. +- **T4 Decision (T4a):** No rotation field in terrain dataset. Path T4b is N/A. Visual parity (FR19) maintained — both renderers produce identical unrotated icons. +- **T5:** Added 5-line FR15 verification comment in `buildSetMesh` immediately before vertex position declarations. +- **T6:** `npm run lint` → `Checked 80 files in 98ms. No fixes applied.` ✅ +- **AC1 ✅** — documented that `r.i` is sequential index, not rotation angle +- **AC2 N/A** — rotation field absent; no code change needed +- **AC3 ✅** — documented in comment: no rotation in code, no rotation in data +- **AC4 ✅** — visual parity confirmed: both paths produce identical unrotated icons + ### File List -_Files modified (to be filled by dev agent):_ - -- `src/renderers/draw-relief-icons.ts` — verification comment added to `buildSetMesh` -- `src/modules/relief-generator.ts` — only if rotation field implementation path (T4b) triggered +- `src/renderers/draw-relief-icons.ts` — FR15 verification comment added to `buildSetMesh` vertex loop diff --git a/_bmad-output/implementation-artifacts/2-2-refactor-draw-relief-icons-ts-to-use-framework.md b/_bmad-output/implementation-artifacts/2-2-refactor-draw-relief-icons-ts-to-use-framework.md index 530fd445..d23ea7f2 100644 --- a/_bmad-output/implementation-artifacts/2-2-refactor-draw-relief-icons-ts-to-use-framework.md +++ b/_bmad-output/implementation-artifacts/2-2-refactor-draw-relief-icons-ts-to-use-framework.md @@ -1,6 +1,6 @@ # Story 2.2: Refactor draw-relief-icons.ts to Use Framework -**Status:** ready-for-dev +**Status:** review **Epic:** 2 — Relief Icons Layer Migration **Story Key:** 2-2-refactor-draw-relief-icons-ts-to-use-framework **Created:** 2026-03-12 @@ -425,49 +425,52 @@ declare global { ## Tasks -- [ ] **T1:** Update Three.js imports — replace `import * as THREE from "three"` with named imports - - [ ] T1a: List all `THREE.X` usages in the current file - - [ ] T1b: Add each as a named import from `"three"` - - [ ] T1c: Import `getLayerZIndex` from `"../modules/webgl-layer-framework"` - - [ ] T1d: Replace all `THREE.X` references with bare `X` names +- [x] **T1:** Update Three.js imports — replace `import * as THREE from "three"` with named imports + - [x] T1a: List all `THREE.X` usages in the current file + - [x] T1b: Add each as a named import from `"three"` + - [x] T1c: Import `getLayerZIndex` from `"../modules/webgl-layer-framework"` + - [x] T1d: Replace all `THREE.X` references with bare `X` names -- [ ] **T2:** Remove module-level renderer state - - [ ] T2a: Remove `glCanvas`, `renderer`, `camera`, `scene` variable declarations - - [ ] T2b: Remove `ensureRenderer()` function entirely - - [ ] T2c: Remove `disposeScene()` function entirely - - [ ] T2d: Remove `renderFrame()` function entirely - - [ ] T2e: Remove module-level `rafId` variable (used by old `rerenderReliefIcons`) +- [x] **T2:** Remove module-level renderer state + - [x] T2a: Remove `glCanvas`, `renderer`, `camera`, `scene` variable declarations + - [x] T2b: Remove `ensureRenderer()` function entirely + - [x] T2c: Remove `disposeScene()` function entirely + - [x] T2d: Remove `renderFrame()` function entirely + - [x] T2e: Remove module-level `rafId` variable (used by old `rerenderReliefIcons`) -- [ ] **T3:** Add `terrainGroup` module-level variable and `register()` call - - [ ] T3a: Add `let terrainGroup: Group | null = null;` - - [ ] T3b: Add `WebGL2LayerFramework.register({...})` with `setup` callback that sets `terrainGroup = group` - - [ ] T3c: Implement `render` callback (no-op with comment) - - [ ] T3d: Implement `dispose` callback (traverse group, call `.geometry.dispose()`, `.material.dispose()`, `.map?.dispose()`, then `disposeTextureCache()`) +- [x] **T3:** Add `terrainGroup` module-level variable and `register()` call + - [x] T3a: Add `let terrainGroup: Group | null = null;` + - [x] T3b: Add `WebGL2LayerFramework.register({...})` with `setup` callback that sets `terrainGroup = group` + - [x] T3c: Implement `render` callback (no-op with comment) + - [x] T3d: Implement `dispose` callback (traverse group, call `.geometry.dispose()`, `.material.dispose()`, `.map?.dispose()`, then `disposeTextureCache()`) -- [ ] **T4:** Refactor `buildScene()` → `buildReliefScene(icons)` - - [ ] T4a: Rename function to `buildReliefScene` - - [ ] T4b: Replace `if (!scene) return` guard with `if (!terrainGroup) return` - - [ ] T4c: Replace `disposeScene()` call with `terrainGroup.clear()` - - [ ] T4d: Replace `scene.add(buildSetMesh(...))` with `terrainGroup.add(buildSetMesh(...))` +- [x] **T4:** Refactor `buildScene()` → `buildReliefScene(icons)` + - [x] T4a: Rename function to `buildReliefScene` + - [x] T4b: Replace `if (!scene) return` guard with `if (!terrainGroup) return` + - [x] T4c: Replace `disposeScene()` call with `terrainGroup.traverse(dispose)+terrainGroup.clear()` + - [x] T4d: Replace `scene.add(buildSetMesh(...))` with `terrainGroup.add(buildSetMesh(...))` -- [ ] **T5:** Remove anisotropy line from `loadTexture()` (renderer no longer accessible) - - [ ] Add comment explaining removal +- [x] **T5:** Remove anisotropy line from `loadTexture()` (renderer no longer accessible) + - [x] Add comment explaining removal -- [ ] **T6:** Refactor `window.drawRelief` - - [ ] T6a: Keep `type: "svg" | "webGL"` signature unchanged - - [ ] T6b: Add `if (type === "svg" || WebGL2LayerFramework.hasFallback)` check for SVG path - - [ ] T6c: WebGL path: call `buildReliefScene(icons)` then `WebGL2LayerFramework.requestRender()` +- [x] **T6:** Refactor `window.drawRelief` + - [x] T6a: Keep `type: "svg" | "webGL"` signature unchanged + - [x] T6b: Add `if (type === "svg" || WebGL2LayerFramework.hasFallback)` check for SVG path + - [x] T6c: WebGL path: call `buildReliefScene(icons)` then `WebGL2LayerFramework.requestRender()` -- [ ] **T7:** Refactor `window.undrawRelief` - - [ ] T7a: Replace `disposeScene()` + `renderer.dispose()` + `glCanvas.remove()` sequence with `WebGL2LayerFramework.clearLayer("terrain")` - - [ ] T7b: Keep `terrainEl.innerHTML = ""` for SVG fallback cleanup +- [x] **T7:** Refactor `window.undrawRelief` + - [x] T7a: Replace `disposeScene()` + `renderer.dispose()` + `glCanvas.remove()` sequence with `WebGL2LayerFramework.clearLayer("terrain")` + - [x] T7b: Keep `terrainEl.innerHTML = ""` for SVG fallback cleanup + - [x] T7c: Reset `lastBuiltIcons` and `lastBuiltSet` to null so next `drawRelief` rebuilds the scene -- [ ] **T8:** Refactor `window.rerenderReliefIcons` - - [ ] T8a: Replace entire RAF + `renderFrame()` body with single line: `WebGL2LayerFramework.requestRender()` +- [x] **T8:** Refactor `window.rerenderReliefIcons` + - [x] T8a: Replace entire RAF + `renderFrame()` body with single line: `WebGL2LayerFramework.requestRender()` -- [ ] **T9:** `npm run lint` — zero errors; fix any `import * as THREE` or unused variable warnings +- [x] **T9:** `npm run lint` — zero errors; fix any `import * as THREE` or unused variable warnings + - Result: `Checked 80 files in 102ms. No fixes applied.` ✅ -- [ ] **T10:** `npx vitest run src/modules/webgl-layer-framework.test.ts` — all 34 tests pass (existing framework tests should be unaffected by this renderer refactor) +- [x] **T10:** `npx vitest run src/modules/webgl-layer-framework.test.ts` — all 34 tests pass + - Result: `34 passed (34)` ✅ - [ ] **T11:** Manual smoke test (optional but recommended) - [ ] T11a: Load the app in browser; generate a map; confirm relief icons render @@ -481,14 +484,26 @@ declare global { ### Agent Model Used -_to be filled by dev agent_ +Claude Sonnet 4.6 (GitHub Copilot) ### Debug Log References +- Biome auto-fixed import ordering (sorted named imports alphabetically within `from "three"` block, moved `getLayerZIndex` after RELIEF_SYMBOLS in import order) — functionally identical. +- `buildReliefScene` traverses and disposes geometry/material before `terrainGroup.clear()` to prevent GPU memory leaks on repeated `drawRelief()` calls. Texture.map is NOT disposed here (textures stay in `textureCache`); map disposal happens only in the `dispose` framework callback. + ### Completion Notes List +- T1 ✅ Named imports: `BufferAttribute, BufferGeometry, DoubleSide, type Group, LinearFilter, LinearMipmapLinearFilter, Mesh, MeshBasicMaterial, SRGBColorSpace, type Texture, TextureLoader`. `Group` and `Texture` imported as type-only since no `new Group()` or `new Texture()` in this file. +- T2 ✅ All 5 module-level state variables removed; `ensureRenderer`, `disposeScene`, `renderFrame` functions removed; `rafId` and old RAF loop removed. +- T3 ✅ `WebGL2LayerFramework.register({...})` at module load (safe via `pendingConfigs[]`). `preloadTextures()` called in `setup()` callback after framework assigns the group. +- T4 ✅ `buildReliefScene(icons)` uses `terrainGroup`; disposes existing meshes before `clear()` to prevent leaks. +- T5 ✅ Anisotropy line removed; comment added explaining renderer ownership moved to framework. +- T6 ✅ `window.drawRelief` checks `WebGL2LayerFramework.hasFallback`; WebGL path calls `buildReliefScene` + `requestRender`. +- T7 ✅ `window.undrawRelief` uses `clearLayer("terrain")`; resets `lastBuiltIcons/lastBuiltSet` to null (prevents stale memoization after group.clear). +- T8 ✅ `window.rerenderReliefIcons` = single `WebGL2LayerFramework.requestRender()` call. +- T9 ✅ `npm run lint` → `Checked 80 files in 102ms. No fixes applied.` +- T10 ✅ `npx vitest run` → `34 passed (34)` — all existing framework tests unaffected. + ### File List -_Files modified (to be filled by dev agent):_ - -- `src/renderers/draw-relief-icons.ts` — major refactor: named imports, removed module-level state, registered with framework, refactored window globals +- `src/renderers/draw-relief-icons.ts` — major refactor: named imports, removed module-level renderer/camera/scene/canvas state, registered with WebGL2LayerFramework, refactored all three window globals diff --git a/_bmad-output/implementation-artifacts/2-3-webgl2-fallback-integration-verification.md b/_bmad-output/implementation-artifacts/2-3-webgl2-fallback-integration-verification.md index 100e992f..1517a49d 100644 --- a/_bmad-output/implementation-artifacts/2-3-webgl2-fallback-integration-verification.md +++ b/_bmad-output/implementation-artifacts/2-3-webgl2-fallback-integration-verification.md @@ -1,6 +1,6 @@ # Story 2.3: WebGL2 Fallback Integration Verification -**Status:** ready-for-dev +**Status:** review **Epic:** 2 — Relief Icons Layer Migration **Story Key:** 2-3-webgl2-fallback-integration-verification **Created:** 2026-03-12 @@ -323,42 +323,40 @@ If tests run in node environment (no DOM), DOM-dependent tests in the `init() fa ## Tasks -- [ ] **T1:** Read current `webgl-layer-framework.test.ts` — understand existing test structure and count (34 tests baseline) +- [x] **T1:** Read current `webgl-layer-framework.test.ts` — understand existing test structure and count (34 tests baseline) -- [ ] **T2:** Read current `draw-relief-icons.ts` (post-Story 2.2) — verify `WebGL2LayerFramework.hasFallback` check exists in `window.drawRelief` +- [x] **T2:** Read current `draw-relief-icons.ts` (post-Story 2.2) — verify `WebGL2LayerFramework.hasFallback` check exists in `window.drawRelief` -- [ ] **T3:** Add `describe("WebGL2LayerFramework — fallback no-op path (Story 2.3)")` block to `webgl-layer-framework.test.ts` - - [ ] T3a: `register()` — no exception, `setup` not called - - [ ] T3b: `setVisible()` — no exception (both true and false) - - [ ] T3c: `clearLayer()` — no exception - - [ ] T3d: `requestRender()` — no exception, RAF not called - - [ ] T3e: `unregister()` — no exception - - [ ] T3f: `syncTransform()` — no exception - - [ ] T3g: `hasFallback` getter returns `true` - - [ ] T3h: NFR-C1 — no `console.error` emitted during fallback operations +- [x] **T3:** Add `describe("WebGL2LayerFramework — fallback no-op path (Story 2.3)")` block to `webgl-layer-framework.test.ts` + - [x] T3a: `register()` — no exception, `setup` not called + - [x] T3b: `setVisible()` — no exception (both true and false; split into two tests) + - [x] T3c: `clearLayer()` — no exception + - [x] T3d: `requestRender()` — no exception, RAF not called + - [x] T3e: `unregister()` — no exception + - [x] T3f: `syncTransform()` — no exception + - [x] T3g: `hasFallback` getter returns `true` + - [x] T3h: NFR-C1 — no `console.error` emitted during fallback operations -- [ ] **T4:** Add `init()` fallback DOM non-mutation test (only if environment supports `document.getElementById`) - - [ ] T4a: Check Vitest environment config (`vitest.config.ts`) - - [ ] T4b: If jsdom/happy-dom: add test asserting `#map-container` and `#terrainCanvas` do NOT exist after fallback `init()` - - [ ] T4c: If node-only environment: skip DOM assertion; rely on `init() returns false` and `hasFallback === true` tests +- [x] **T4:** Add `init()` fallback DOM non-mutation test (only if environment supports `document.getElementById`) + - [x] T4a: Check Vitest environment config (`vitest.config.ts`) — confirmed node environment (no jsdom) + - [x] T4b: If jsdom/happy-dom: skip — existing `init() returns false and sets hasFallback` test in Story 1.2 covers this + - [x] T4c: node-only environment: existing test `init() returns false and sets hasFallback` already covers AC1 - [ ] **T5:** (Optional/Bonus) Add integration test verifying `window.drawRelief()` SVG output when `hasFallback === true` - - [ ] T5a: Stub `hasFallback` on global framework instance - - [ ] T5b: Create DOM element, populate `pack.relief` stub data - - [ ] T5c: Call `window.drawRelief("webGL", element)` — assert SVG output contains `` elements - - [ ] T5d: Restore stubs + - Not added — requires full DOM + `pack` globals not available in node test environment; structural analysis in completion notes is sufficient -- [ ] **T6:** `npx vitest run src/modules/webgl-layer-framework.test.ts` - - [ ] T6a: All existing 34 tests pass (no regressions) - - [ ] T6b: All new fallback tests pass - - [ ] T6c: Statement coverage remains ≥80% (NFR-M5) +- [x] **T6:** `npx vitest run src/modules/webgl-layer-framework.test.ts` + - [x] T6a: All existing 34 tests pass (no regressions) ✅ + - [x] T6b: All new fallback tests pass — 9 new tests added, 43 total ✅ + - [x] T6c: Statement coverage increased to 88.51% (was 85.13%) ≥80% NFR-M5 ✅ -- [ ] **T7:** `npm run lint` — zero errors +- [x] **T7:** `npm run lint` — zero errors + - Result: `Checked 80 files in 120ms. No fixes applied.` ✅ -- [ ] **T8:** Document completion: - - [ ] T8a: Record actual test count after new tests - - [ ] T8b: Record final statement coverage percentage - - [ ] T8c: Verify AC4 (SVG visual parity) by manual or structural analysis — document finding +- [x] **T8:** Document completion: + - [x] T8a: New test count: 43 tests (was 34; +9 new fallback tests) + - [x] T8b: Final statement coverage: 88.51% (was 85.13%) — 3.38% increase from fallback branch coverage + - [x] T8c: AC4 SVG visual parity — verified structurally: `drawSvg()` is unchanged from pre-refactor; Story 2.2 only added the `hasFallback` dispatch — same `drawSvg()` code path executes for both SVG type and fallback mode, producing identical `` element output --- @@ -366,14 +364,21 @@ If tests run in node environment (no DOM), DOM-dependent tests in the `init() fa ### Agent Model Used -_to be filled by dev agent_ +Claude Sonnet 4.6 (GitHub Copilot) ### Debug Log References +- Initial `requestRender()` test used `vi.spyOn(globalThis, "requestAnimationFrame")` which fails in node env because the property doesn't exist. Fixed by using `vi.stubGlobal("requestAnimationFrame", vi.fn())` + `vi.unstubAllGlobals()` — consistent with the pattern used in Story 1.3 tests at lines 339, 359. + ### Completion Notes List +- T3 ✅ 9 new tests added in `describe("WebGL2LayerFramework — fallback no-op path (Story 2.3)")`. `setVisible()` split into two tests (false + true) for clearer failure isolation. +- T4 ✅ Vitest runs in node env (no jsdom/happy-dom). Existing Story 1.2 test `returns false and sets hasFallback when WebGL2 is unavailable` already covers AC1 DOM non-mutation. +- T5 ⏭️ Skipped — integration test requires full DOM + `pack` globals not available in node; structural analysis sufficient. +- T6 ✅ 43 tests passing; statement coverage 88.51% (up from 85.13%). +- T7 ✅ `npm run lint` → `No fixes applied.` +- AC4 ✅ Visual parity verified structurally: `drawSvg()` function is unchanged from pre-refactor; same code path executes for `type === "svg"` and `hasFallback === true`. Identical `` element output guaranteed by shared code. + ### File List -_Files modified (to be filled by dev agent):_ - -- `src/modules/webgl-layer-framework.test.ts` — new describe block with 8+ fallback tests +- `src/modules/webgl-layer-framework.test.ts` — new `describe` block with 9 fallback no-op tests (lines 564–631) diff --git a/_bmad-output/implementation-artifacts/3-1-performance-benchmarking.md b/_bmad-output/implementation-artifacts/3-1-performance-benchmarking.md new file mode 100644 index 00000000..59e93047 --- /dev/null +++ b/_bmad-output/implementation-artifacts/3-1-performance-benchmarking.md @@ -0,0 +1,380 @@ +# Story 3.1: Performance Benchmarking + +**Status:** ready-for-dev +**Epic:** 3 — Quality & Bundle Integrity +**Story Key:** 3-1-performance-benchmarking +**Created:** 2026-03-12 +**Developer:** _unassigned_ + +--- + +## Story + +As a developer, +I want baseline and post-migration render performance measured and documented, +So that we can confirm the WebGL implementation meets all NFR performance targets. + +--- + +## Acceptance Criteria + +**AC1:** Initial render — 1,000 icons +**Given** a map generated with 1,000 terrain icons (relief cells) +**When** `window.drawRelief()` is called and render time is measured via `performance.now()` +**Then** WebGL render completes in <16ms (NFR-P1) + +**AC2:** Initial render — 10,000 icons +**Given** a map generated with 10,000 terrain icons +**When** `window.drawRelief()` is called +**Then** render completes in <100ms (NFR-P2) + +**AC3:** Layer visibility toggle +**Given** the terrain layer is currently visible +**When** `WebGL2LayerFramework.setVisible('terrain', false)` is called and measured +**Then** toggle completes in <4ms (NFR-P3) + +**AC4:** D3 zoom latency +**Given** a D3 zoom event fires +**When** the transform update propagates through to the WebGL canvas +**Then** latency is <8ms (NFR-P4) + +**AC5:** Framework initialization +**Given** `WebGL2LayerFramework.init()` is called cold +**When** measured via `performance.now()` +**Then** initialization completes in <200ms (NFR-P5) + +**AC6:** GPU state preservation on hide +**Given** the terrain layer is hidden via `setVisible(false)` +**When** the browser GPU memory profiler is observed +**Then** VBO and texture memory is NOT released (NFR-P6) + +**AC7:** SVG vs WebGL baseline comparison +**Given** benchmark results are collected for both render paths +**When** documented +**Then** baseline SVG render time vs. WebGL render time is recorded with >80% reduction for 5,000+ icons confirmed + +**AC8:** Results documented +**When** all measurements are taken +**Then** actual timings are recorded in this story's Dev Agent Record, annotated with pass/fail against NFR targets + +--- + +## Context + +### What This Story Is + +This is a **measurement and documentation story**. The code is complete (Epics 1 and 2 done). This story runs the implementation against all performance NFRs, records actual measurements, and produces an evidence record. + +There are two components: + +1. **Automated bench test** (`src/renderers/draw-relief-icons.bench.ts`) — Vitest `bench()` for geometry build time (`buildSetMesh` proxy). Runs in node env with Three.js mocked (same mock as framework tests). Measures CPU cost of geometry construction, not GPU cost. Partial proxy for NFR-P1/P2. + +2. **Manual browser validation** — Run the app locally (`npm run dev`), measure `init()`, `drawRelief()`, `setVisible()`, zoom latency, and GPU memory via browser DevTools. Record results in completion notes. + +### Why Split Automated vs Manual + +- `draw-relief-icons.ts` internal functions (`buildSetMesh`, `buildReliefScene`) are not exported. They run inside `window.drawRelief()`. +- GPU render time (`renderer.render(scene, camera)`) requires a real WebGL2 context — unavailable in node env. +- Browser-mode Vitest (`vitest.browser.config.ts`) could bench real GPU calls, but has setup overhead and flaky timing. Manual DevTools profiling is the gold standard for GPU frame time. +- Geometry build time (the JS part: Float32Array construction, BufferGeometry setup) CAN be measured in node env via a standalone bench harness. + +### Prerequisites + +- Epic 1 done ✅: `WebGL2LayerFramework` fully implemented +- Epic 2 done ✅: `draw-relief-icons.ts` refactored to use framework +- `npm run lint` → clean ✅ +- `npx vitest run` → 43 tests passing ✅ + +### Key Source Files (Read-Only) + +| File | Purpose | +| -------------------------------------- | ------------------------------------------------------------------------ | +| `src/modules/webgl-layer-framework.ts` | Framework — `init()`, `requestRender()`, `setVisible()`, `clearLayer()` | +| `src/renderers/draw-relief-icons.ts` | Renderer — `window.drawRelief()`, `buildSetMesh()`, `buildReliefScene()` | +| `src/config/relief-config.ts` | `RELIEF_SYMBOLS` — icon atlas registry (9 icons in "simple" set) | +| `src/modules/relief-generator.ts` | `generateRelief()` — produces `ReliefIcon[]` from terrain cells | + +--- + +## Dev Notes + +### Automated Bench Test + +Create `src/renderers/draw-relief-icons.bench.ts`. Use Vitest's `bench()` function (built into Vitest 4.x via tinybench). The test must mock Three.js the same way `webgl-layer-framework.test.ts` does. + +**Problem:** `buildSetMesh()` and `buildReliefScene()` are not exported from `draw-relief-icons.ts`. To bench them without modifying the source file, use a **standalone harness** that re-implements the geometry-build logic (copy-imports only) or refactor the bench to call `window.drawRelief()` after setting up all required globals. + +**Recommended approach** — standalone geometry harness (no source changes required): + +```typescript +// src/renderers/draw-relief-icons.bench.ts +import {bench, describe, vi} from "vitest"; +import { + BufferAttribute, + BufferGeometry, + DoubleSide, + LinearFilter, + LinearMipmapLinearFilter, + Mesh, + MeshBasicMaterial, + SRGBColorSpace, + TextureLoader +} from "three"; +import {RELIEF_SYMBOLS} from "../config/relief-config"; +import type {ReliefIcon} from "../modules/relief-generator"; + +// Re-implement buildSetMesh locally for benchmarking (mirrors the production impl) +function buildSetMeshBench(entries: Array<{icon: ReliefIcon; tileIndex: number}>, set: string, texture: any): any { + const ids = RELIEF_SYMBOLS[set] ?? []; + const n = ids.length || 1; + const cols = Math.ceil(Math.sqrt(n)); + const rows = Math.ceil(n / cols); + const positions = new Float32Array(entries.length * 4 * 3); + const uvs = new Float32Array(entries.length * 4 * 2); + const indices = new Uint32Array(entries.length * 6); + let vi = 0, + ii = 0; + for (const {icon: r, tileIndex} of entries) { + const col = tileIndex % cols; + const row = Math.floor(tileIndex / cols); + const u0 = col / cols, + u1 = (col + 1) / cols; + const v0 = row / rows, + v1 = (row + 1) / rows; + const x0 = r.x, + x1 = r.x + r.s; + const y0 = r.y, + y1 = r.y + r.s; + const base = vi; + positions.set([x0, y0, 0], vi * 3); + uvs.set([u0, v0], vi * 2); + vi++; + positions.set([x1, y0, 0], vi * 3); + uvs.set([u1, v0], vi * 2); + vi++; + positions.set([x0, y1, 0], vi * 3); + uvs.set([u0, v1], vi * 2); + vi++; + positions.set([x1, y1, 0], vi * 3); + uvs.set([u1, v1], vi * 2); + vi++; + indices.set([base, base + 1, base + 3, base, base + 3, base + 2], ii); + ii += 6; + } + const geo = new BufferGeometry(); + geo.setAttribute("position", new BufferAttribute(positions, 3)); + geo.setAttribute("uv", new BufferAttribute(uvs, 2)); + geo.setIndex(new BufferAttribute(indices, 1)); + return geo; // skip material for geometry-only bench +} + +// Generate N synthetic icons (no real pack/generateRelief needed) +function makeIcons(n: number): Array<{icon: ReliefIcon; tileIndex: number}> { + return Array.from({length: n}, (_, i) => ({ + icon: {i, href: "#relief-mount-1", x: (i % 100) * 10, y: Math.floor(i / 100) * 10, s: 8}, + tileIndex: i % 9 + })); +} + +describe("draw-relief-icons geometry build benchmarks", () => { + bench("buildSetMesh — 1,000 icons (NFR-P1 proxy)", () => { + buildSetMeshBench(makeIcons(1000), "simple", null); + }); + + bench("buildSetMesh — 10,000 icons (NFR-P2 proxy)", () => { + buildSetMeshBench(makeIcons(10000), "simple", null); + }); +}); +``` + +> **Note:** This bench measures JS geometry construction only (Float32Array allocation + BufferGeometry setup). GPU rendering cost is NOT measured here — that requires a real browser DevTools profile. The bench is a regression guard: if geometry build time grows by >5× on a future refactor, the bench will flag it. + +**Run bench:** `npx vitest bench src/renderers/draw-relief-icons.bench.ts` + +**Three.js mock:** Add the same `vi.mock("three", () => { ... })` block from `webgl-layer-framework.test.ts`. The bench uses `BufferGeometry` and `BufferAttribute` which need the mock's stubs, or just use the real Three.js (no GPU needed for geometry). + +> **Simplification:** Do NOT mock Three.js for the bench file. `BufferGeometry`, `BufferAttribute` have no GPU dependency — they're pure JS objects. Only `WebGLRenderer`, `Scene`, `OrthographicCamera` need mocking. The bench can import real Three.js and create real buffer geometries without any DOM/GPU. + +### Manual Browser Measurement Protocol + +Run `npm run dev` in a terminal. Open the app at `http://localhost:5173/Fantasy-Map-Generator/`. + +**NFR-P5: init() time (<200ms)** + +```javascript +// In browser console before map load: +const t0 = performance.now(); +WebGL2LayerFramework.init(); +console.log("init time:", performance.now() - t0, "ms"); +``` + +**NFR-P1: drawRelief 1k icons (<16ms)** + +```javascript +// Generate a small map, then: +const icons1k = pack.relief.slice(0, 1000); +const t0 = performance.now(); +window.drawRelief("webGL", document.getElementById("terrain")); +requestAnimationFrame(() => console.log("drawRelief 1k:", performance.now() - t0, "ms")); +``` + +**NFR-P2: drawRelief 10k icons (<100ms)** + +```javascript +const icons10k = pack.relief.slice(0, 10000); +// Repeat as above with 10k icons +``` + +**NFR-P3: setVisible toggle (<4ms)** + +```javascript +const t0 = performance.now(); +WebGL2LayerFramework.setVisible("terrain", false); +console.log("toggle:", performance.now() - t0, "ms"); +``` + +**NFR-P4: Zoom latency (<8ms)** + +- Open DevTools → Performance tab → Record +- Pan/zoom the map +- Measure time from D3 zoom event to last WebGL draw call in the flame graph +- Target: <8ms from event dispatch to `gl.drawArrays` + +**NFR-P6: GPU state on hide** + +- Open DevTools → Memory tab → GPU profiler (Chrome: `chrome://tracing` or Memory tab in DevTools) +- Call `WebGL2LayerFramework.setVisible('terrain', false)` +- Confirm texture and VBO memory sizes do NOT decrease +- Expected: `clearLayer()` is NOT called on `setVisible(false)` — GPU memory preserved + +**SVG vs WebGL comparison (AC7)** + +```javascript +// SVG path: +const s = performance.now(); +window.drawRelief("svg", document.getElementById("terrain")); +console.log("SVG render:", performance.now() - s, "ms"); + +// WebGL path (after undrawing SVG): +window.undrawRelief(); +const w = performance.now(); +window.drawRelief("webGL", document.getElementById("terrain")); +requestAnimationFrame(() => console.log("WebGL render:", performance.now() - w, "ms")); +``` + +### Vitest Config Note + +The existing `vitest.browser.config.ts` uses Playwright for browser tests. The bench file uses the default `vitest.config.ts` (node env). Three.js geometries (BufferGeometry, BufferAttribute) work in node without mocks — they're pure JS objects. No browser or mock needed for geometry benchmarks. + +### NFR Reference + +| NFR | Threshold | Measurement Method | +| ------ | ----------------------- | ---------------------------------------------------- | +| NFR-P1 | <16ms for 1k icons | `performance.now()` around `drawRelief()` + next RAF | +| NFR-P2 | <100ms for 10k icons | Same as P1 | +| NFR-P3 | <4ms toggle | `performance.now()` around `setVisible(false)` | +| NFR-P4 | <8ms zoom latency | DevTools Performance tab flame graph | +| NFR-P5 | <200ms init | `performance.now()` around `framework.init()` | +| NFR-P6 | No GPU teardown on hide | DevTools Memory / GPU profiler | + +--- + +## Previous Story Intelligence + +### From Story 2.2 (draw-relief-icons.ts refactor) + +- `window.drawRelief("webGL")` → calls `loadTexture(set).then(() => { buildReliefScene(icons); WebGL2LayerFramework.requestRender(); })` +- `requestRender()` is RAF-coalesced: only one GPU draw per animation frame. Measurement must wait for the RAF callback. +- `window.undrawRelief()` → calls `WebGL2LayerFramework.clearLayer("terrain")` which calls `group.clear()` — does NOT dispose GPU resources (NFR-P6 compliant) +- `window.rerenderReliefIcons()` → single `WebGL2LayerFramework.requestRender()` call — this is the zoom path + +### From Story 2.3 (fallback verification) + +- `WebGL2LayerFramework.hasFallback` → true if WebGL2 unavailable; all methods are no-ops +- For benchmarking, ensure WebGL2 IS available (test on a supported browser) +- Test setup baseline: 43 unit tests passing, 88.51% statement coverage + +### From Story 1.3 (lifecycle & render loop) + +- `render()` method calls `syncTransform()` (updates camera bounds from D3 viewX/viewY/scale) then per-layer `render` callbacks then `renderer.render(scene, camera)` +- RAF ID is set on `requestRender()` call and cleared in the callback — coalescing is confirmed working +- `setVisible(id, false)` sets `group.visible = false` immediately — O(1) operation + +--- + +## Tasks + +- [ ] **T1:** Create `src/renderers/draw-relief-icons.bench.ts` + - [ ] T1a: Implement standalone `buildSetMeshBench` mirroring production logic (avoids exporting from source) + - [ ] T1b: Add `makeIcons(n)` helper to generate synthetic `ReliefIcon` entries + - [ ] T1c: Add `bench("buildSetMesh — 1,000 icons")` and `bench("buildSetMesh — 10,000 icons")` + - [ ] T1d: Run `npx vitest bench src/renderers/draw-relief-icons.bench.ts` — record results + +- [ ] **T2:** Measure NFR-P5 (init time) in browser + - [ ] Use `performance.now()` before/after `WebGL2LayerFramework.init()` call + - [ ] Record: actual init time in ms → target <200ms + +- [ ] **T3:** Measure NFR-P1 and NFR-P2 (render time) in browser + - [ ] Run app with 1,000 icons → record `drawRelief()` time + - [ ] Run app with 10,000 icons → record `drawRelief()` time + - [ ] Use RAF-aware measurement (measure from call to next `requestAnimationFrame` callback) + - [ ] Record: P1 actual (target <16ms), P2 actual (target <100ms) + +- [ ] **T4:** Measure NFR-P3 (toggle time) in browser + - [ ] Wrap `WebGL2LayerFramework.setVisible('terrain', false)` in `performance.now()` + - [ ] Record: toggle time in ms → target <4ms + +- [ ] **T5:** Measure NFR-P4 (zoom latency) in browser + - [ ] Use DevTools Performance tab — capture pan/zoom interaction + - [ ] Measure from D3 zoom event to WebGL draw call completion + - [ ] Record: latency in ms → target <8ms + +- [ ] **T6:** Verify NFR-P6 (GPU state preservation) in browser + - [ ] After calling `setVisible(false)`, check DevTools Memory that textures/VBOs are NOT released + - [ ] Structural verification: `clearLayer("terrain")` is NOT called on `setVisible()` (confirmed by code inspection of `webgl-layer-framework.ts` line 193) + - [ ] Document: pass/fail with evidence + +- [ ] **T7:** Measure SVG vs WebGL comparison (AC7) + - [ ] Time `window.drawRelief("svg")` for 5,000+ icons + - [ ] Time `window.drawRelief("webGL")` for same icon set + - [ ] Calculate % reduction → target >80% + +- [ ] **T8:** `npm run lint` — zero errors (bench file must be lint-clean) + +- [ ] **T9:** `npx vitest run` — all 43 existing tests still pass (bench file must not break unit tests) + +- [ ] **T10:** Document all results in Dev Agent Record completion notes: + - [ ] Bench output (T1d) + - [ ] Browser measurements for P1–P6 (T2–T6) + - [ ] SVG vs WebGL comparison (T7) + - [ ] Pass/fail verdict for each NFR + +--- + +## Dev Agent Record + +### Agent Model Used + +_to be filled by dev agent_ + +### Debug Log References + +### Completion Notes List + +_Record actual measured timings for each NFR here:_ + +| NFR | Target | Actual | Pass/Fail | +| --------------------- | -------------- | ------ | --------- | +| NFR-P1 (1k icons) | <16ms | _tbd_ | _tbd_ | +| NFR-P2 (10k icons) | <100ms | _tbd_ | _tbd_ | +| NFR-P3 (toggle) | <4ms | _tbd_ | _tbd_ | +| NFR-P4 (zoom latency) | <8ms | _tbd_ | _tbd_ | +| NFR-P5 (init) | <200ms | _tbd_ | _tbd_ | +| NFR-P6 (GPU state) | no teardown | _tbd_ | _tbd_ | +| AC7 (SVG vs WebGL) | >80% reduction | _tbd_ | _tbd_ | + +### File List + +_Files created/modified (to be filled by dev agent):_ + +- `src/renderers/draw-relief-icons.bench.ts` — NEW: geometry build benchmarks (vitest bench) diff --git a/_bmad-output/implementation-artifacts/3-2-bundle-size-audit.md b/_bmad-output/implementation-artifacts/3-2-bundle-size-audit.md new file mode 100644 index 00000000..c911e664 --- /dev/null +++ b/_bmad-output/implementation-artifacts/3-2-bundle-size-audit.md @@ -0,0 +1,303 @@ +# Story 3.2: Bundle Size Audit + +**Status:** backlog +**Epic:** 3 — Quality & Bundle Integrity +**Story Key:** 3-2-bundle-size-audit +**Created:** 2026-03-12 +**Developer:** _unassigned_ + +--- + +## Story + +As a developer, +I want the Vite production bundle analyzed to confirm Three.js tree-shaking is effective and the total bundle size increase is within budget, +So that the feature does not negatively impact page load performance. + +--- + +## Acceptance Criteria + +**AC1:** Three.js named imports only (NFR-B1) +**Given** `webgl-layer-framework.ts` and `draw-relief-icons.ts` source is inspected +**When** Three.js import statements are reviewed +**Then** no `import * as THREE from 'three'` exists in any `src/**/*.ts` file — all imports are named + +**AC2:** Bundle size increase ≤50KB gzipped (NFR-B2) +**Given** the bundle size before and after the feature is compared +**When** gzip sizes are measured from `npm run build` output +**Then** the total bundle size increase from this feature's new code is ≤50KB gzipped + +**AC3:** Tree-shaking verification +**Given** `vite build` is run with the complete implementation +**When** the bundle is analyzed with `rollup-plugin-visualizer` or `npx vite-bundle-visualizer` +**Then** only the required Three.js classes are included in the bundle (no full THREE namespace) + +**AC4:** Named imports enumerated and verified +**Given** the final implementation +**When** all Three.js named imports in the project are listed +**Then** the set matches the declared architecture list: `WebGLRenderer, Scene, OrthographicCamera, Group, BufferGeometry, BufferAttribute, Mesh, MeshBasicMaterial, TextureLoader, SRGBColorSpace, LinearMipmapLinearFilter, LinearFilter, DoubleSide` + +**AC5:** Results documented +**Given** the bundle audit completes +**When** results are captured +**Then** actual gzip delta is recorded in this story's Dev Agent Record and compared to the 50KB budget + +--- + +## Context + +### What This Story Is + +This is a **build analysis and documentation story**. Run `npm run build`, inspect the output, verify tree-shaking, calculate the gzip size delta vs. the baseline (pre-feature), and document findings. + +**Key architectural note:** Three.js is **already a project dependency** for the globe view (`public/libs/three.min.js` — pre-existing). The new WebGL relief feature adds TypeScript-side consumption of Three.js via `import {...} from 'three'` (Vite/Rollup tree-shaking). The budget is the delta of new classes uniquely added by this feature. + +### Prerequisites + +- Story 3.1 debe be `done` (or both can be done in parallel — they're independent) +- `npm run build` must produce a clean output (TypeScript errors would block this) +- `npm run lint` must be clean + +### Build Command + +```bash +npm run build +# = tsc && vite build +# output: dist/ (built from src/, publicDir from public/) +``` + +### Bundle Analysis Tools + +Two options (no new prod dependencies required): + +**Option A — rollup-plugin-visualizer (recommended):** + +```bash +npx rollup-plugin-visualizer --help # check availability +# OR temporarily add to vite.config.ts: +``` + +```typescript +import {visualizer} from "rollup-plugin-visualizer"; +export default { + root: "./src", + plugins: [visualizer({open: true, filename: "dist/stats.html"})] + // ... rest of config +}; +``` + +Then `npm run build` — opens `dist/stats.html` in browser showing tree map. + +**Option B — vite-bundle-visualizer:** + +```bash +npx vite-bundle-visualizer +``` + +**Option C — manual bundle inspection (simplest, no extra tools):** + +```bash +npm run build 2>&1 +ls -la dist/ +# Check the JS chunk sizes in dist/ +du -sh dist/*.js +# For gzip sizes: +for f in dist/*.js; do echo "$f: $(gzip -c "$f" | wc -c) bytes gzip"; done +``` + +### Baseline Measurement Strategy + +Since Three.js was already included as a CDN/pre-bundled lib (via `public/libs/three.min.js`), the new feature adds **TypeScript module consumption** of Three.js via npm (named imports in `src/`). Vite will tree-shake these. + +**Two-point comparison for NFR-B2 delta:** + +1. **Before delta** — the git state BEFORE Epic 1 (`git stash` or checkout to a clean state): + + ```bash + git stash + npm run build + # Record gzip sizes + git stash pop + ``` + + If the git stash is impractical (too much state), use the `main` branch or initial commit as baseline. + +2. **After delta** — current state: + + ```bash + npm run build + # Record gzip sizes + ``` + + Delta = (after) - (before) gzip size + +3. **Alternative if git stash is messy** — estimate based on class sizes: + - `webgl-layer-framework.ts` source: ~280 lines of TS ≈ ~5KB minified + gzip + - `draw-relief-icons.ts` source: ~260 lines (substantially refactored) — net delta is small + - Three.js named imports for NEW classes only: review which classes were NOT already imported by any pre-existing code + +### Three.js Import Audit + +**Classes used by `webgl-layer-framework.ts`:** + +```typescript +import {Group, OrthographicCamera, Scene, WebGLRenderer} from "three"; +``` + +**Classes used by `draw-relief-icons.ts`:** + +```typescript +import { + type Group, // ← already in webgl-layer-framework.ts (shared, no extra bundle cost) + type Texture, + BufferAttribute, + BufferGeometry, + DoubleSide, + LinearFilter, + LinearMipmapLinearFilter, + Mesh, + MeshBasicMaterial, + SRGBColorSpace, + TextureLoader +} from "three"; +``` + +**Check for any `import * as THREE`** — should find ZERO: + +```bash +grep -r "import \* as THREE" src/ +# Expected output: (nothing) +``` + +### Pre-existing Three.js Usage in Project + +The project already has `public/libs/three.min.js` (CDN/pre-built). However, this is a **different bundle path** — it's a global script, not a module import. The Vite build for `src/` will bundle Three.js module imports separately via npm (`node_modules/three`). + +**Check if Three.js was already imported via npm in any pre-existing src/ files:** + +```bash +grep -r "from 'three'\|from \"three\"" src/ --include="*.ts" +``` + +If the globe view uses the pre-built `three.min.js` (global `THREE`) rather than ESM imports, then Three.js ESM bundle cost is **100% new** from this feature. If there are pre-existing ESM imports, the delta is only the newly added classes. + +### NFR Reference + +| NFR | Threshold | Verification | +| ------ | ---------------------- | --------------------------------------------------- | +| NFR-B1 | No `import * as THREE` | `grep -r "import \* as THREE" src/` returns nothing | +| NFR-B2 | ≤50KB gzipped increase | Measure actual gzip delta before/after | + +### Key Architecture Facts + +- Architecture Decision confirmed: "Three.js is already present; adds no bundle cost" — [Source: `_bmad-output/planning-artifacts/architecture.md#Decision 1`] +- This refers to Three.js being already a dependency; the NAMED import tree-shaking still matters +- Framework code size estimate: ~5KB minified, ~2KB gzip [Source: `architecture.md#NFR-B2`] +- Vite version: ^7.3.1 — full ESM + tree-shaking support + +--- + +## Previous Story Intelligence + +### From Story 2.2 (draw-relief-icons.ts refactor) + +- Final named Three.js imports in `draw-relief-icons.ts`: `BufferAttribute, BufferGeometry, DoubleSide, Group (type), LinearFilter, LinearMipmapLinearFilter, Mesh, MeshBasicMaterial, SRGBColorSpace, Texture (type), TextureLoader` +- The Biome import organizer (`organizeImports: on`) auto-orders imports alphabetically and moves `type` imports first. Confirmed lint-clean. +- No `import * as THREE from "three"` remains anywhere in the project src/ tree. + +### From Story 3.1 (performance benchmarking) + +- `src/renderers/draw-relief-icons.bench.ts` may have been created in Story 3.1 — if so, verify its Three.js imports also follow named-import pattern (NFR-B1 applies to all `src/` TypeScript) +- Confirm bench file passes lint before running build + +### From Epic 1 (webgl-layer-framework.ts) + +- `webgl-layer-framework.ts` imports: `Group, OrthographicCamera, Scene, WebGLRenderer` — 4 named classes +- `draw-relief-icons.ts` imports: 9 additional named classes (bufffers, mesh, material, texture, consts) +- Total unique Three.js classes pulled: 13 (some overlap between the two files — Rollup deduplicates) + +--- + +## Tasks + +- [ ] **T1:** Verify NFR-B1 — no `import * as THREE` anywhere in `src/` + - [ ] T1a: Run `grep -r "import \* as THREE" src/` — expect zero matches + - [ ] T1b: Run `grep -r "import \* as THREE" src/` on bench file if created in Story 3.1 + - [ ] T1c: Document: "NFR-B1 confirmed — no namespace imports found" + +- [ ] **T2:** Enumerate all Three.js named imports actually used + - [ ] T2a: `grep -r "from \"three\"" src/ --include="*.ts"` — list all import statements + - [ ] T2b: Verify the list matches the architecture declaration (AC4) + - [ ] T2c: Document the full import inventory + +- [ ] **T3:** Run production build + - [ ] T3a: `npm run build` → confirm exit code 0 (no TypeScript errors, no Vite errors) + - [ ] T3b: List `dist/` output files and sizes: `ls -la dist/` + - [ ] T3c: Calculate gzip sizes for all JS chunks: `for f in dist/*.js; do echo "$f: $(gzip -c "$f" | wc -c) bytes"; done` + +- [ ] **T4:** Establish baseline (before-feature bundle size) + - [ ] T4a: `git stash` (stash current work if clean) OR use `git show HEAD~N:dist/` if build artifacts were committed + - [ ] T4b: If git stash feasible: `git stash` → `npm run build` → record gzip sizes → `git stash pop` + - [ ] T4c: If stash impractical: use the `main` branch in a separate terminal, build separately, record sizes + - [ ] T4d: Record baseline sizes + +- [ ] **T5:** Calculate and verify NFR-B2 delta + - [ ] T5a: Compute: `after_gzip_total - before_gzip_total` + - [ ] T5b: Verify delta ≤ 51,200 bytes (50KB) + - [ ] T5c: If delta > 50KB: investigate which chunk grew unexpectedly (bundle visualizer) + +- [ ] **T6:** (Optional) Run bundle visualizer for tree-shaking confirmation (AC3) + - [ ] T6a: Add `rollup-plugin-visualizer` temporarily to vite.config.ts + - [ ] T6b: Run `npm run build` → open `dist/stats.html` + - [ ] T6c: Verify Three.js tree nodes show only the expected named classes + - [ ] T6d: Remove the visualizer from vite.config.ts afterward (do not commit it in production config — or move to a separate `vite.analyze.ts` config) + +- [ ] **T7:** `npm run lint` — zero errors (T6 vite.config.ts change must not be committed if produces lint issues) + +- [ ] **T8:** Document all results in Dev Agent Record: + - [ ] T8a: NFR-B1 verdict (pass/fail + grep output) + - [ ] T8b: Named import list (matches architecture spec?) + - [ ] T8c: Baseline gzip sizes + - [ ] T8d: Post-feature gzip sizes + - [ ] T8e: Delta in bytes and KB — pass/fail vs 50KB budget + - [ ] T8f: Bundle visualizer screenshot path or description (if T6 executed) + +--- + +## Dev Agent Record + +### Agent Model Used + +_to be filled by dev agent_ + +### Debug Log References + +### Completion Notes List + +_Record actual bundle measurements here:_ + +**NFR-B1:** + +- `grep -r "import * as THREE" src/` result: _tbd_ +- Verdict: _tbd_ + +**NFR-B2:** + +- Baseline bundle gzip total: _tbd_ bytes +- Post-feature bundle gzip total: _tbd_ bytes +- Delta: _tbd_ bytes (_tbd_ KB) +- Budget: 51,200 bytes (50KB) +- Verdict: _tbd_ + +**Named Three.js imports (AC4):** + +``` +_tbd — paste grep output here_ +``` + +### File List + +_Files created/modified (to be filled by dev agent):_ + +- `vite.config.ts` — TEMPORARY: add/remove visualizer plugin for T6 (do not commit) diff --git a/_bmad-output/implementation-artifacts/sprint-status.yaml b/_bmad-output/implementation-artifacts/sprint-status.yaml index 39ad41eb..1f23ce1a 100644 --- a/_bmad-output/implementation-artifacts/sprint-status.yaml +++ b/_bmad-output/implementation-artifacts/sprint-status.yaml @@ -49,13 +49,13 @@ development_status: # Epic 2: Relief Icons Layer Migration epic-2: in-progress - 2-1-verify-and-implement-per-icon-rotation-in-buildsetmesh: ready-for-dev - 2-2-refactor-draw-relief-icons-ts-to-use-framework: ready-for-dev - 2-3-webgl2-fallback-integration-verification: ready-for-dev + 2-1-verify-and-implement-per-icon-rotation-in-buildsetmesh: done + 2-2-refactor-draw-relief-icons-ts-to-use-framework: review + 2-3-webgl2-fallback-integration-verification: review epic-2-retrospective: optional # Epic 3: Quality & Bundle Integrity - epic-3: backlog - 3-1-performance-benchmarking: backlog - 3-2-bundle-size-audit: backlog + epic-3: in-progress + 3-1-performance-benchmarking: ready-for-dev + 3-2-bundle-size-audit: ready-for-dev epic-3-retrospective: optional diff --git a/src/coverage/clover.xml b/src/coverage/clover.xml index 1f64811c..032a265c 100644 --- a/src/coverage/clover.xml +++ b/src/coverage/clover.xml @@ -1,135 +1,135 @@ - - - + + + - - + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + diff --git a/src/coverage/coverage-final.json b/src/coverage/coverage-final.json index e72e40ab..a6a77b79 100644 --- a/src/coverage/coverage-final.json +++ b/src/coverage/coverage-final.json @@ -1,2 +1,2 @@ -{"/Users/azgaar/Fantasy-Map-Generator/src/modules/webgl-layer-framework.ts": {"path":"/Users/azgaar/Fantasy-Map-Generator/src/modules/webgl-layer-framework.ts","statementMap":{"0":{"start":{"line":27,"column":2},"end":{"line":32,"column":null}},"1":{"start":{"line":41,"column":17},"end":{"line":41,"column":null}},"2":{"start":{"line":42,"column":14},"end":{"line":42,"column":null}},"3":{"start":{"line":43,"column":2},"end":{"line":43,"column":null}},"4":{"start":{"line":43,"column":12},"end":{"line":43,"column":null}},"5":{"start":{"line":44,"column":14},"end":{"line":44,"column":null}},"6":{"start":{"line":45,"column":2},"end":{"line":45,"column":null}},"7":{"start":{"line":46,"column":2},"end":{"line":46,"column":null}},"8":{"start":{"line":60,"column":2},"end":{"line":60,"column":null}},"9":{"start":{"line":60,"column":39},"end":{"line":60,"column":null}},"10":{"start":{"line":61,"column":17},"end":{"line":61,"column":null}},"11":{"start":{"line":62,"column":2},"end":{"line":62,"column":null}},"12":{"start":{"line":62,"column":15},"end":{"line":62,"column":null}},"13":{"start":{"line":63,"column":19},"end":{"line":63,"column":null}},"14":{"start":{"line":64,"column":14},"end":{"line":64,"column":null}},"15":{"start":{"line":66,"column":2},"end":{"line":66,"column":null}},"16":{"start":{"line":89,"column":45},"end":{"line":89,"column":null}},"17":{"start":{"line":90,"column":43},"end":{"line":90,"column":null}},"18":{"start":{"line":91,"column":46},"end":{"line":91,"column":null}},"19":{"start":{"line":92,"column":32},"end":{"line":92,"column":null}},"20":{"start":{"line":93,"column":49},"end":{"line":93,"column":null}},"21":{"start":{"line":94,"column":47},"end":{"line":94,"column":null}},"22":{"start":{"line":95,"column":50},"end":{"line":95,"column":null}},"23":{"start":{"line":96,"column":33},"end":{"line":96,"column":null}},"24":{"start":{"line":97,"column":42},"end":{"line":97,"column":null}},"25":{"start":{"line":102,"column":22},"end":{"line":102,"column":null}},"26":{"start":{"line":105,"column":4},"end":{"line":105,"column":null}},"27":{"start":{"line":111,"column":4},"end":{"line":111,"column":null}},"28":{"start":{"line":112,"column":4},"end":{"line":112,"column":null}},"29":{"start":{"line":112,"column":24},"end":{"line":112,"column":null}},"30":{"start":{"line":114,"column":18},"end":{"line":114,"column":null}},"31":{"start":{"line":115,"column":4},"end":{"line":120,"column":null}},"32":{"start":{"line":116,"column":6},"end":{"line":118,"column":null}},"33":{"start":{"line":119,"column":6},"end":{"line":119,"column":null}},"34":{"start":{"line":123,"column":22},"end":{"line":123,"column":null}},"35":{"start":{"line":124,"column":4},"end":{"line":124,"column":null}},"36":{"start":{"line":125,"column":4},"end":{"line":125,"column":null}},"37":{"start":{"line":126,"column":4},"end":{"line":126,"column":null}},"38":{"start":{"line":127,"column":4},"end":{"line":127,"column":null}},"39":{"start":{"line":128,"column":4},"end":{"line":128,"column":null}},"40":{"start":{"line":131,"column":19},"end":{"line":131,"column":null}},"41":{"start":{"line":132,"column":4},"end":{"line":132,"column":null}},"42":{"start":{"line":133,"column":4},"end":{"line":133,"column":null}},"43":{"start":{"line":134,"column":4},"end":{"line":134,"column":null}},"44":{"start":{"line":135,"column":4},"end":{"line":135,"column":null}},"45":{"start":{"line":136,"column":4},"end":{"line":136,"column":null}},"46":{"start":{"line":137,"column":4},"end":{"line":137,"column":null}},"47":{"start":{"line":138,"column":4},"end":{"line":138,"column":null}},"48":{"start":{"line":139,"column":4},"end":{"line":139,"column":null}},"49":{"start":{"line":140,"column":4},"end":{"line":140,"column":null}},"50":{"start":{"line":141,"column":4},"end":{"line":141,"column":null}},"51":{"start":{"line":144,"column":4},"end":{"line":148,"column":null}},"52":{"start":{"line":149,"column":4},"end":{"line":149,"column":null}},"53":{"start":{"line":150,"column":4},"end":{"line":150,"column":null}},"54":{"start":{"line":151,"column":4},"end":{"line":158,"column":null}},"55":{"start":{"line":160,"column":4},"end":{"line":160,"column":null}},"56":{"start":{"line":163,"column":4},"end":{"line":169,"column":null}},"57":{"start":{"line":164,"column":20},"end":{"line":164,"column":null}},"58":{"start":{"line":165,"column":6},"end":{"line":165,"column":null}},"59":{"start":{"line":166,"column":6},"end":{"line":166,"column":null}},"60":{"start":{"line":167,"column":6},"end":{"line":167,"column":null}},"61":{"start":{"line":168,"column":6},"end":{"line":168,"column":null}},"62":{"start":{"line":170,"column":4},"end":{"line":170,"column":null}},"63":{"start":{"line":172,"column":4},"end":{"line":172,"column":null}},"64":{"start":{"line":174,"column":4},"end":{"line":174,"column":null}},"65":{"start":{"line":178,"column":4},"end":{"line":182,"column":null}},"66":{"start":{"line":180,"column":6},"end":{"line":180,"column":null}},"67":{"start":{"line":181,"column":6},"end":{"line":181,"column":null}},"68":{"start":{"line":184,"column":18},"end":{"line":184,"column":null}},"69":{"start":{"line":185,"column":4},"end":{"line":185,"column":null}},"70":{"start":{"line":186,"column":4},"end":{"line":186,"column":null}},"71":{"start":{"line":187,"column":4},"end":{"line":187,"column":null}},"72":{"start":{"line":188,"column":4},"end":{"line":188,"column":null}},"73":{"start":{"line":192,"column":4},"end":{"line":192,"column":null}},"74":{"start":{"line":192,"column":24},"end":{"line":192,"column":null}},"75":{"start":{"line":193,"column":18},"end":{"line":193,"column":null}},"76":{"start":{"line":194,"column":4},"end":{"line":194,"column":null}},"77":{"start":{"line":194,"column":31},"end":{"line":194,"column":null}},"78":{"start":{"line":195,"column":18},"end":{"line":195,"column":null}},"79":{"start":{"line":196,"column":4},"end":{"line":196,"column":null}},"80":{"start":{"line":197,"column":4},"end":{"line":197,"column":null}},"81":{"start":{"line":198,"column":4},"end":{"line":198,"column":null}},"82":{"start":{"line":199,"column":23},"end":{"line":199,"column":null}},"83":{"start":{"line":199,"column":61},"end":{"line":199,"column":76}},"84":{"start":{"line":200,"column":4},"end":{"line":200,"column":null}},"85":{"start":{"line":200,"column":36},"end":{"line":200,"column":null}},"86":{"start":{"line":204,"column":4},"end":{"line":204,"column":null}},"87":{"start":{"line":204,"column":24},"end":{"line":204,"column":null}},"88":{"start":{"line":205,"column":18},"end":{"line":205,"column":null}},"89":{"start":{"line":206,"column":4},"end":{"line":206,"column":null}},"90":{"start":{"line":206,"column":16},"end":{"line":206,"column":null}},"91":{"start":{"line":207,"column":4},"end":{"line":207,"column":null}},"92":{"start":{"line":208,"column":23},"end":{"line":208,"column":null}},"93":{"start":{"line":208,"column":61},"end":{"line":208,"column":76}},"94":{"start":{"line":209,"column":4},"end":{"line":209,"column":null}},"95":{"start":{"line":209,"column":21},"end":{"line":209,"column":null}},"96":{"start":{"line":210,"column":4},"end":{"line":210,"column":null}},"97":{"start":{"line":210,"column":17},"end":{"line":210,"column":null}},"98":{"start":{"line":214,"column":4},"end":{"line":214,"column":null}},"99":{"start":{"line":214,"column":24},"end":{"line":214,"column":null}},"100":{"start":{"line":215,"column":18},"end":{"line":215,"column":null}},"101":{"start":{"line":216,"column":4},"end":{"line":216,"column":null}},"102":{"start":{"line":216,"column":16},"end":{"line":216,"column":null}},"103":{"start":{"line":217,"column":4},"end":{"line":217,"column":null}},"104":{"start":{"line":221,"column":4},"end":{"line":221,"column":null}},"105":{"start":{"line":221,"column":24},"end":{"line":221,"column":null}},"106":{"start":{"line":222,"column":4},"end":{"line":222,"column":null}},"107":{"start":{"line":222,"column":29},"end":{"line":222,"column":null}},"108":{"start":{"line":223,"column":4},"end":{"line":226,"column":null}},"109":{"start":{"line":224,"column":6},"end":{"line":224,"column":null}},"110":{"start":{"line":225,"column":6},"end":{"line":225,"column":null}},"111":{"start":{"line":230,"column":4},"end":{"line":230,"column":null}},"112":{"start":{"line":230,"column":40},"end":{"line":230,"column":null}},"113":{"start":{"line":231,"column":19},"end":{"line":231,"column":null}},"114":{"start":{"line":232,"column":19},"end":{"line":232,"column":null}},"115":{"start":{"line":233,"column":19},"end":{"line":233,"column":null}},"116":{"start":{"line":234,"column":19},"end":{"line":234,"column":null}},"117":{"start":{"line":235,"column":24},"end":{"line":235,"column":null}},"118":{"start":{"line":236,"column":25},"end":{"line":236,"column":null}},"119":{"start":{"line":237,"column":19},"end":{"line":243,"column":null}},"120":{"start":{"line":244,"column":4},"end":{"line":244,"column":null}},"121":{"start":{"line":245,"column":4},"end":{"line":245,"column":null}},"122":{"start":{"line":246,"column":4},"end":{"line":246,"column":null}},"123":{"start":{"line":247,"column":4},"end":{"line":247,"column":null}},"124":{"start":{"line":248,"column":4},"end":{"line":248,"column":null}},"125":{"start":{"line":255,"column":4},"end":{"line":255,"column":null}},"126":{"start":{"line":255,"column":60},"end":{"line":255,"column":null}},"127":{"start":{"line":256,"column":5},"end":{"line":256,"column":null}},"128":{"start":{"line":256,"column":55},"end":{"line":256,"column":75}},"129":{"start":{"line":260,"column":4},"end":{"line":260,"column":null}},"130":{"start":{"line":260,"column":43},"end":{"line":260,"column":null}},"131":{"start":{"line":261,"column":4},"end":{"line":267,"column":null}},"132":{"start":{"line":262,"column":32},"end":{"line":262,"column":null}},"133":{"start":{"line":263,"column":6},"end":{"line":266,"column":null}},"134":{"start":{"line":264,"column":8},"end":{"line":264,"column":null}},"135":{"start":{"line":265,"column":8},"end":{"line":265,"column":null}},"136":{"start":{"line":268,"column":4},"end":{"line":268,"column":null}},"137":{"start":{"line":272,"column":4},"end":{"line":272,"column":null}},"138":{"start":{"line":272,"column":73},"end":{"line":272,"column":null}},"139":{"start":{"line":273,"column":21},"end":{"line":273,"column":null}},"140":{"start":{"line":274,"column":18},"end":{"line":274,"column":null}},"141":{"start":{"line":275,"column":19},"end":{"line":275,"column":null}},"142":{"start":{"line":276,"column":4},"end":{"line":276,"column":null}},"143":{"start":{"line":277,"column":4},"end":{"line":281,"column":null}},"144":{"start":{"line":278,"column":6},"end":{"line":280,"column":null}},"145":{"start":{"line":279,"column":8},"end":{"line":279,"column":null}},"146":{"start":{"line":282,"column":4},"end":{"line":282,"column":null}},"147":{"start":{"line":292,"column":0},"end":{"line":292,"column":null}}},"fnMap":{"0":{"name":"buildCameraBounds","decl":{"start":{"line":20,"column":16},"end":{"line":20,"column":null}},"loc":{"start":{"line":26,"column":64},"end":{"line":33,"column":null}},"line":26},"1":{"name":"detectWebGL2","decl":{"start":{"line":40,"column":16},"end":{"line":40,"column":29}},"loc":{"start":{"line":40,"column":65},"end":{"line":47,"column":null}},"line":40},"2":{"name":"getLayerZIndex","decl":{"start":{"line":59,"column":16},"end":{"line":59,"column":31}},"loc":{"start":{"line":59,"column":62},"end":{"line":67,"column":null}},"line":59},"3":{"name":"(anonymous_3)","decl":{"start":{"line":104,"column":6},"end":{"line":104,"column":29}},"loc":{"start":{"line":104,"column":29},"end":{"line":106,"column":null}},"line":104},"4":{"name":"(anonymous_4)","decl":{"start":{"line":110,"column":2},"end":{"line":110,"column":18}},"loc":{"start":{"line":110,"column":18},"end":{"line":175,"column":null}},"line":110},"5":{"name":"(anonymous_5)","decl":{"start":{"line":177,"column":2},"end":{"line":177,"column":11}},"loc":{"start":{"line":177,"column":43},"end":{"line":189,"column":null}},"line":177},"6":{"name":"(anonymous_6)","decl":{"start":{"line":191,"column":2},"end":{"line":191,"column":13}},"loc":{"start":{"line":191,"column":31},"end":{"line":201,"column":null}},"line":191},"7":{"name":"(anonymous_7)","decl":{"start":{"line":199,"column":54},"end":{"line":199,"column":55}},"loc":{"start":{"line":199,"column":61},"end":{"line":199,"column":76}},"line":199},"8":{"name":"(anonymous_8)","decl":{"start":{"line":203,"column":2},"end":{"line":203,"column":13}},"loc":{"start":{"line":203,"column":49},"end":{"line":211,"column":null}},"line":203},"9":{"name":"(anonymous_9)","decl":{"start":{"line":208,"column":54},"end":{"line":208,"column":55}},"loc":{"start":{"line":208,"column":61},"end":{"line":208,"column":76}},"line":208},"10":{"name":"(anonymous_10)","decl":{"start":{"line":213,"column":2},"end":{"line":213,"column":13}},"loc":{"start":{"line":213,"column":31},"end":{"line":218,"column":null}},"line":213},"11":{"name":"(anonymous_11)","decl":{"start":{"line":220,"column":2},"end":{"line":220,"column":24}},"loc":{"start":{"line":220,"column":24},"end":{"line":227,"column":null}},"line":220},"12":{"name":"(anonymous_12)","decl":{"start":{"line":223,"column":39},"end":{"line":223,"column":45}},"loc":{"start":{"line":223,"column":45},"end":{"line":226,"column":5}},"line":223},"13":{"name":"(anonymous_13)","decl":{"start":{"line":229,"column":2},"end":{"line":229,"column":24}},"loc":{"start":{"line":229,"column":24},"end":{"line":249,"column":null}},"line":229},"14":{"name":"(anonymous_14)","decl":{"start":{"line":253,"column":10},"end":{"line":253,"column":34}},"loc":{"start":{"line":253,"column":34},"end":{"line":257,"column":null}},"line":253},"15":{"name":"(anonymous_15)","decl":{"start":{"line":256,"column":49},"end":{"line":256,"column":55}},"loc":{"start":{"line":256,"column":55},"end":{"line":256,"column":75}},"line":256},"16":{"name":"(anonymous_16)","decl":{"start":{"line":259,"column":10},"end":{"line":259,"column":32}},"loc":{"start":{"line":259,"column":32},"end":{"line":269,"column":null}},"line":259},"17":{"name":"(anonymous_17)","decl":{"start":{"line":261,"column":45},"end":{"line":261,"column":46}},"loc":{"start":{"line":261,"column":58},"end":{"line":267,"column":5}},"line":261},"18":{"name":"(anonymous_18)","decl":{"start":{"line":271,"column":10},"end":{"line":271,"column":25}},"loc":{"start":{"line":271,"column":25},"end":{"line":283,"column":null}},"line":271}},"branchMap":{"0":{"loc":{"start":{"line":41,"column":17},"end":{"line":41,"column":null}},"type":"binary-expr","locations":[{"start":{"line":41,"column":17},"end":{"line":41,"column":26}},{"start":{"line":41,"column":26},"end":{"line":41,"column":null}}],"line":41},"1":{"loc":{"start":{"line":43,"column":2},"end":{"line":43,"column":null}},"type":"if","locations":[{"start":{"line":43,"column":2},"end":{"line":43,"column":null}},{"start":{},"end":{}}],"line":43},"2":{"loc":{"start":{"line":60,"column":2},"end":{"line":60,"column":null}},"type":"if","locations":[{"start":{"line":60,"column":2},"end":{"line":60,"column":null}},{"start":{},"end":{}}],"line":60},"3":{"loc":{"start":{"line":62,"column":2},"end":{"line":62,"column":null}},"type":"if","locations":[{"start":{"line":62,"column":2},"end":{"line":62,"column":null}},{"start":{},"end":{}}],"line":62},"4":{"loc":{"start":{"line":63,"column":30},"end":{"line":63,"column":66}},"type":"binary-expr","locations":[{"start":{"line":63,"column":30},"end":{"line":63,"column":64}},{"start":{"line":63,"column":64},"end":{"line":63,"column":66}}],"line":63},"5":{"loc":{"start":{"line":66,"column":9},"end":{"line":66,"column":null}},"type":"cond-expr","locations":[{"start":{"line":66,"column":19},"end":{"line":66,"column":29}},{"start":{"line":66,"column":29},"end":{"line":66,"column":null}}],"line":66},"6":{"loc":{"start":{"line":112,"column":4},"end":{"line":112,"column":null}},"type":"if","locations":[{"start":{"line":112,"column":4},"end":{"line":112,"column":null}},{"start":{},"end":{}}],"line":112},"7":{"loc":{"start":{"line":115,"column":4},"end":{"line":120,"column":null}},"type":"if","locations":[{"start":{"line":115,"column":4},"end":{"line":120,"column":null}},{"start":{},"end":{}}],"line":115},"8":{"loc":{"start":{"line":138,"column":19},"end":{"line":138,"column":null}},"type":"binary-expr","locations":[{"start":{"line":138,"column":19},"end":{"line":138,"column":44}},{"start":{"line":138,"column":44},"end":{"line":138,"column":null}}],"line":138},"9":{"loc":{"start":{"line":139,"column":20},"end":{"line":139,"column":null}},"type":"binary-expr","locations":[{"start":{"line":139,"column":20},"end":{"line":139,"column":46}},{"start":{"line":139,"column":46},"end":{"line":139,"column":null}}],"line":139},"10":{"loc":{"start":{"line":178,"column":4},"end":{"line":182,"column":null}},"type":"if","locations":[{"start":{"line":178,"column":4},"end":{"line":182,"column":null}},{"start":{},"end":{}}],"line":178},"11":{"loc":{"start":{"line":192,"column":4},"end":{"line":192,"column":null}},"type":"if","locations":[{"start":{"line":192,"column":4},"end":{"line":192,"column":null}},{"start":{},"end":{}}],"line":192},"12":{"loc":{"start":{"line":194,"column":4},"end":{"line":194,"column":null}},"type":"if","locations":[{"start":{"line":194,"column":4},"end":{"line":194,"column":null}},{"start":{},"end":{}}],"line":194},"13":{"loc":{"start":{"line":194,"column":8},"end":{"line":194,"column":31}},"type":"binary-expr","locations":[{"start":{"line":194,"column":8},"end":{"line":194,"column":18}},{"start":{"line":194,"column":18},"end":{"line":194,"column":31}}],"line":194},"14":{"loc":{"start":{"line":200,"column":4},"end":{"line":200,"column":null}},"type":"if","locations":[{"start":{"line":200,"column":4},"end":{"line":200,"column":null}},{"start":{},"end":{}}],"line":200},"15":{"loc":{"start":{"line":200,"column":8},"end":{"line":200,"column":36}},"type":"binary-expr","locations":[{"start":{"line":200,"column":8},"end":{"line":200,"column":23}},{"start":{"line":200,"column":23},"end":{"line":200,"column":36}}],"line":200},"16":{"loc":{"start":{"line":204,"column":4},"end":{"line":204,"column":null}},"type":"if","locations":[{"start":{"line":204,"column":4},"end":{"line":204,"column":null}},{"start":{},"end":{}}],"line":204},"17":{"loc":{"start":{"line":206,"column":4},"end":{"line":206,"column":null}},"type":"if","locations":[{"start":{"line":206,"column":4},"end":{"line":206,"column":null}},{"start":{},"end":{}}],"line":206},"18":{"loc":{"start":{"line":209,"column":4},"end":{"line":209,"column":null}},"type":"if","locations":[{"start":{"line":209,"column":4},"end":{"line":209,"column":null}},{"start":{},"end":{}}],"line":209},"19":{"loc":{"start":{"line":209,"column":49},"end":{"line":209,"column":null}},"type":"cond-expr","locations":[{"start":{"line":209,"column":62},"end":{"line":209,"column":72}},{"start":{"line":209,"column":72},"end":{"line":209,"column":null}}],"line":209},"20":{"loc":{"start":{"line":210,"column":4},"end":{"line":210,"column":null}},"type":"if","locations":[{"start":{"line":210,"column":4},"end":{"line":210,"column":null}},{"start":{},"end":{}}],"line":210},"21":{"loc":{"start":{"line":214,"column":4},"end":{"line":214,"column":null}},"type":"if","locations":[{"start":{"line":214,"column":4},"end":{"line":214,"column":null}},{"start":{},"end":{}}],"line":214},"22":{"loc":{"start":{"line":216,"column":4},"end":{"line":216,"column":null}},"type":"if","locations":[{"start":{"line":216,"column":4},"end":{"line":216,"column":null}},{"start":{},"end":{}}],"line":216},"23":{"loc":{"start":{"line":221,"column":4},"end":{"line":221,"column":null}},"type":"if","locations":[{"start":{"line":221,"column":4},"end":{"line":221,"column":null}},{"start":{},"end":{}}],"line":221},"24":{"loc":{"start":{"line":222,"column":4},"end":{"line":222,"column":null}},"type":"if","locations":[{"start":{"line":222,"column":4},"end":{"line":222,"column":null}},{"start":{},"end":{}}],"line":222},"25":{"loc":{"start":{"line":230,"column":4},"end":{"line":230,"column":null}},"type":"if","locations":[{"start":{"line":230,"column":4},"end":{"line":230,"column":null}},{"start":{},"end":{}}],"line":230},"26":{"loc":{"start":{"line":230,"column":8},"end":{"line":230,"column":40}},"type":"binary-expr","locations":[{"start":{"line":230,"column":8},"end":{"line":230,"column":26}},{"start":{"line":230,"column":26},"end":{"line":230,"column":40}}],"line":230},"27":{"loc":{"start":{"line":232,"column":19},"end":{"line":232,"column":null}},"type":"binary-expr","locations":[{"start":{"line":232,"column":19},"end":{"line":232,"column":47}},{"start":{"line":232,"column":47},"end":{"line":232,"column":null}}],"line":232},"28":{"loc":{"start":{"line":233,"column":19},"end":{"line":233,"column":null}},"type":"binary-expr","locations":[{"start":{"line":233,"column":19},"end":{"line":233,"column":47}},{"start":{"line":233,"column":47},"end":{"line":233,"column":null}}],"line":233},"29":{"loc":{"start":{"line":234,"column":19},"end":{"line":234,"column":null}},"type":"binary-expr","locations":[{"start":{"line":234,"column":19},"end":{"line":234,"column":47}},{"start":{"line":234,"column":47},"end":{"line":234,"column":null}}],"line":234},"30":{"loc":{"start":{"line":235,"column":24},"end":{"line":235,"column":null}},"type":"binary-expr","locations":[{"start":{"line":235,"column":24},"end":{"line":235,"column":57}},{"start":{"line":235,"column":57},"end":{"line":235,"column":null}}],"line":235},"31":{"loc":{"start":{"line":236,"column":25},"end":{"line":236,"column":null}},"type":"binary-expr","locations":[{"start":{"line":236,"column":25},"end":{"line":236,"column":59}},{"start":{"line":236,"column":59},"end":{"line":236,"column":null}}],"line":236},"32":{"loc":{"start":{"line":255,"column":4},"end":{"line":255,"column":null}},"type":"if","locations":[{"start":{"line":255,"column":4},"end":{"line":255,"column":null}},{"start":{},"end":{}}],"line":255},"33":{"loc":{"start":{"line":260,"column":4},"end":{"line":260,"column":null}},"type":"if","locations":[{"start":{"line":260,"column":4},"end":{"line":260,"column":null}},{"start":{},"end":{}}],"line":260},"34":{"loc":{"start":{"line":260,"column":8},"end":{"line":260,"column":43}},"type":"binary-expr","locations":[{"start":{"line":260,"column":8},"end":{"line":260,"column":27}},{"start":{"line":260,"column":27},"end":{"line":260,"column":43}}],"line":260},"35":{"loc":{"start":{"line":263,"column":6},"end":{"line":266,"column":null}},"type":"if","locations":[{"start":{"line":263,"column":6},"end":{"line":266,"column":null}},{"start":{},"end":{}}],"line":263},"36":{"loc":{"start":{"line":263,"column":10},"end":{"line":263,"column":40}},"type":"binary-expr","locations":[{"start":{"line":263,"column":10},"end":{"line":263,"column":27}},{"start":{"line":263,"column":27},"end":{"line":263,"column":40}}],"line":263},"37":{"loc":{"start":{"line":272,"column":4},"end":{"line":272,"column":null}},"type":"if","locations":[{"start":{"line":272,"column":4},"end":{"line":272,"column":null}},{"start":{},"end":{}}],"line":272},"38":{"loc":{"start":{"line":272,"column":8},"end":{"line":272,"column":73}},"type":"binary-expr","locations":[{"start":{"line":272,"column":8},"end":{"line":272,"column":26}},{"start":{"line":272,"column":26},"end":{"line":272,"column":44}},{"start":{"line":272,"column":44},"end":{"line":272,"column":59}},{"start":{"line":272,"column":59},"end":{"line":272,"column":73}}],"line":272},"39":{"loc":{"start":{"line":278,"column":6},"end":{"line":280,"column":null}},"type":"if","locations":[{"start":{"line":278,"column":6},"end":{"line":280,"column":null}},{"start":{},"end":{}}],"line":278}},"s":{"0":11,"1":8,"2":8,"3":8,"4":2,"5":6,"6":6,"7":8,"8":4,"9":1,"10":3,"11":3,"12":3,"13":0,"14":4,"15":4,"16":26,"17":26,"18":26,"19":26,"20":26,"21":26,"22":26,"23":26,"24":26,"25":26,"26":2,"27":5,"28":5,"29":1,"30":4,"31":4,"32":1,"33":1,"34":3,"35":3,"36":3,"37":3,"38":3,"39":3,"40":3,"41":3,"42":3,"43":3,"44":3,"45":3,"46":3,"47":3,"48":5,"49":5,"50":5,"51":5,"52":5,"53":5,"54":5,"55":5,"56":5,"57":1,"58":1,"59":1,"60":1,"61":1,"62":3,"63":3,"64":3,"65":4,"66":4,"67":4,"68":0,"69":0,"70":0,"71":0,"72":0,"73":2,"74":0,"75":2,"76":2,"77":0,"78":2,"79":2,"80":2,"81":2,"82":2,"83":0,"84":2,"85":2,"86":4,"87":0,"88":4,"89":4,"90":0,"91":4,"92":4,"93":5,"94":4,"95":4,"96":4,"97":1,"98":3,"99":0,"100":3,"101":3,"102":0,"103":3,"104":10,"105":0,"106":10,"107":4,"108":6,"109":3,"110":3,"111":3,"112":0,"113":3,"114":3,"115":3,"116":3,"117":3,"118":3,"119":3,"120":3,"121":3,"122":3,"123":3,"124":3,"125":3,"126":3,"127":0,"128":0,"129":3,"130":0,"131":3,"132":0,"133":0,"134":0,"135":0,"136":3,"137":3,"138":1,"139":2,"140":2,"141":2,"142":2,"143":2,"144":2,"145":1,"146":2,"147":1},"f":{"0":11,"1":8,"2":4,"3":2,"4":5,"5":4,"6":2,"7":0,"8":4,"9":5,"10":3,"11":10,"12":3,"13":3,"14":3,"15":0,"16":3,"17":0,"18":3},"b":{"0":[8,5],"1":[2,6],"2":[1,3],"3":[3,0],"4":[0,0],"5":[0,0],"6":[1,4],"7":[1,3],"8":[3,0],"9":[5,0],"10":[4,0],"11":[0,2],"12":[0,2],"13":[2,2],"14":[2,0],"15":[2,2],"16":[0,4],"17":[0,4],"18":[4,0],"19":[1,3],"20":[1,3],"21":[0,3],"22":[0,3],"23":[0,10],"24":[4,6],"25":[0,3],"26":[3,3],"27":[3,2],"28":[3,2],"29":[3,2],"30":[3,2],"31":[3,2],"32":[3,0],"33":[0,3],"34":[3,3],"35":[0,0],"36":[0,0],"37":[1,2],"38":[3,3,2,2],"39":[1,1]},"meta":{"lastBranch":40,"lastFunction":19,"lastStatement":148,"seen":{"f:20:16:20:Infinity":0,"s:27:2:32:Infinity":0,"f:40:16:40:29":1,"s:41:17:41:Infinity":1,"b:41:17:41:26:41:26:41:Infinity":0,"s:42:14:42:Infinity":2,"b:43:2:43:Infinity:undefined:undefined:undefined:undefined":1,"s:43:2:43:Infinity":3,"s:43:12:43:Infinity":4,"s:44:14:44:Infinity":5,"s:45:2:45:Infinity":6,"s:46:2:46:Infinity":7,"f:59:16:59:31":2,"b:60:2:60:Infinity:undefined:undefined:undefined:undefined":2,"s:60:2:60:Infinity":8,"s:60:39:60:Infinity":9,"s:61:17:61:Infinity":10,"b:62:2:62:Infinity:undefined:undefined:undefined:undefined":3,"s:62:2:62:Infinity":11,"s:62:15:62:Infinity":12,"s:63:19:63:Infinity":13,"b:63:30:63:64:63:64:63:66":4,"s:64:14:64:Infinity":14,"s:66:2:66:Infinity":15,"b:66:19:66:29:66:29:66:Infinity":5,"s:89:45:89:Infinity":16,"s:90:43:90:Infinity":17,"s:91:46:91:Infinity":18,"s:92:32:92:Infinity":19,"s:93:49:93:Infinity":20,"s:94:47:94:Infinity":21,"s:95:50:95:Infinity":22,"s:96:33:96:Infinity":23,"s:97:42:97:Infinity":24,"s:102:22:102:Infinity":25,"f:104:6:104:29":3,"s:105:4:105:Infinity":26,"f:110:2:110:18":4,"s:111:4:111:Infinity":27,"b:112:4:112:Infinity:undefined:undefined:undefined:undefined":6,"s:112:4:112:Infinity":28,"s:112:24:112:Infinity":29,"s:114:18:114:Infinity":30,"b:115:4:120:Infinity:undefined:undefined:undefined:undefined":7,"s:115:4:120:Infinity":31,"s:116:6:118:Infinity":32,"s:119:6:119:Infinity":33,"s:123:22:123:Infinity":34,"s:124:4:124:Infinity":35,"s:125:4:125:Infinity":36,"s:126:4:126:Infinity":37,"s:127:4:127:Infinity":38,"s:128:4:128:Infinity":39,"s:131:19:131:Infinity":40,"s:132:4:132:Infinity":41,"s:133:4:133:Infinity":42,"s:134:4:134:Infinity":43,"s:135:4:135:Infinity":44,"s:136:4:136:Infinity":45,"s:137:4:137:Infinity":46,"s:138:4:138:Infinity":47,"b:138:19:138:44:138:44:138:Infinity":8,"s:139:4:139:Infinity":48,"b:139:20:139:46:139:46:139:Infinity":9,"s:140:4:140:Infinity":49,"s:141:4:141:Infinity":50,"s:144:4:148:Infinity":51,"s:149:4:149:Infinity":52,"s:150:4:150:Infinity":53,"s:151:4:158:Infinity":54,"s:160:4:160:Infinity":55,"s:163:4:169:Infinity":56,"s:164:20:164:Infinity":57,"s:165:6:165:Infinity":58,"s:166:6:166:Infinity":59,"s:167:6:167:Infinity":60,"s:168:6:168:Infinity":61,"s:170:4:170:Infinity":62,"s:172:4:172:Infinity":63,"s:174:4:174:Infinity":64,"f:177:2:177:11":5,"b:178:4:182:Infinity:undefined:undefined:undefined:undefined":10,"s:178:4:182:Infinity":65,"s:180:6:180:Infinity":66,"s:181:6:181:Infinity":67,"s:184:18:184:Infinity":68,"s:185:4:185:Infinity":69,"s:186:4:186:Infinity":70,"s:187:4:187:Infinity":71,"s:188:4:188:Infinity":72,"f:191:2:191:13":6,"b:192:4:192:Infinity:undefined:undefined:undefined:undefined":11,"s:192:4:192:Infinity":73,"s:192:24:192:Infinity":74,"s:193:18:193:Infinity":75,"b:194:4:194:Infinity:undefined:undefined:undefined:undefined":12,"s:194:4:194:Infinity":76,"b:194:8:194:18:194:18:194:31":13,"s:194:31:194:Infinity":77,"s:195:18:195:Infinity":78,"s:196:4:196:Infinity":79,"s:197:4:197:Infinity":80,"s:198:4:198:Infinity":81,"s:199:23:199:Infinity":82,"f:199:54:199:55":7,"s:199:61:199:76":83,"b:200:4:200:Infinity:undefined:undefined:undefined:undefined":14,"s:200:4:200:Infinity":84,"b:200:8:200:23:200:23:200:36":15,"s:200:36:200:Infinity":85,"f:203:2:203:13":8,"b:204:4:204:Infinity:undefined:undefined:undefined:undefined":16,"s:204:4:204:Infinity":86,"s:204:24:204:Infinity":87,"s:205:18:205:Infinity":88,"b:206:4:206:Infinity:undefined:undefined:undefined:undefined":17,"s:206:4:206:Infinity":89,"s:206:16:206:Infinity":90,"s:207:4:207:Infinity":91,"s:208:23:208:Infinity":92,"f:208:54:208:55":9,"s:208:61:208:76":93,"b:209:4:209:Infinity:undefined:undefined:undefined:undefined":18,"s:209:4:209:Infinity":94,"s:209:21:209:Infinity":95,"b:209:62:209:72:209:72:209:Infinity":19,"b:210:4:210:Infinity:undefined:undefined:undefined:undefined":20,"s:210:4:210:Infinity":96,"s:210:17:210:Infinity":97,"f:213:2:213:13":10,"b:214:4:214:Infinity:undefined:undefined:undefined:undefined":21,"s:214:4:214:Infinity":98,"s:214:24:214:Infinity":99,"s:215:18:215:Infinity":100,"b:216:4:216:Infinity:undefined:undefined:undefined:undefined":22,"s:216:4:216:Infinity":101,"s:216:16:216:Infinity":102,"s:217:4:217:Infinity":103,"f:220:2:220:24":11,"b:221:4:221:Infinity:undefined:undefined:undefined:undefined":23,"s:221:4:221:Infinity":104,"s:221:24:221:Infinity":105,"b:222:4:222:Infinity:undefined:undefined:undefined:undefined":24,"s:222:4:222:Infinity":106,"s:222:29:222:Infinity":107,"s:223:4:226:Infinity":108,"f:223:39:223:45":12,"s:224:6:224:Infinity":109,"s:225:6:225:Infinity":110,"f:229:2:229:24":13,"b:230:4:230:Infinity:undefined:undefined:undefined:undefined":25,"s:230:4:230:Infinity":111,"b:230:8:230:26:230:26:230:40":26,"s:230:40:230:Infinity":112,"s:231:19:231:Infinity":113,"s:232:19:232:Infinity":114,"b:232:19:232:47:232:47:232:Infinity":27,"s:233:19:233:Infinity":115,"b:233:19:233:47:233:47:233:Infinity":28,"s:234:19:234:Infinity":116,"b:234:19:234:47:234:47:234:Infinity":29,"s:235:24:235:Infinity":117,"b:235:24:235:57:235:57:235:Infinity":30,"s:236:25:236:Infinity":118,"b:236:25:236:59:236:59:236:Infinity":31,"s:237:19:243:Infinity":119,"s:244:4:244:Infinity":120,"s:245:4:245:Infinity":121,"s:246:4:246:Infinity":122,"s:247:4:247:Infinity":123,"s:248:4:248:Infinity":124,"f:253:10:253:34":14,"b:255:4:255:Infinity:undefined:undefined:undefined:undefined":32,"s:255:4:255:Infinity":125,"s:255:60:255:Infinity":126,"s:256:5:256:Infinity":127,"f:256:49:256:55":15,"s:256:55:256:75":128,"f:259:10:259:32":16,"b:260:4:260:Infinity:undefined:undefined:undefined:undefined":33,"s:260:4:260:Infinity":129,"b:260:8:260:27:260:27:260:43":34,"s:260:43:260:Infinity":130,"s:261:4:267:Infinity":131,"f:261:45:261:46":17,"s:262:32:262:Infinity":132,"b:263:6:266:Infinity:undefined:undefined:undefined:undefined":35,"s:263:6:266:Infinity":133,"b:263:10:263:27:263:27:263:40":36,"s:264:8:264:Infinity":134,"s:265:8:265:Infinity":135,"s:268:4:268:Infinity":136,"f:271:10:271:25":18,"b:272:4:272:Infinity:undefined:undefined:undefined:undefined":37,"s:272:4:272:Infinity":137,"b:272:8:272:26:272:26:272:44:272:44:272:59:272:59:272:73":38,"s:272:73:272:Infinity":138,"s:273:21:273:Infinity":139,"s:274:18:274:Infinity":140,"s:275:19:275:Infinity":141,"s:276:4:276:Infinity":142,"s:277:4:281:Infinity":143,"b:278:6:280:Infinity:undefined:undefined:undefined:undefined":39,"s:278:6:280:Infinity":144,"s:279:8:279:Infinity":145,"s:282:4:282:Infinity":146,"s:292:0:292:Infinity":147}}} +{"/Users/azgaar/Fantasy-Map-Generator/src/modules/webgl-layer-framework.ts": {"path":"/Users/azgaar/Fantasy-Map-Generator/src/modules/webgl-layer-framework.ts","statementMap":{"0":{"start":{"line":25,"column":2},"end":{"line":30,"column":null}},"1":{"start":{"line":39,"column":17},"end":{"line":39,"column":null}},"2":{"start":{"line":40,"column":14},"end":{"line":40,"column":null}},"3":{"start":{"line":41,"column":2},"end":{"line":41,"column":null}},"4":{"start":{"line":41,"column":12},"end":{"line":41,"column":null}},"5":{"start":{"line":42,"column":14},"end":{"line":42,"column":null}},"6":{"start":{"line":43,"column":2},"end":{"line":43,"column":null}},"7":{"start":{"line":44,"column":2},"end":{"line":44,"column":null}},"8":{"start":{"line":58,"column":2},"end":{"line":58,"column":null}},"9":{"start":{"line":58,"column":39},"end":{"line":58,"column":null}},"10":{"start":{"line":59,"column":17},"end":{"line":59,"column":null}},"11":{"start":{"line":60,"column":2},"end":{"line":60,"column":null}},"12":{"start":{"line":60,"column":15},"end":{"line":60,"column":null}},"13":{"start":{"line":61,"column":19},"end":{"line":61,"column":null}},"14":{"start":{"line":62,"column":14},"end":{"line":62,"column":null}},"15":{"start":{"line":64,"column":2},"end":{"line":64,"column":null}},"16":{"start":{"line":85,"column":45},"end":{"line":85,"column":null}},"17":{"start":{"line":86,"column":43},"end":{"line":86,"column":null}},"18":{"start":{"line":87,"column":46},"end":{"line":87,"column":null}},"19":{"start":{"line":88,"column":32},"end":{"line":88,"column":null}},"20":{"start":{"line":89,"column":49},"end":{"line":89,"column":null}},"21":{"start":{"line":90,"column":47},"end":{"line":90,"column":null}},"22":{"start":{"line":91,"column":50},"end":{"line":91,"column":null}},"23":{"start":{"line":92,"column":33},"end":{"line":92,"column":null}},"24":{"start":{"line":93,"column":42},"end":{"line":93,"column":null}},"25":{"start":{"line":94,"column":22},"end":{"line":94,"column":null}},"26":{"start":{"line":97,"column":4},"end":{"line":97,"column":null}},"27":{"start":{"line":101,"column":4},"end":{"line":101,"column":null}},"28":{"start":{"line":102,"column":4},"end":{"line":102,"column":null}},"29":{"start":{"line":102,"column":24},"end":{"line":102,"column":null}},"30":{"start":{"line":104,"column":18},"end":{"line":104,"column":null}},"31":{"start":{"line":105,"column":4},"end":{"line":110,"column":null}},"32":{"start":{"line":106,"column":6},"end":{"line":108,"column":null}},"33":{"start":{"line":109,"column":6},"end":{"line":109,"column":null}},"34":{"start":{"line":113,"column":22},"end":{"line":113,"column":null}},"35":{"start":{"line":114,"column":4},"end":{"line":114,"column":null}},"36":{"start":{"line":115,"column":4},"end":{"line":115,"column":null}},"37":{"start":{"line":116,"column":4},"end":{"line":116,"column":null}},"38":{"start":{"line":117,"column":4},"end":{"line":117,"column":null}},"39":{"start":{"line":118,"column":4},"end":{"line":118,"column":null}},"40":{"start":{"line":121,"column":19},"end":{"line":121,"column":null}},"41":{"start":{"line":122,"column":4},"end":{"line":122,"column":null}},"42":{"start":{"line":123,"column":4},"end":{"line":123,"column":null}},"43":{"start":{"line":124,"column":4},"end":{"line":124,"column":null}},"44":{"start":{"line":125,"column":4},"end":{"line":125,"column":null}},"45":{"start":{"line":126,"column":4},"end":{"line":126,"column":null}},"46":{"start":{"line":127,"column":4},"end":{"line":127,"column":null}},"47":{"start":{"line":128,"column":4},"end":{"line":128,"column":null}},"48":{"start":{"line":129,"column":4},"end":{"line":129,"column":null}},"49":{"start":{"line":130,"column":4},"end":{"line":130,"column":null}},"50":{"start":{"line":131,"column":4},"end":{"line":131,"column":null}},"51":{"start":{"line":134,"column":4},"end":{"line":138,"column":null}},"52":{"start":{"line":139,"column":4},"end":{"line":139,"column":null}},"53":{"start":{"line":140,"column":4},"end":{"line":140,"column":null}},"54":{"start":{"line":141,"column":4},"end":{"line":148,"column":null}},"55":{"start":{"line":150,"column":4},"end":{"line":150,"column":null}},"56":{"start":{"line":153,"column":4},"end":{"line":159,"column":null}},"57":{"start":{"line":154,"column":20},"end":{"line":154,"column":null}},"58":{"start":{"line":155,"column":6},"end":{"line":155,"column":null}},"59":{"start":{"line":156,"column":6},"end":{"line":156,"column":null}},"60":{"start":{"line":157,"column":6},"end":{"line":157,"column":null}},"61":{"start":{"line":158,"column":6},"end":{"line":158,"column":null}},"62":{"start":{"line":160,"column":4},"end":{"line":160,"column":null}},"63":{"start":{"line":161,"column":4},"end":{"line":161,"column":null}},"64":{"start":{"line":163,"column":4},"end":{"line":163,"column":null}},"65":{"start":{"line":167,"column":4},"end":{"line":171,"column":null}},"66":{"start":{"line":169,"column":6},"end":{"line":169,"column":null}},"67":{"start":{"line":170,"column":6},"end":{"line":170,"column":null}},"68":{"start":{"line":173,"column":18},"end":{"line":173,"column":null}},"69":{"start":{"line":174,"column":4},"end":{"line":174,"column":null}},"70":{"start":{"line":175,"column":4},"end":{"line":175,"column":null}},"71":{"start":{"line":176,"column":4},"end":{"line":176,"column":null}},"72":{"start":{"line":177,"column":4},"end":{"line":177,"column":null}},"73":{"start":{"line":181,"column":4},"end":{"line":181,"column":null}},"74":{"start":{"line":181,"column":24},"end":{"line":181,"column":null}},"75":{"start":{"line":182,"column":18},"end":{"line":182,"column":null}},"76":{"start":{"line":183,"column":4},"end":{"line":183,"column":null}},"77":{"start":{"line":183,"column":31},"end":{"line":183,"column":null}},"78":{"start":{"line":184,"column":18},"end":{"line":184,"column":null}},"79":{"start":{"line":185,"column":4},"end":{"line":185,"column":null}},"80":{"start":{"line":186,"column":4},"end":{"line":186,"column":null}},"81":{"start":{"line":187,"column":4},"end":{"line":187,"column":null}},"82":{"start":{"line":188,"column":23},"end":{"line":188,"column":null}},"83":{"start":{"line":188,"column":61},"end":{"line":188,"column":76}},"84":{"start":{"line":189,"column":4},"end":{"line":189,"column":null}},"85":{"start":{"line":189,"column":36},"end":{"line":189,"column":null}},"86":{"start":{"line":193,"column":4},"end":{"line":193,"column":null}},"87":{"start":{"line":193,"column":24},"end":{"line":193,"column":null}},"88":{"start":{"line":194,"column":18},"end":{"line":194,"column":null}},"89":{"start":{"line":195,"column":4},"end":{"line":195,"column":null}},"90":{"start":{"line":195,"column":16},"end":{"line":195,"column":null}},"91":{"start":{"line":196,"column":4},"end":{"line":196,"column":null}},"92":{"start":{"line":197,"column":23},"end":{"line":197,"column":null}},"93":{"start":{"line":197,"column":61},"end":{"line":197,"column":76}},"94":{"start":{"line":198,"column":4},"end":{"line":198,"column":null}},"95":{"start":{"line":198,"column":21},"end":{"line":198,"column":null}},"96":{"start":{"line":199,"column":4},"end":{"line":199,"column":null}},"97":{"start":{"line":199,"column":17},"end":{"line":199,"column":null}},"98":{"start":{"line":203,"column":4},"end":{"line":203,"column":null}},"99":{"start":{"line":203,"column":24},"end":{"line":203,"column":null}},"100":{"start":{"line":204,"column":18},"end":{"line":204,"column":null}},"101":{"start":{"line":205,"column":4},"end":{"line":205,"column":null}},"102":{"start":{"line":205,"column":16},"end":{"line":205,"column":null}},"103":{"start":{"line":206,"column":4},"end":{"line":206,"column":null}},"104":{"start":{"line":210,"column":4},"end":{"line":210,"column":null}},"105":{"start":{"line":210,"column":24},"end":{"line":210,"column":null}},"106":{"start":{"line":211,"column":4},"end":{"line":211,"column":null}},"107":{"start":{"line":211,"column":29},"end":{"line":211,"column":null}},"108":{"start":{"line":212,"column":4},"end":{"line":215,"column":null}},"109":{"start":{"line":213,"column":6},"end":{"line":213,"column":null}},"110":{"start":{"line":214,"column":6},"end":{"line":214,"column":null}},"111":{"start":{"line":219,"column":4},"end":{"line":219,"column":null}},"112":{"start":{"line":219,"column":40},"end":{"line":219,"column":null}},"113":{"start":{"line":220,"column":19},"end":{"line":220,"column":null}},"114":{"start":{"line":221,"column":19},"end":{"line":221,"column":null}},"115":{"start":{"line":222,"column":19},"end":{"line":222,"column":null}},"116":{"start":{"line":223,"column":19},"end":{"line":223,"column":null}},"117":{"start":{"line":224,"column":24},"end":{"line":224,"column":null}},"118":{"start":{"line":225,"column":25},"end":{"line":225,"column":null}},"119":{"start":{"line":226,"column":19},"end":{"line":232,"column":null}},"120":{"start":{"line":233,"column":4},"end":{"line":233,"column":null}},"121":{"start":{"line":234,"column":4},"end":{"line":234,"column":null}},"122":{"start":{"line":235,"column":4},"end":{"line":235,"column":null}},"123":{"start":{"line":236,"column":4},"end":{"line":236,"column":null}},"124":{"start":{"line":237,"column":4},"end":{"line":237,"column":null}},"125":{"start":{"line":242,"column":4},"end":{"line":242,"column":null}},"126":{"start":{"line":242,"column":60},"end":{"line":242,"column":null}},"127":{"start":{"line":243,"column":5},"end":{"line":243,"column":null}},"128":{"start":{"line":243,"column":55},"end":{"line":243,"column":75}},"129":{"start":{"line":247,"column":4},"end":{"line":247,"column":null}},"130":{"start":{"line":247,"column":43},"end":{"line":247,"column":null}},"131":{"start":{"line":248,"column":4},"end":{"line":254,"column":null}},"132":{"start":{"line":249,"column":32},"end":{"line":249,"column":null}},"133":{"start":{"line":250,"column":6},"end":{"line":253,"column":null}},"134":{"start":{"line":251,"column":8},"end":{"line":251,"column":null}},"135":{"start":{"line":252,"column":8},"end":{"line":252,"column":null}},"136":{"start":{"line":255,"column":4},"end":{"line":255,"column":null}},"137":{"start":{"line":259,"column":4},"end":{"line":259,"column":null}},"138":{"start":{"line":259,"column":73},"end":{"line":259,"column":null}},"139":{"start":{"line":260,"column":21},"end":{"line":260,"column":null}},"140":{"start":{"line":261,"column":18},"end":{"line":261,"column":null}},"141":{"start":{"line":262,"column":19},"end":{"line":262,"column":null}},"142":{"start":{"line":263,"column":4},"end":{"line":263,"column":null}},"143":{"start":{"line":264,"column":4},"end":{"line":268,"column":null}},"144":{"start":{"line":265,"column":6},"end":{"line":267,"column":null}},"145":{"start":{"line":266,"column":8},"end":{"line":266,"column":null}},"146":{"start":{"line":269,"column":4},"end":{"line":269,"column":null}},"147":{"start":{"line":276,"column":0},"end":{"line":276,"column":null}}},"fnMap":{"0":{"name":"buildCameraBounds","decl":{"start":{"line":18,"column":16},"end":{"line":18,"column":null}},"loc":{"start":{"line":24,"column":64},"end":{"line":31,"column":null}},"line":24},"1":{"name":"detectWebGL2","decl":{"start":{"line":38,"column":16},"end":{"line":38,"column":29}},"loc":{"start":{"line":38,"column":65},"end":{"line":45,"column":null}},"line":38},"2":{"name":"getLayerZIndex","decl":{"start":{"line":57,"column":16},"end":{"line":57,"column":31}},"loc":{"start":{"line":57,"column":62},"end":{"line":65,"column":null}},"line":57},"3":{"name":"(anonymous_3)","decl":{"start":{"line":96,"column":6},"end":{"line":96,"column":29}},"loc":{"start":{"line":96,"column":29},"end":{"line":98,"column":null}},"line":96},"4":{"name":"(anonymous_4)","decl":{"start":{"line":100,"column":2},"end":{"line":100,"column":18}},"loc":{"start":{"line":100,"column":18},"end":{"line":164,"column":null}},"line":100},"5":{"name":"(anonymous_5)","decl":{"start":{"line":166,"column":2},"end":{"line":166,"column":11}},"loc":{"start":{"line":166,"column":43},"end":{"line":178,"column":null}},"line":166},"6":{"name":"(anonymous_6)","decl":{"start":{"line":180,"column":2},"end":{"line":180,"column":13}},"loc":{"start":{"line":180,"column":31},"end":{"line":190,"column":null}},"line":180},"7":{"name":"(anonymous_7)","decl":{"start":{"line":188,"column":54},"end":{"line":188,"column":55}},"loc":{"start":{"line":188,"column":61},"end":{"line":188,"column":76}},"line":188},"8":{"name":"(anonymous_8)","decl":{"start":{"line":192,"column":2},"end":{"line":192,"column":13}},"loc":{"start":{"line":192,"column":49},"end":{"line":200,"column":null}},"line":192},"9":{"name":"(anonymous_9)","decl":{"start":{"line":197,"column":54},"end":{"line":197,"column":55}},"loc":{"start":{"line":197,"column":61},"end":{"line":197,"column":76}},"line":197},"10":{"name":"(anonymous_10)","decl":{"start":{"line":202,"column":2},"end":{"line":202,"column":13}},"loc":{"start":{"line":202,"column":31},"end":{"line":207,"column":null}},"line":202},"11":{"name":"(anonymous_11)","decl":{"start":{"line":209,"column":2},"end":{"line":209,"column":24}},"loc":{"start":{"line":209,"column":24},"end":{"line":216,"column":null}},"line":209},"12":{"name":"(anonymous_12)","decl":{"start":{"line":212,"column":39},"end":{"line":212,"column":45}},"loc":{"start":{"line":212,"column":45},"end":{"line":215,"column":5}},"line":212},"13":{"name":"(anonymous_13)","decl":{"start":{"line":218,"column":2},"end":{"line":218,"column":24}},"loc":{"start":{"line":218,"column":24},"end":{"line":238,"column":null}},"line":218},"14":{"name":"(anonymous_14)","decl":{"start":{"line":240,"column":10},"end":{"line":240,"column":34}},"loc":{"start":{"line":240,"column":34},"end":{"line":244,"column":null}},"line":240},"15":{"name":"(anonymous_15)","decl":{"start":{"line":243,"column":49},"end":{"line":243,"column":55}},"loc":{"start":{"line":243,"column":55},"end":{"line":243,"column":75}},"line":243},"16":{"name":"(anonymous_16)","decl":{"start":{"line":246,"column":10},"end":{"line":246,"column":32}},"loc":{"start":{"line":246,"column":32},"end":{"line":256,"column":null}},"line":246},"17":{"name":"(anonymous_17)","decl":{"start":{"line":248,"column":45},"end":{"line":248,"column":46}},"loc":{"start":{"line":248,"column":58},"end":{"line":254,"column":5}},"line":248},"18":{"name":"(anonymous_18)","decl":{"start":{"line":258,"column":10},"end":{"line":258,"column":25}},"loc":{"start":{"line":258,"column":25},"end":{"line":270,"column":null}},"line":258}},"branchMap":{"0":{"loc":{"start":{"line":39,"column":17},"end":{"line":39,"column":null}},"type":"binary-expr","locations":[{"start":{"line":39,"column":17},"end":{"line":39,"column":26}},{"start":{"line":39,"column":26},"end":{"line":39,"column":null}}],"line":39},"1":{"loc":{"start":{"line":41,"column":2},"end":{"line":41,"column":null}},"type":"if","locations":[{"start":{"line":41,"column":2},"end":{"line":41,"column":null}},{"start":{},"end":{}}],"line":41},"2":{"loc":{"start":{"line":58,"column":2},"end":{"line":58,"column":null}},"type":"if","locations":[{"start":{"line":58,"column":2},"end":{"line":58,"column":null}},{"start":{},"end":{}}],"line":58},"3":{"loc":{"start":{"line":60,"column":2},"end":{"line":60,"column":null}},"type":"if","locations":[{"start":{"line":60,"column":2},"end":{"line":60,"column":null}},{"start":{},"end":{}}],"line":60},"4":{"loc":{"start":{"line":61,"column":30},"end":{"line":61,"column":66}},"type":"binary-expr","locations":[{"start":{"line":61,"column":30},"end":{"line":61,"column":64}},{"start":{"line":61,"column":64},"end":{"line":61,"column":66}}],"line":61},"5":{"loc":{"start":{"line":64,"column":9},"end":{"line":64,"column":null}},"type":"cond-expr","locations":[{"start":{"line":64,"column":19},"end":{"line":64,"column":29}},{"start":{"line":64,"column":29},"end":{"line":64,"column":null}}],"line":64},"6":{"loc":{"start":{"line":102,"column":4},"end":{"line":102,"column":null}},"type":"if","locations":[{"start":{"line":102,"column":4},"end":{"line":102,"column":null}},{"start":{},"end":{}}],"line":102},"7":{"loc":{"start":{"line":105,"column":4},"end":{"line":110,"column":null}},"type":"if","locations":[{"start":{"line":105,"column":4},"end":{"line":110,"column":null}},{"start":{},"end":{}}],"line":105},"8":{"loc":{"start":{"line":128,"column":19},"end":{"line":128,"column":null}},"type":"binary-expr","locations":[{"start":{"line":128,"column":19},"end":{"line":128,"column":44}},{"start":{"line":128,"column":44},"end":{"line":128,"column":null}}],"line":128},"9":{"loc":{"start":{"line":129,"column":20},"end":{"line":129,"column":null}},"type":"binary-expr","locations":[{"start":{"line":129,"column":20},"end":{"line":129,"column":46}},{"start":{"line":129,"column":46},"end":{"line":129,"column":null}}],"line":129},"10":{"loc":{"start":{"line":167,"column":4},"end":{"line":171,"column":null}},"type":"if","locations":[{"start":{"line":167,"column":4},"end":{"line":171,"column":null}},{"start":{},"end":{}}],"line":167},"11":{"loc":{"start":{"line":181,"column":4},"end":{"line":181,"column":null}},"type":"if","locations":[{"start":{"line":181,"column":4},"end":{"line":181,"column":null}},{"start":{},"end":{}}],"line":181},"12":{"loc":{"start":{"line":183,"column":4},"end":{"line":183,"column":null}},"type":"if","locations":[{"start":{"line":183,"column":4},"end":{"line":183,"column":null}},{"start":{},"end":{}}],"line":183},"13":{"loc":{"start":{"line":183,"column":8},"end":{"line":183,"column":31}},"type":"binary-expr","locations":[{"start":{"line":183,"column":8},"end":{"line":183,"column":18}},{"start":{"line":183,"column":18},"end":{"line":183,"column":31}}],"line":183},"14":{"loc":{"start":{"line":189,"column":4},"end":{"line":189,"column":null}},"type":"if","locations":[{"start":{"line":189,"column":4},"end":{"line":189,"column":null}},{"start":{},"end":{}}],"line":189},"15":{"loc":{"start":{"line":189,"column":8},"end":{"line":189,"column":36}},"type":"binary-expr","locations":[{"start":{"line":189,"column":8},"end":{"line":189,"column":23}},{"start":{"line":189,"column":23},"end":{"line":189,"column":36}}],"line":189},"16":{"loc":{"start":{"line":193,"column":4},"end":{"line":193,"column":null}},"type":"if","locations":[{"start":{"line":193,"column":4},"end":{"line":193,"column":null}},{"start":{},"end":{}}],"line":193},"17":{"loc":{"start":{"line":195,"column":4},"end":{"line":195,"column":null}},"type":"if","locations":[{"start":{"line":195,"column":4},"end":{"line":195,"column":null}},{"start":{},"end":{}}],"line":195},"18":{"loc":{"start":{"line":198,"column":4},"end":{"line":198,"column":null}},"type":"if","locations":[{"start":{"line":198,"column":4},"end":{"line":198,"column":null}},{"start":{},"end":{}}],"line":198},"19":{"loc":{"start":{"line":198,"column":49},"end":{"line":198,"column":null}},"type":"cond-expr","locations":[{"start":{"line":198,"column":62},"end":{"line":198,"column":72}},{"start":{"line":198,"column":72},"end":{"line":198,"column":null}}],"line":198},"20":{"loc":{"start":{"line":199,"column":4},"end":{"line":199,"column":null}},"type":"if","locations":[{"start":{"line":199,"column":4},"end":{"line":199,"column":null}},{"start":{},"end":{}}],"line":199},"21":{"loc":{"start":{"line":203,"column":4},"end":{"line":203,"column":null}},"type":"if","locations":[{"start":{"line":203,"column":4},"end":{"line":203,"column":null}},{"start":{},"end":{}}],"line":203},"22":{"loc":{"start":{"line":205,"column":4},"end":{"line":205,"column":null}},"type":"if","locations":[{"start":{"line":205,"column":4},"end":{"line":205,"column":null}},{"start":{},"end":{}}],"line":205},"23":{"loc":{"start":{"line":210,"column":4},"end":{"line":210,"column":null}},"type":"if","locations":[{"start":{"line":210,"column":4},"end":{"line":210,"column":null}},{"start":{},"end":{}}],"line":210},"24":{"loc":{"start":{"line":211,"column":4},"end":{"line":211,"column":null}},"type":"if","locations":[{"start":{"line":211,"column":4},"end":{"line":211,"column":null}},{"start":{},"end":{}}],"line":211},"25":{"loc":{"start":{"line":219,"column":4},"end":{"line":219,"column":null}},"type":"if","locations":[{"start":{"line":219,"column":4},"end":{"line":219,"column":null}},{"start":{},"end":{}}],"line":219},"26":{"loc":{"start":{"line":219,"column":8},"end":{"line":219,"column":40}},"type":"binary-expr","locations":[{"start":{"line":219,"column":8},"end":{"line":219,"column":26}},{"start":{"line":219,"column":26},"end":{"line":219,"column":40}}],"line":219},"27":{"loc":{"start":{"line":221,"column":19},"end":{"line":221,"column":null}},"type":"binary-expr","locations":[{"start":{"line":221,"column":19},"end":{"line":221,"column":47}},{"start":{"line":221,"column":47},"end":{"line":221,"column":null}}],"line":221},"28":{"loc":{"start":{"line":222,"column":19},"end":{"line":222,"column":null}},"type":"binary-expr","locations":[{"start":{"line":222,"column":19},"end":{"line":222,"column":47}},{"start":{"line":222,"column":47},"end":{"line":222,"column":null}}],"line":222},"29":{"loc":{"start":{"line":223,"column":19},"end":{"line":223,"column":null}},"type":"binary-expr","locations":[{"start":{"line":223,"column":19},"end":{"line":223,"column":47}},{"start":{"line":223,"column":47},"end":{"line":223,"column":null}}],"line":223},"30":{"loc":{"start":{"line":224,"column":24},"end":{"line":224,"column":null}},"type":"binary-expr","locations":[{"start":{"line":224,"column":24},"end":{"line":224,"column":57}},{"start":{"line":224,"column":57},"end":{"line":224,"column":null}}],"line":224},"31":{"loc":{"start":{"line":225,"column":25},"end":{"line":225,"column":null}},"type":"binary-expr","locations":[{"start":{"line":225,"column":25},"end":{"line":225,"column":59}},{"start":{"line":225,"column":59},"end":{"line":225,"column":null}}],"line":225},"32":{"loc":{"start":{"line":242,"column":4},"end":{"line":242,"column":null}},"type":"if","locations":[{"start":{"line":242,"column":4},"end":{"line":242,"column":null}},{"start":{},"end":{}}],"line":242},"33":{"loc":{"start":{"line":247,"column":4},"end":{"line":247,"column":null}},"type":"if","locations":[{"start":{"line":247,"column":4},"end":{"line":247,"column":null}},{"start":{},"end":{}}],"line":247},"34":{"loc":{"start":{"line":247,"column":8},"end":{"line":247,"column":43}},"type":"binary-expr","locations":[{"start":{"line":247,"column":8},"end":{"line":247,"column":27}},{"start":{"line":247,"column":27},"end":{"line":247,"column":43}}],"line":247},"35":{"loc":{"start":{"line":250,"column":6},"end":{"line":253,"column":null}},"type":"if","locations":[{"start":{"line":250,"column":6},"end":{"line":253,"column":null}},{"start":{},"end":{}}],"line":250},"36":{"loc":{"start":{"line":250,"column":10},"end":{"line":250,"column":40}},"type":"binary-expr","locations":[{"start":{"line":250,"column":10},"end":{"line":250,"column":27}},{"start":{"line":250,"column":27},"end":{"line":250,"column":40}}],"line":250},"37":{"loc":{"start":{"line":259,"column":4},"end":{"line":259,"column":null}},"type":"if","locations":[{"start":{"line":259,"column":4},"end":{"line":259,"column":null}},{"start":{},"end":{}}],"line":259},"38":{"loc":{"start":{"line":259,"column":8},"end":{"line":259,"column":73}},"type":"binary-expr","locations":[{"start":{"line":259,"column":8},"end":{"line":259,"column":26}},{"start":{"line":259,"column":26},"end":{"line":259,"column":44}},{"start":{"line":259,"column":44},"end":{"line":259,"column":59}},{"start":{"line":259,"column":59},"end":{"line":259,"column":73}}],"line":259},"39":{"loc":{"start":{"line":265,"column":6},"end":{"line":267,"column":null}},"type":"if","locations":[{"start":{"line":265,"column":6},"end":{"line":267,"column":null}},{"start":{},"end":{}}],"line":265}},"s":{"0":11,"1":8,"2":8,"3":8,"4":2,"5":6,"6":6,"7":8,"8":4,"9":1,"10":3,"11":3,"12":3,"13":0,"14":4,"15":4,"16":35,"17":35,"18":35,"19":35,"20":35,"21":35,"22":35,"23":35,"24":35,"25":35,"26":3,"27":5,"28":5,"29":1,"30":4,"31":4,"32":1,"33":1,"34":3,"35":3,"36":3,"37":3,"38":3,"39":3,"40":3,"41":3,"42":3,"43":3,"44":3,"45":3,"46":3,"47":3,"48":5,"49":5,"50":5,"51":5,"52":5,"53":5,"54":5,"55":5,"56":5,"57":1,"58":1,"59":1,"60":1,"61":1,"62":3,"63":3,"64":3,"65":6,"66":6,"67":6,"68":0,"69":0,"70":0,"71":0,"72":0,"73":4,"74":2,"75":2,"76":2,"77":0,"78":2,"79":2,"80":2,"81":2,"82":2,"83":0,"84":2,"85":2,"86":7,"87":3,"88":4,"89":4,"90":0,"91":4,"92":4,"93":5,"94":4,"95":4,"96":4,"97":1,"98":5,"99":2,"100":3,"101":3,"102":0,"103":3,"104":12,"105":2,"106":10,"107":4,"108":6,"109":3,"110":3,"111":5,"112":2,"113":3,"114":3,"115":5,"116":5,"117":5,"118":5,"119":5,"120":5,"121":5,"122":5,"123":5,"124":5,"125":3,"126":3,"127":0,"128":0,"129":3,"130":0,"131":3,"132":0,"133":0,"134":0,"135":0,"136":3,"137":3,"138":1,"139":2,"140":2,"141":2,"142":2,"143":2,"144":2,"145":1,"146":2,"147":1},"f":{"0":11,"1":8,"2":4,"3":3,"4":5,"5":6,"6":4,"7":0,"8":7,"9":5,"10":5,"11":12,"12":3,"13":5,"14":3,"15":0,"16":3,"17":0,"18":3},"b":{"0":[8,5],"1":[2,6],"2":[1,3],"3":[3,0],"4":[0,0],"5":[0,0],"6":[1,4],"7":[1,3],"8":[3,0],"9":[5,0],"10":[6,0],"11":[2,2],"12":[0,2],"13":[2,2],"14":[2,0],"15":[2,2],"16":[3,4],"17":[0,4],"18":[4,0],"19":[1,3],"20":[1,3],"21":[2,3],"22":[0,3],"23":[2,10],"24":[4,6],"25":[2,3],"26":[5,3],"27":[3,2],"28":[5,2],"29":[5,2],"30":[5,2],"31":[5,2],"32":[3,0],"33":[0,3],"34":[3,3],"35":[0,0],"36":[0,0],"37":[1,2],"38":[3,3,2,2],"39":[1,1]},"meta":{"lastBranch":40,"lastFunction":19,"lastStatement":148,"seen":{"f:18:16:18:Infinity":0,"s:25:2:30:Infinity":0,"f:38:16:38:29":1,"s:39:17:39:Infinity":1,"b:39:17:39:26:39:26:39:Infinity":0,"s:40:14:40:Infinity":2,"b:41:2:41:Infinity:undefined:undefined:undefined:undefined":1,"s:41:2:41:Infinity":3,"s:41:12:41:Infinity":4,"s:42:14:42:Infinity":5,"s:43:2:43:Infinity":6,"s:44:2:44:Infinity":7,"f:57:16:57:31":2,"b:58:2:58:Infinity:undefined:undefined:undefined:undefined":2,"s:58:2:58:Infinity":8,"s:58:39:58:Infinity":9,"s:59:17:59:Infinity":10,"b:60:2:60:Infinity:undefined:undefined:undefined:undefined":3,"s:60:2:60:Infinity":11,"s:60:15:60:Infinity":12,"s:61:19:61:Infinity":13,"b:61:30:61:64:61:64:61:66":4,"s:62:14:62:Infinity":14,"s:64:2:64:Infinity":15,"b:64:19:64:29:64:29:64:Infinity":5,"s:85:45:85:Infinity":16,"s:86:43:86:Infinity":17,"s:87:46:87:Infinity":18,"s:88:32:88:Infinity":19,"s:89:49:89:Infinity":20,"s:90:47:90:Infinity":21,"s:91:50:91:Infinity":22,"s:92:33:92:Infinity":23,"s:93:42:93:Infinity":24,"s:94:22:94:Infinity":25,"f:96:6:96:29":3,"s:97:4:97:Infinity":26,"f:100:2:100:18":4,"s:101:4:101:Infinity":27,"b:102:4:102:Infinity:undefined:undefined:undefined:undefined":6,"s:102:4:102:Infinity":28,"s:102:24:102:Infinity":29,"s:104:18:104:Infinity":30,"b:105:4:110:Infinity:undefined:undefined:undefined:undefined":7,"s:105:4:110:Infinity":31,"s:106:6:108:Infinity":32,"s:109:6:109:Infinity":33,"s:113:22:113:Infinity":34,"s:114:4:114:Infinity":35,"s:115:4:115:Infinity":36,"s:116:4:116:Infinity":37,"s:117:4:117:Infinity":38,"s:118:4:118:Infinity":39,"s:121:19:121:Infinity":40,"s:122:4:122:Infinity":41,"s:123:4:123:Infinity":42,"s:124:4:124:Infinity":43,"s:125:4:125:Infinity":44,"s:126:4:126:Infinity":45,"s:127:4:127:Infinity":46,"s:128:4:128:Infinity":47,"b:128:19:128:44:128:44:128:Infinity":8,"s:129:4:129:Infinity":48,"b:129:20:129:46:129:46:129:Infinity":9,"s:130:4:130:Infinity":49,"s:131:4:131:Infinity":50,"s:134:4:138:Infinity":51,"s:139:4:139:Infinity":52,"s:140:4:140:Infinity":53,"s:141:4:148:Infinity":54,"s:150:4:150:Infinity":55,"s:153:4:159:Infinity":56,"s:154:20:154:Infinity":57,"s:155:6:155:Infinity":58,"s:156:6:156:Infinity":59,"s:157:6:157:Infinity":60,"s:158:6:158:Infinity":61,"s:160:4:160:Infinity":62,"s:161:4:161:Infinity":63,"s:163:4:163:Infinity":64,"f:166:2:166:11":5,"b:167:4:171:Infinity:undefined:undefined:undefined:undefined":10,"s:167:4:171:Infinity":65,"s:169:6:169:Infinity":66,"s:170:6:170:Infinity":67,"s:173:18:173:Infinity":68,"s:174:4:174:Infinity":69,"s:175:4:175:Infinity":70,"s:176:4:176:Infinity":71,"s:177:4:177:Infinity":72,"f:180:2:180:13":6,"b:181:4:181:Infinity:undefined:undefined:undefined:undefined":11,"s:181:4:181:Infinity":73,"s:181:24:181:Infinity":74,"s:182:18:182:Infinity":75,"b:183:4:183:Infinity:undefined:undefined:undefined:undefined":12,"s:183:4:183:Infinity":76,"b:183:8:183:18:183:18:183:31":13,"s:183:31:183:Infinity":77,"s:184:18:184:Infinity":78,"s:185:4:185:Infinity":79,"s:186:4:186:Infinity":80,"s:187:4:187:Infinity":81,"s:188:23:188:Infinity":82,"f:188:54:188:55":7,"s:188:61:188:76":83,"b:189:4:189:Infinity:undefined:undefined:undefined:undefined":14,"s:189:4:189:Infinity":84,"b:189:8:189:23:189:23:189:36":15,"s:189:36:189:Infinity":85,"f:192:2:192:13":8,"b:193:4:193:Infinity:undefined:undefined:undefined:undefined":16,"s:193:4:193:Infinity":86,"s:193:24:193:Infinity":87,"s:194:18:194:Infinity":88,"b:195:4:195:Infinity:undefined:undefined:undefined:undefined":17,"s:195:4:195:Infinity":89,"s:195:16:195:Infinity":90,"s:196:4:196:Infinity":91,"s:197:23:197:Infinity":92,"f:197:54:197:55":9,"s:197:61:197:76":93,"b:198:4:198:Infinity:undefined:undefined:undefined:undefined":18,"s:198:4:198:Infinity":94,"s:198:21:198:Infinity":95,"b:198:62:198:72:198:72:198:Infinity":19,"b:199:4:199:Infinity:undefined:undefined:undefined:undefined":20,"s:199:4:199:Infinity":96,"s:199:17:199:Infinity":97,"f:202:2:202:13":10,"b:203:4:203:Infinity:undefined:undefined:undefined:undefined":21,"s:203:4:203:Infinity":98,"s:203:24:203:Infinity":99,"s:204:18:204:Infinity":100,"b:205:4:205:Infinity:undefined:undefined:undefined:undefined":22,"s:205:4:205:Infinity":101,"s:205:16:205:Infinity":102,"s:206:4:206:Infinity":103,"f:209:2:209:24":11,"b:210:4:210:Infinity:undefined:undefined:undefined:undefined":23,"s:210:4:210:Infinity":104,"s:210:24:210:Infinity":105,"b:211:4:211:Infinity:undefined:undefined:undefined:undefined":24,"s:211:4:211:Infinity":106,"s:211:29:211:Infinity":107,"s:212:4:215:Infinity":108,"f:212:39:212:45":12,"s:213:6:213:Infinity":109,"s:214:6:214:Infinity":110,"f:218:2:218:24":13,"b:219:4:219:Infinity:undefined:undefined:undefined:undefined":25,"s:219:4:219:Infinity":111,"b:219:8:219:26:219:26:219:40":26,"s:219:40:219:Infinity":112,"s:220:19:220:Infinity":113,"s:221:19:221:Infinity":114,"b:221:19:221:47:221:47:221:Infinity":27,"s:222:19:222:Infinity":115,"b:222:19:222:47:222:47:222:Infinity":28,"s:223:19:223:Infinity":116,"b:223:19:223:47:223:47:223:Infinity":29,"s:224:24:224:Infinity":117,"b:224:24:224:57:224:57:224:Infinity":30,"s:225:25:225:Infinity":118,"b:225:25:225:59:225:59:225:Infinity":31,"s:226:19:232:Infinity":119,"s:233:4:233:Infinity":120,"s:234:4:234:Infinity":121,"s:235:4:235:Infinity":122,"s:236:4:236:Infinity":123,"s:237:4:237:Infinity":124,"f:240:10:240:34":14,"b:242:4:242:Infinity:undefined:undefined:undefined:undefined":32,"s:242:4:242:Infinity":125,"s:242:60:242:Infinity":126,"s:243:5:243:Infinity":127,"f:243:49:243:55":15,"s:243:55:243:75":128,"f:246:10:246:32":16,"b:247:4:247:Infinity:undefined:undefined:undefined:undefined":33,"s:247:4:247:Infinity":129,"b:247:8:247:27:247:27:247:43":34,"s:247:43:247:Infinity":130,"s:248:4:254:Infinity":131,"f:248:45:248:46":17,"s:249:32:249:Infinity":132,"b:250:6:253:Infinity:undefined:undefined:undefined:undefined":35,"s:250:6:253:Infinity":133,"b:250:10:250:27:250:27:250:40":36,"s:251:8:251:Infinity":134,"s:252:8:252:Infinity":135,"s:255:4:255:Infinity":136,"f:258:10:258:25":18,"b:259:4:259:Infinity:undefined:undefined:undefined:undefined":37,"s:259:4:259:Infinity":137,"b:259:8:259:26:259:26:259:44:259:44:259:59:259:59:259:73":38,"s:259:73:259:Infinity":138,"s:260:21:260:Infinity":139,"s:261:18:261:Infinity":140,"s:262:19:262:Infinity":141,"s:263:4:263:Infinity":142,"s:264:4:268:Infinity":143,"b:265:6:267:Infinity:undefined:undefined:undefined:undefined":39,"s:265:6:267:Infinity":144,"s:266:8:266:Infinity":145,"s:269:4:269:Infinity":146,"s:276:0:276:Infinity":147}}} } diff --git a/src/coverage/index.html b/src/coverage/index.html index d016bb01..855d0c91 100644 --- a/src/coverage/index.html +++ b/src/coverage/index.html @@ -23,16 +23,16 @@
- 85.13% + 88.51% Statements - 126/148 + 131/148
- 70.73% + 76.82% Branches - 58/82 + 63/82
@@ -80,13 +80,13 @@ webgl-layer-framework.ts - -
+ +
- 85.13% - 126/148 - 70.73% - 58/82 + 88.51% + 131/148 + 76.82% + 63/82 84.21% 16/19 91.26% @@ -101,7 +101,7 @@