mirror of
https://github.com/Matysh/houseplan-card
synced 2026-07-31 08:28:31 +00:00
perf/fix v1.43.1: external audit P1 — render cost, drag threshold, geometry, backend
L1: memoized space model + open pairs (structural fingerprint key, epoch bumped synchronously at mutation time, not inside the debounce); hoisted per-room geometry out of the render loop; smoke asserts zero recomputation across state pushes. L4: openings get the 3 px drag threshold used by every other pipeline and only write when the geometry actually changed — taps open the dialog again. G2: interiorPoint() replaces the vertex mean, so island rooms inside concave (U/L) parents are accepted and their evenodd holes render; traced duplicates still are not containment. G3: segKey rounds before ordering — one shared wall, one key. B2: _check_write fails closed when the entry is unavailable. B3: layout/set honours expected_rev and returns the new rev. B4: config/set without expected_rev over a non-empty store logs a warning. B5: coordinates reject NaN/Infinity; spaces/rooms/markers/decor/layout capped. +2 unit tests (118), +2 backend tests (14), smoke_render_perf; docs same-commit
This commit is contained in:
@@ -13,6 +13,7 @@ import {
|
||||
migratePdfUrls,
|
||||
roomFillModeOf,
|
||||
contentUrl,
|
||||
interiorPoint,
|
||||
segmentCm, formatLength, roomEdges, roomPoly, pointOnBoundary, pointStrictlyInside, roomsOverlap,
|
||||
mergeRooms, splitRoom, polygonArea, closestPointOnBoundary, isActiveState, snapToWall, openingAmount, fillColorsOf, lerpColor, roomFillStyle, stateIcon, lightColorOf, isAlarmState, parseRoomRef, diffNewDevices,
|
||||
} from '../test-build/logic.js';
|
||||
@@ -844,3 +845,25 @@ test('contentUrl: legacy static paths become authenticated ones (audit B1)', ()
|
||||
assert.equal(contentUrl(''), '');
|
||||
assert.equal(contentUrl(null), '');
|
||||
});
|
||||
|
||||
test('interiorPoint / polyContainsPoly on concave rooms (audit G2)', () => {
|
||||
// U-образная комната: среднее вершин лежит СНАРУЖИ
|
||||
const u = [[0, 0], [10, 0], [10, 10], [9, 10], [9, 2], [1, 2], [1, 10], [0, 10]];
|
||||
const mean = [u.reduce((s, p) => s + p[0], 0) / u.length, u.reduce((s, p) => s + p[1], 0) / u.length];
|
||||
assert.equal(pointStrictlyInside(mean, u), false, 'предпосылка: среднее снаружи');
|
||||
const ip = interiorPoint(u);
|
||||
assert.ok(ip && pointStrictlyInside(ip, u), 'interiorPoint обязана быть внутри');
|
||||
// вложенность вогнутых теперь распознаётся
|
||||
const outer = [[-1, -1], [11, -1], [11, 11], [8.5, 11], [8.5, 2.5], [1.5, 2.5], [1.5, 11], [-1, 11]];
|
||||
assert.equal(polyContainsPoly(outer, u), true);
|
||||
assert.equal(roomsOverlap(outer, u), false);
|
||||
// дубликат по-прежнему НЕ вложенность
|
||||
assert.equal(polyContainsPoly(u, u), false);
|
||||
});
|
||||
|
||||
test('segKey: one wall, one key at any precision (audit G3)', () => {
|
||||
assert.equal(segKey([1.000001, 1], [1.000002, 2]), segKey([1.000002, 1], [1.000001, 2]));
|
||||
assert.equal(segKey([0, 0], [1, 1], 3), segKey([1, 1], [0, 0], 3));
|
||||
// разные стены — разные ключи
|
||||
assert.notEqual(segKey([0, 0], [1, 1]), segKey([0, 0], [2, 2]));
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user