mirror of
https://github.com/Matysh/houseplan-card
synced 2026-09-28 19:01:34 +00:00
103 lines
4.5 KiB
JavaScript
103 lines
4.5 KiB
JavaScript
/**
|
||
* Issue #233: resize labels measure between wall faces, not between centrelines.
|
||
*
|
||
* Before the fix one bubble carried two conventions at once — lengths along the
|
||
* centreline next to an area computed from the floor — so «3.00 × 4.00 · 11.0 m²»
|
||
* described a room that no tape measure would confirm.
|
||
*
|
||
* The room below is 300×400 cm centre-to-centre with 15 cm walls on all four
|
||
* sides, so every clear span is exactly 15 cm shorter than the axis it sits on:
|
||
* 285 and 385 cm. Thickness is set through the card's own dialog path
|
||
* (`_wallThickClick` → `_wallThickApply(true)`), and both label producers are
|
||
* then called as the drag handlers call them. The legacy room-scale frame was
|
||
* deliberately removed by #277, so only fixed-topology edge labels remain.
|
||
*/
|
||
import { launch, checkAll, finish } from './serve.mjs';
|
||
const { page, browser } = await launch();
|
||
|
||
const res = await page.evaluate(async () => {
|
||
const out = {};
|
||
const c = window.__card;
|
||
const sr = c.shadowRoot || c.renderRoot;
|
||
const upd = async () => { c._cfgEpoch++; c.requestUpdate(); await c.updateComplete; };
|
||
// First number of a label: both formatters emit a dot, so this is locale-safe.
|
||
const num = (text) => Number((String(text).match(/-?\d+(?:\.\d+)?/) || [])[0]);
|
||
|
||
c._setMode('plan');
|
||
await upd();
|
||
const space = c._curSpaceCfg;
|
||
const savedConfig = JSON.parse(JSON.stringify(c._serverCfg));
|
||
|
||
// 5 cm to a grid cell, so 300×400 cm is 60×80 cells of the plan.
|
||
space.cell_cm = 5;
|
||
c._serverCfg.model_version = 7;
|
||
space.partitions = [];
|
||
delete space.walls;
|
||
delete space.wall_segments;
|
||
delete space.open_spans;
|
||
const g = c._gridPitch;
|
||
const x0 = 20 * g, y0 = 20 * g;
|
||
const render = [
|
||
[x0, y0], [x0 + 60 * g, y0], [x0 + 60 * g, y0 + 80 * g], [x0, y0 + 80 * g],
|
||
];
|
||
space.rooms = [{ id: 'r233', name: 'r233', poly: render.map((p) => [p[0] / 1000, p[1] / 1000]) }];
|
||
await upd();
|
||
out.roomBuilt = !!c._spaceModel()?.rooms?.some((r) => r.id === 'r233');
|
||
|
||
// 15 cm on every side, applied the way the Thickness tool applies it.
|
||
c._tool = 'wallthick';
|
||
await upd();
|
||
const mid = (a, b) => [(a[0] + b[0]) / 2, (a[1] + b[1]) / 2];
|
||
c._wallThickClick(mid(render[0], render[1]));
|
||
await upd();
|
||
out.thicknessDialogOpened = !!c._wallDialog && c._wallDialog.roomId === 'r233';
|
||
if (c._wallDialog) c._wallDialog = { ...c._wallDialog, value: '15' };
|
||
c._wallThickApply(true);
|
||
await upd();
|
||
const committed = c._curSpaceCfg;
|
||
const committedRoom = committed.rooms.find((room) => room.id === 'r233');
|
||
const byId = new Map((committed.wall_segments || []).map((segment) => [segment.id, segment]));
|
||
out.fourWallsRecorded = committedRoom?.wall_ids?.length === 4;
|
||
out.everyWallFifteen = committedRoom?.wall_ids?.every((id) =>
|
||
Math.abs((byId.get(id)?.cm ?? -1) - 15) < 0.01) === true;
|
||
|
||
// Wall labels: the clear span across is 285 cm, along it 385 cm.
|
||
const spans = c._rszInnerSpanCms('r233', render, {});
|
||
out.spansComputed = Array.isArray(spans) && spans.length === 4;
|
||
out.spanAcrossIsInner = !!spans && Math.abs(spans[0] - 285) < 1;
|
||
out.spanAlongIsInner = !!spans && Math.abs(spans[1] - 385) < 1;
|
||
out.spansSymmetric = !!spans
|
||
&& Math.abs(spans[0] - spans[2]) < 1 && Math.abs(spans[1] - spans[3]) < 1;
|
||
// The whole point of #233: no label may still read the centreline.
|
||
out.noCentrelineSpan = !!spans
|
||
&& !spans.some((s) => Math.abs(s - 300) < 0.5 || Math.abs(s - 400) < 0.5);
|
||
|
||
// The two useful side-wall bubbles, called with the controller's room snapshot.
|
||
const resizeRooms = c._spaceModel().rooms.map((r) => ({ id: r.id, poly: r.poly }));
|
||
await upd();
|
||
const drag = c._rszEdgeLabels(
|
||
{ polys: { r233: render } },
|
||
{ roomId: 'r233', edge: 0, roomIds: ['r233'], edgeByRoom: { r233: 0 } },
|
||
resizeRooms,
|
||
);
|
||
const dragLens = drag.filter((l) => l.kind === 'length').map((l) => num(l.text));
|
||
out.dragLabelsTwoSideEdges = dragLens.length === 2;
|
||
out.dragLabelsInner = dragLens.every((v) => Math.abs(v - 2.85) < 0.02 || Math.abs(v - 3.85) < 0.02);
|
||
out.dragLabelsNotCentreline = !dragLens.some((v) => Math.abs(v - 3) < 0.005 || Math.abs(v - 4) < 0.005);
|
||
const dragArea = drag.find((l) => l.kind === 'area');
|
||
out.dragAreaStillInner = !!dragArea && Math.abs(num(dragArea.text) - 11) < 0.06;
|
||
|
||
out.legacyScaleLabelsAbsent = typeof c._rszScaleLabels === 'undefined';
|
||
out.legacyCornerHandlesAbsent = !sr.querySelector('.rszcorner');
|
||
|
||
c._resize.reset();
|
||
c._tool = null;
|
||
c._serverCfg = savedConfig;
|
||
c._modelCache = null; c._frame = null;
|
||
await upd();
|
||
return out;
|
||
});
|
||
|
||
checkAll(res);
|
||
await finish(browser);
|