mirror of
https://github.com/Matysh/houseplan-card
synced 2026-10-05 14:19:04 +00:00
feat: LED strips — editor notes, docs, demo, smokes, golden scenes, profile (#780)
Stage 5 of #780. - Import summary: «Strips left unbound after import: {n}» from the backend `unbound_led_strips` count; «Optimize plans» reports strips passing through walls per space and edits none (AC16). - Linear field for long strips (ТЗ §13.2): pieces of at most the radius along the polyline, emitters thinned to r/4, each piece clipped to the visibility fans of its own emitters as separate clipPath children (no boolean pass per piece), one floor clip for the whole layer, no fan at all where nothing blocks within the radius; a grid index of body faces and boxed inside tests; unchanged fields skip re-diffing. 50×50 on the large house: first stable frame ~1.4 s, warm space ~1.1 s locally. - led-strips-v1 profile: demo/benchmark_led_strips.mjs with the derived large-house fixture (10×5, 50×50, none), absolute limits of the ТЗ table in demo/performance/budgets-led-strips.json, exact counters (zero recomputes on HA ticks/camera/colour, ≤50 cache entries, no growth over 20 cycles); added to the full performance workflow. - Bundle: LAZY_LED_GZIP_CEILING 10 KiB, LAZY_LED_EDITOR_GZIP_CEILING 11 KiB (measured + 10 %, rounded up); overlaps with the initial and editor graphs refused; the lazy editor graph stays inside its ceiling. - Smokes smoke_led_strip_draw/bind/glow, linked in smoke-links; 13 mutants in the registry (7 browser guards in the inventory); config field registry entry `spaces[].led_strips`. - Golden: five new scenes on the `golden-led` space of the visual fixture (`ledStrips` option, the designer's four strips on #868D94), matrix v71. - Docs: LIGHT, DEVICE-PRESENTATION, USER-GUIDE (en/ru), UX-MODES, ARCHITECTURE, ISOMETRIC, CONFIG-COMPATIBILITY, TOUCH-SUPPORT, demo/stand README, performance README; docs/design/led-strips with the unchanged designer archive, two paired frames and ACCEPTANCE.md; both changelogs. Issue: #780 User-Visible: yes
This commit is contained in:
@@ -668,6 +668,16 @@ export const LAZY_GRAPH_CEILING_BAND = 2_000;
|
||||
*/
|
||||
export const LAZY_ONBOARDING_GZIP_CEILING = 28_396;
|
||||
|
||||
/**
|
||||
* #780 ТЗ §13.1: the LED chunks are a new feature's own budget, not a raise of
|
||||
* an existing ceiling. Measured on the production build at the hand-off
|
||||
* (runtime + linear field + shared geometry 8 698 B; Devices-editor tool +
|
||||
* its English dictionary + shared geometry 9 913 B), plus 10 %, rounded up to
|
||||
* a KiB. Absolute walls: a View without strips loads neither graph.
|
||||
*/
|
||||
export const LAZY_LED_GZIP_CEILING = 10 * 1024;
|
||||
export const LAZY_LED_EDITOR_GZIP_CEILING = 11 * 1024;
|
||||
|
||||
/**
|
||||
* Потолок ленивого графа: `null`, пока значение внутри полосы.
|
||||
*
|
||||
@@ -749,6 +759,21 @@ export function assertBundleBudget(
|
||||
if (manifest.lazyEditorFiles.some((path) => manifest.lazyMoonFiles.includes(path))) {
|
||||
throw new Error('lazy editor graph overlaps lazy moon graph');
|
||||
}
|
||||
// #780 ТЗ §13.1: the LED runtime/field and the LED tool are lazy, own-budget
|
||||
// graphs; neither enters the first frame or the static editor graph.
|
||||
for (const [files, bytes, ceiling, label] of [
|
||||
[manifest.lazyLedFiles, manifest.lazyLedGzipBytes, LAZY_LED_GZIP_CEILING, 'lazy LED graph'],
|
||||
[manifest.lazyLedEditorFiles, manifest.lazyLedEditorGzipBytes, LAZY_LED_EDITOR_GZIP_CEILING, 'lazy LED editor graph'],
|
||||
]) {
|
||||
if (!files?.length) throw new Error(`bundle has no ${label}`);
|
||||
if (manifest.initialViewFiles.some((path) => files.includes(path))) {
|
||||
throw new Error(`initial View graph overlaps ${label}`);
|
||||
}
|
||||
if (manifest.lazyEditorFiles.some((path) => /\/led-strip-/.test(path) && files.includes(path))) {
|
||||
throw new Error(`lazy editor graph overlaps ${label}`);
|
||||
}
|
||||
if (bytes > ceiling) throw new Error(`${label} ${bytes} B gzip exceeds its ${ceiling} B ceiling`);
|
||||
}
|
||||
// #474: designer furniture artwork is lazy; a static import anywhere in the
|
||||
// View graph would pull ~10 KB gzip back into the initial graph silently.
|
||||
if (!manifest.lazyFurnitureArtFiles?.length) {
|
||||
@@ -822,6 +847,8 @@ export function assertBundleBudget(
|
||||
lazyFurnitureArtGzipBytes: manifest.lazyFurnitureArtGzipBytes,
|
||||
lazyPdfGzipBytes: manifest.lazyPdfGzipBytes,
|
||||
lazyMoonGzipBytes: manifest.lazyMoonGzipBytes,
|
||||
lazyLedGzipBytes: manifest.lazyLedGzipBytes,
|
||||
lazyLedEditorGzipBytes: manifest.lazyLedEditorGzipBytes,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -857,6 +884,8 @@ if (import.meta.url === pathToFileURL(process.argv[1] || '').href) {
|
||||
`lazy isometric: ${result.lazyIsometricGzipBytes} B gzip`,
|
||||
`lazy PDF: ${result.lazyPdfGzipBytes} B gzip`,
|
||||
`lazy moon: ${result.lazyMoonGzipBytes} B gzip`,
|
||||
`lazy LED: ${result.lazyLedGzipBytes} B gzip (потолок ${LAZY_LED_GZIP_CEILING} B)`,
|
||||
`lazy LED editor: ${result.lazyLedEditorGzipBytes} B gzip (потолок ${LAZY_LED_EDITOR_GZIP_CEILING} B)`,
|
||||
];
|
||||
for (const line of lines) console.log(line);
|
||||
const warning = lowHeadroomWarning(headroom);
|
||||
|
||||
Reference in New Issue
Block a user