mirror of
https://github.com/Matysh/houseplan-card
synced 2026-10-03 05:08:53 +00:00
test: add a second real plan to the masonry gate
The second floor covers one class: the multi-wall corridor eating a neighbouring wall. The first floor brings what neither it nor any synthetic fixture has — three virtual spans, two wall columns, two solid edges with no thickness record at all, and 127 noisy coordinates. The two plans pin opposite states, which is worth more than two plans with the same defect: one records a known debt of 181 steps, the other records cleanliness at zero. A regression is caught in both directions. A declared virtual span is a declared break, not a defect, so the rule from #285 would have reddened on the first floor's own contract. Samples lying on open_spans are now excluded: 830 of 6800 on that plan, and the remaining gap count is zero. The two zero-thickness solid edges are two grid steps long and covered by the bodies of their neighbours, so the browser sees no break. Their count is therefore pinned in the model test rather than the smoke — if it grows, or if the neighbours stop covering them, that shows up before it becomes a hole. Both fixtures must stay noisy: the project's synthetic models carry exactly zero noise, which is why #258 and #248 are not reproducible on them. A profile check asserts at least a hundred noisy coordinates each, so a future write barrier run over the fixtures cannot quietly rob them of their purpose. Privacy: names, ids, markers, device bindings and layout are gone; geometry stays, coordinates unchanged, because they are the point. Issue: #286 User-Visible: no
This commit is contained in:
@@ -18,8 +18,18 @@
|
||||
import { readFileSync } from 'node:fs';
|
||||
import { launch, checkAll, finish } from './serve.mjs';
|
||||
|
||||
const FIXTURE = new URL('../test/fixtures/real-plan-second-floor.json', import.meta.url);
|
||||
const { space } = JSON.parse(readFileSync(FIXTURE, 'utf8'));
|
||||
/**
|
||||
* Реальные планы, каждый со своим классом дефектов (#285, #286).
|
||||
*
|
||||
* Второй этаж — стыки: коридор многостенного узла съедает соседнюю кладку.
|
||||
* Первый этаж — другое: у него есть виртуальные пролёты, колонны и два
|
||||
* сплошных ребра, у которых вообще нет записи толщины. Ни то, ни другое
|
||||
* синтетика не воспроизводит.
|
||||
*/
|
||||
const PLANS = [
|
||||
{ file: 'real-plan-second-floor.json', gapCount: 4, gapSteps: 181 },
|
||||
{ file: 'real-plan-first-floor.json', gapCount: 0, gapSteps: 0 },
|
||||
];
|
||||
|
||||
/**
|
||||
* Признанный долг beta.9, ведётся в #284 вместе с #271/#275.
|
||||
@@ -42,7 +52,7 @@ const KNOWN_GAP_STEPS = 181;
|
||||
const { page, browser } = await launch();
|
||||
const out = {};
|
||||
|
||||
const measured = await page.evaluate(async (space) => {
|
||||
const measure = (space) => page.evaluate(async (space) => {
|
||||
const card = window.__card;
|
||||
card._serverCfg = { spaces: [space], markers: [], settings: {} };
|
||||
card._cfgEpoch = (card._cfgEpoch || 0) + 1;
|
||||
@@ -69,9 +79,25 @@ const measured = await page.evaluate(async (space) => {
|
||||
// достаточно грубо, чтобы прогон оставался быстрым.
|
||||
const SAMPLE = STEP / 4;
|
||||
|
||||
// Виртуальный пролёт — объявленный разрыв, а не дефект: там кладки быть не
|
||||
// должно. Без этого исключения план с виртуальными границами покраснел бы
|
||||
// на собственном контракте.
|
||||
const spans = (space.open_spans || []).map((s) => [s.a, s.b]);
|
||||
const onDeclaredSpan = (x, y) => spans.some(([a, b]) => {
|
||||
const dx = b[0] - a[0], dy = b[1] - a[1];
|
||||
const len2 = dx * dx + dy * dy;
|
||||
if (len2 < 1e-18) return false;
|
||||
const t = ((x - a[0]) * dx + (y - a[1]) * dy) / len2;
|
||||
if (t < -0.02 || t > 1.02) return false;
|
||||
const px = a[0] + dx * Math.max(0, Math.min(1, t));
|
||||
const py = a[1] + dy * Math.max(0, Math.min(1, t));
|
||||
return Math.hypot(x - px, y - py) <= 1 / 240;
|
||||
});
|
||||
|
||||
const gaps = [];
|
||||
let sampled = 0;
|
||||
let missing = 0;
|
||||
let skipped = 0;
|
||||
for (const room of space.rooms) {
|
||||
const poly = room.poly;
|
||||
for (let i = 0; i < poly.length; i++) {
|
||||
@@ -84,6 +110,14 @@ const measured = await page.evaluate(async (space) => {
|
||||
const t = k / count;
|
||||
const x = a[0] + (b[0] - a[0]) * t;
|
||||
const y = a[1] + (b[1] - a[1]) * t;
|
||||
if (onDeclaredSpan(x, y)) {
|
||||
skipped++;
|
||||
if (runStart !== null) {
|
||||
gaps.push({ room: room.id, edge: i, steps: (t - runStart) * length / STEP });
|
||||
runStart = null;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
sampled++;
|
||||
const solid = wall.isPointInFill(at(x, y));
|
||||
if (!solid) {
|
||||
@@ -102,6 +136,7 @@ const measured = await page.evaluate(async (space) => {
|
||||
const worst = gaps.slice().sort((x, y) => y.steps - x.steps).slice(0, 5);
|
||||
return {
|
||||
sampled,
|
||||
skipped,
|
||||
missing,
|
||||
gapCount: gaps.length,
|
||||
totalGapSteps: gaps.reduce((sum, g) => sum + g.steps, 0),
|
||||
@@ -109,15 +144,27 @@ const measured = await page.evaluate(async (space) => {
|
||||
};
|
||||
}, space);
|
||||
|
||||
console.log(JSON.stringify(measured, null, 2));
|
||||
out.wallPathFound = !measured.error;
|
||||
out.sampledEnough = measured.sampled > 5000;
|
||||
out.gapCountMatchesKnownDebt = measured.gapCount === KNOWN_GAP_COUNT;
|
||||
out.gapLengthMatchesKnownDebt = Math.abs(measured.totalGapSteps - KNOWN_GAP_STEPS) < 1;
|
||||
if (!out.gapCountMatchesKnownDebt || !out.gapLengthMatchesKnownDebt) {
|
||||
console.log(`Долг изменился: было ${KNOWN_GAP_COUNT} разрывов на ${KNOWN_GAP_STEPS} шага,`
|
||||
+ ` стало ${measured.gapCount} на ${measured.totalGapSteps.toFixed(2)}.`
|
||||
+ ' Меньше — обновите числа и приложите прогон; больше — это регрессия.');
|
||||
for (const plan of PLANS) {
|
||||
const { space } = JSON.parse(readFileSync(
|
||||
new URL(`../test/fixtures/${plan.file}`, import.meta.url), 'utf8'));
|
||||
const measured = await measure(space);
|
||||
const tag = plan.file.replace('real-plan-', '').replace('.json', '');
|
||||
console.log(tag, JSON.stringify(measured, null, 2));
|
||||
out[`${tag}:wallPath`] = !measured.error;
|
||||
out[`${tag}:sampledEnough`] = measured.sampled > 5000;
|
||||
if (plan.gapCount === null) {
|
||||
console.log(`ИЗМЕРЕНИЕ ${tag}: разрывов ${measured.gapCount},`
|
||||
+ ` суммарно ${measured.totalGapSteps.toFixed(2)} шага`);
|
||||
} else {
|
||||
out[`${tag}:gapCount`] = measured.gapCount === plan.gapCount;
|
||||
out[`${tag}:gapLength`] = Math.abs(measured.totalGapSteps - plan.gapSteps) < 1;
|
||||
if (!out[`${tag}:gapCount`] || !out[`${tag}:gapLength`]) {
|
||||
console.log(`Долг ${tag} изменился: было ${plan.gapCount} разрывов на`
|
||||
+ ` ${plan.gapSteps} шага, стало ${measured.gapCount} на`
|
||||
+ ` ${measured.totalGapSteps.toFixed(2)}. Меньше — обновите числа и приложите`
|
||||
+ ' прогон; больше — это регрессия.');
|
||||
}
|
||||
}
|
||||
}
|
||||
checkAll(out);
|
||||
await finish(browser, out);
|
||||
|
||||
+583
@@ -0,0 +1,583 @@
|
||||
{
|
||||
"note": "Privacy-minimised geometry of a real first floor (issue #286 (gate introduced in #285)). Room names, ids and every device binding are removed; only geometry, thickness, virtual spans and openings remain. Coordinates are unchanged on purpose: this plan carries the coordinate noise that synthetic fixtures do not.",
|
||||
"space": {
|
||||
"id": "real-first-floor",
|
||||
"title": "Real first floor",
|
||||
"cell_cm": 5,
|
||||
"view_box": [
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
1
|
||||
],
|
||||
"settings": {
|
||||
"show_borders": true,
|
||||
"show_names": false,
|
||||
"fill_mode": "custom",
|
||||
"custom_fill": {
|
||||
"c": "#607d8b",
|
||||
"a": 0
|
||||
},
|
||||
"glow_enabled": false
|
||||
},
|
||||
"rooms": [
|
||||
{
|
||||
"id": "room-a",
|
||||
"name": "Room A",
|
||||
"poly": [
|
||||
[
|
||||
0.070833333,
|
||||
0.4375
|
||||
],
|
||||
[
|
||||
0.070833333,
|
||||
0.05
|
||||
],
|
||||
[
|
||||
0.8875,
|
||||
0.05
|
||||
],
|
||||
[
|
||||
0.8875,
|
||||
0.345833333
|
||||
],
|
||||
[
|
||||
0.691666667,
|
||||
0.345833333
|
||||
],
|
||||
[
|
||||
0.691666667,
|
||||
0.55
|
||||
],
|
||||
[
|
||||
0.620833333,
|
||||
0.55
|
||||
],
|
||||
[
|
||||
0.620833333,
|
||||
0.425
|
||||
],
|
||||
[
|
||||
0.420833333,
|
||||
0.425
|
||||
],
|
||||
[
|
||||
0.420833333,
|
||||
0.4375
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "room-b",
|
||||
"name": "Room B",
|
||||
"poly": [
|
||||
[
|
||||
0.204166667,
|
||||
0.645833333
|
||||
],
|
||||
[
|
||||
0.204166667,
|
||||
0.4375
|
||||
],
|
||||
[
|
||||
0.420833333,
|
||||
0.4375
|
||||
],
|
||||
[
|
||||
0.420833333,
|
||||
0.645833333
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "room-c",
|
||||
"name": "Room C",
|
||||
"poly": [
|
||||
[
|
||||
0.2375,
|
||||
0.866666667
|
||||
],
|
||||
[
|
||||
0.2375,
|
||||
0.645833333
|
||||
],
|
||||
[
|
||||
0.420833333,
|
||||
0.645833333
|
||||
],
|
||||
[
|
||||
0.420833333,
|
||||
0.866666667
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "room-d",
|
||||
"name": "Room D",
|
||||
"poly": [
|
||||
[
|
||||
0.070833333,
|
||||
0.866666667
|
||||
],
|
||||
[
|
||||
0.070833333,
|
||||
0.645833333
|
||||
],
|
||||
[
|
||||
0.2375,
|
||||
0.645833333
|
||||
],
|
||||
[
|
||||
0.2375,
|
||||
0.866666667
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "room-e",
|
||||
"name": "Room E",
|
||||
"poly": [
|
||||
[
|
||||
0.420833333,
|
||||
0.866666667
|
||||
],
|
||||
[
|
||||
0.420833333,
|
||||
0.425
|
||||
],
|
||||
[
|
||||
0.620833333,
|
||||
0.425
|
||||
],
|
||||
[
|
||||
0.620833333,
|
||||
0.866666667
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "room-f",
|
||||
"name": "Room F",
|
||||
"poly": [
|
||||
[
|
||||
0.620833333,
|
||||
0.866666667
|
||||
],
|
||||
[
|
||||
0.620833333,
|
||||
0.55
|
||||
],
|
||||
[
|
||||
0.8875,
|
||||
0.55
|
||||
],
|
||||
[
|
||||
0.8875,
|
||||
0.866666667
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "room-g",
|
||||
"name": "Room G",
|
||||
"poly": [
|
||||
[
|
||||
0.070833333,
|
||||
0.645833333
|
||||
],
|
||||
[
|
||||
0.070833333,
|
||||
0.4375
|
||||
],
|
||||
[
|
||||
0.204166667,
|
||||
0.4375
|
||||
],
|
||||
[
|
||||
0.204166667,
|
||||
0.645833333
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "room-h",
|
||||
"name": "Room H",
|
||||
"poly": [
|
||||
[
|
||||
0.691666667,
|
||||
0.345833333
|
||||
],
|
||||
[
|
||||
0.979166667,
|
||||
0.345833333
|
||||
],
|
||||
[
|
||||
0.979166667,
|
||||
0.55
|
||||
],
|
||||
[
|
||||
0.691666667,
|
||||
0.55
|
||||
]
|
||||
]
|
||||
}
|
||||
],
|
||||
"walls": [
|
||||
{
|
||||
"key": "0.479167,0.050000@0.0000",
|
||||
"cm": 29,
|
||||
"a": [
|
||||
0.070833333,
|
||||
0.05
|
||||
],
|
||||
"b": [
|
||||
0.8875,
|
||||
0.05
|
||||
]
|
||||
},
|
||||
{
|
||||
"key": "0.420833,0.645833@1.5706",
|
||||
"cm": 20,
|
||||
"a": [
|
||||
0.420833333,
|
||||
0.866666667
|
||||
],
|
||||
"b": [
|
||||
0.420833333,
|
||||
0.425
|
||||
]
|
||||
},
|
||||
{
|
||||
"key": "0.070833,0.245833@1.5706",
|
||||
"cm": 29,
|
||||
"a": [
|
||||
0.070833333,
|
||||
0.4375
|
||||
],
|
||||
"b": [
|
||||
0.070833333,
|
||||
0.05
|
||||
]
|
||||
},
|
||||
{
|
||||
"key": "0.245833,0.437500@0.0000",
|
||||
"cm": 33,
|
||||
"a": [
|
||||
0.420833333,
|
||||
0.4375
|
||||
],
|
||||
"b": [
|
||||
0.070833333,
|
||||
0.4375
|
||||
]
|
||||
},
|
||||
{
|
||||
"key": "0.620833,0.708333@1.5706",
|
||||
"cm": 20,
|
||||
"a": [
|
||||
0.620833333,
|
||||
0.55
|
||||
],
|
||||
"b": [
|
||||
0.620833333,
|
||||
0.866666667
|
||||
]
|
||||
},
|
||||
{
|
||||
"key": "0.887500,0.708333@1.5706",
|
||||
"cm": 29,
|
||||
"a": [
|
||||
0.8875,
|
||||
0.55
|
||||
],
|
||||
"b": [
|
||||
0.8875,
|
||||
0.866666667
|
||||
]
|
||||
},
|
||||
{
|
||||
"key": "0.887500,0.195833@1.5706",
|
||||
"cm": 29,
|
||||
"a": [
|
||||
0.8875,
|
||||
0.05
|
||||
],
|
||||
"b": [
|
||||
0.8875,
|
||||
0.345833333
|
||||
]
|
||||
},
|
||||
{
|
||||
"key": "0.754167,0.550000@0.0000",
|
||||
"cm": 20,
|
||||
"a": [
|
||||
0.620833333,
|
||||
0.55
|
||||
],
|
||||
"b": [
|
||||
0.8875,
|
||||
0.55
|
||||
]
|
||||
},
|
||||
{
|
||||
"key": "0.754167,0.866667@0.0000",
|
||||
"cm": 29,
|
||||
"a": [
|
||||
0.8875,
|
||||
0.866666667
|
||||
],
|
||||
"b": [
|
||||
0.620833333,
|
||||
0.866666667
|
||||
]
|
||||
},
|
||||
{
|
||||
"key": "0.070833,0.758333@1.5706",
|
||||
"cm": 29,
|
||||
"a": [
|
||||
0.070833333,
|
||||
0.866666667
|
||||
],
|
||||
"b": [
|
||||
0.070833333,
|
||||
0.645833333
|
||||
]
|
||||
},
|
||||
{
|
||||
"key": "0.237500,0.758333@1.5706",
|
||||
"cm": 20,
|
||||
"a": [
|
||||
0.2375,
|
||||
0.866666667
|
||||
],
|
||||
"b": [
|
||||
0.2375,
|
||||
0.645833333
|
||||
]
|
||||
},
|
||||
{
|
||||
"key": "0.312500,0.645833@0.0000",
|
||||
"cm": 20,
|
||||
"a": [
|
||||
0.420833333,
|
||||
0.645833333
|
||||
],
|
||||
"b": [
|
||||
0.204166667,
|
||||
0.645833333
|
||||
]
|
||||
},
|
||||
{
|
||||
"key": "0.070833,0.541667@1.5706",
|
||||
"cm": 29,
|
||||
"a": [
|
||||
0.070833333,
|
||||
0.645833333
|
||||
],
|
||||
"b": [
|
||||
0.070833333,
|
||||
0.4375
|
||||
]
|
||||
},
|
||||
{
|
||||
"key": "0.204167,0.541667@1.5706",
|
||||
"cm": 20,
|
||||
"a": [
|
||||
0.204166667,
|
||||
0.645833333
|
||||
],
|
||||
"b": [
|
||||
0.204166667,
|
||||
0.4375
|
||||
]
|
||||
},
|
||||
{
|
||||
"key": "0.979167,0.445833@1.5706",
|
||||
"cm": 28,
|
||||
"a": [
|
||||
0.979166667,
|
||||
0.345833333
|
||||
],
|
||||
"b": [
|
||||
0.979166667,
|
||||
0.55
|
||||
]
|
||||
},
|
||||
{
|
||||
"key": "0.520833,0.866667@0.0000",
|
||||
"cm": 29,
|
||||
"a": [
|
||||
0.620833333,
|
||||
0.866666667
|
||||
],
|
||||
"b": [
|
||||
0.420833333,
|
||||
0.866666667
|
||||
]
|
||||
},
|
||||
{
|
||||
"key": "0.791667,0.345833@0.0000",
|
||||
"cm": 22,
|
||||
"a": [
|
||||
0.8875,
|
||||
0.345833333
|
||||
],
|
||||
"b": [
|
||||
0.691666667,
|
||||
0.345833333
|
||||
]
|
||||
},
|
||||
{
|
||||
"key": "0.329167,0.866667@0.0000",
|
||||
"cm": 29,
|
||||
"a": [
|
||||
0.420833333,
|
||||
0.866666667
|
||||
],
|
||||
"b": [
|
||||
0.2375,
|
||||
0.866666667
|
||||
]
|
||||
},
|
||||
{
|
||||
"key": "0.154167,0.645833@0.0000",
|
||||
"cm": 20,
|
||||
"a": [
|
||||
0.070833333,
|
||||
0.645833333
|
||||
],
|
||||
"b": [
|
||||
0.2375,
|
||||
0.645833333
|
||||
]
|
||||
},
|
||||
{
|
||||
"key": "0.154167,0.866667@0.0000",
|
||||
"cm": 29,
|
||||
"a": [
|
||||
0.2375,
|
||||
0.866666667
|
||||
],
|
||||
"b": [
|
||||
0.070833333,
|
||||
0.866666667
|
||||
]
|
||||
},
|
||||
{
|
||||
"key": "0.691667,0.400000@1.5706",
|
||||
"cm": 22,
|
||||
"a": [
|
||||
0.691666667,
|
||||
0.345833333
|
||||
],
|
||||
"b": [
|
||||
0.691666667,
|
||||
0.454166667
|
||||
]
|
||||
},
|
||||
{
|
||||
"key": "0.933333,0.550000@0.0000",
|
||||
"cm": 22,
|
||||
"a": [
|
||||
0.979166667,
|
||||
0.55
|
||||
],
|
||||
"b": [
|
||||
0.8875,
|
||||
0.55
|
||||
]
|
||||
},
|
||||
{
|
||||
"key": "0.933333,0.345833@0.0000",
|
||||
"cm": 22,
|
||||
"a": [
|
||||
0.888881904,
|
||||
0.345833333
|
||||
],
|
||||
"b": [
|
||||
0.979166667,
|
||||
0.345833333
|
||||
]
|
||||
},
|
||||
{
|
||||
"key": "0.887500,0.345833@0.0000",
|
||||
"cm": 15,
|
||||
"a": [
|
||||
0.8875,
|
||||
0.345833333
|
||||
],
|
||||
"b": [
|
||||
0.888881904,
|
||||
0.345833333
|
||||
]
|
||||
}
|
||||
],
|
||||
"partitions": [
|
||||
{
|
||||
"id": "partition_partition_partition_partition-msjey_30638872",
|
||||
"a": [
|
||||
0.691666667,
|
||||
0.345833333
|
||||
],
|
||||
"b": [
|
||||
0.604166667,
|
||||
0.345833333
|
||||
],
|
||||
"cm": 22
|
||||
}
|
||||
],
|
||||
"open_spans": [
|
||||
{
|
||||
"a": [
|
||||
0.420833333,
|
||||
0.425
|
||||
],
|
||||
"b": [
|
||||
0.620833333,
|
||||
0.425
|
||||
]
|
||||
},
|
||||
{
|
||||
"a": [
|
||||
0.620833333,
|
||||
0.425
|
||||
],
|
||||
"b": [
|
||||
0.620833333,
|
||||
0.541666667
|
||||
]
|
||||
},
|
||||
{
|
||||
"a": [
|
||||
0.691666667,
|
||||
0.454166667
|
||||
],
|
||||
"b": [
|
||||
0.691666667,
|
||||
0.55
|
||||
]
|
||||
}
|
||||
],
|
||||
"openings": [],
|
||||
"wall_columns": [
|
||||
{
|
||||
"id": "column_column_column_column-msjeztk0_5a939_96c417e2",
|
||||
"shape": "square",
|
||||
"center": [
|
||||
0.4,
|
||||
0.441666667
|
||||
],
|
||||
"cm": 15
|
||||
},
|
||||
{
|
||||
"id": "column-mt1olibe",
|
||||
"shape": "square",
|
||||
"center": [
|
||||
0.416666667,
|
||||
0.345833333
|
||||
],
|
||||
"cm": 29
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -369,3 +369,52 @@ test('модели проекта не несут шума решётки (#282)
|
||||
+ `${profile.worstNoise ? ` — ${profile.worstNoise.owner}` : ''}`);
|
||||
}
|
||||
});
|
||||
|
||||
// ------------------ реальные планы как фикстуры (#285, #286) -----------------
|
||||
// Синтетика не воспроизводит два класса сразу: координатный шум и конфигурации
|
||||
// живого плана. Здесь закреплены свойства, ради которых эти фикстуры и лежат в
|
||||
// репозитории. Если кто-то «почистит» их координаты, фикстуры потеряют смысл —
|
||||
// и тест скажет об этом раньше, чем это выяснится через месяц.
|
||||
|
||||
const REAL_PLANS = [
|
||||
{ file: 'real-plan-first-floor.json', minNoise: 100, zeroThicknessSolidEdges: 2 },
|
||||
{ file: 'real-plan-second-floor.json', minNoise: 100, zeroThicknessSolidEdges: 0 },
|
||||
];
|
||||
|
||||
test('реальные планы сохраняют координатный шум, ради которого их взяли (#286)', () => {
|
||||
for (const plan of REAL_PLANS) {
|
||||
const { space } = JSON.parse(
|
||||
readFileSync(resolve(repoRoot, 'test/fixtures', plan.file), 'utf8'));
|
||||
const profile = latticeProfile({ config: { spaces: [space] }, layout: {} });
|
||||
assert.ok(profile.noise >= plan.minNoise,
|
||||
`${plan.file}: шума ${profile.noise}, ожидалось не меньше ${plan.minNoise} —`
|
||||
+ ' фикстура канонизирована и больше не воспроизводит свой класс дефектов');
|
||||
assert.equal(checkWallKeys({ spaces: [space] }, { notes: [] }).length, 0,
|
||||
`${plan.file}: запись толщины объявлена неразрешимой`);
|
||||
}
|
||||
});
|
||||
|
||||
test('реальные планы: сплошные рёбра без записи толщины закреплены числом (#286)', async () => {
|
||||
// Ребро, объявленное сплошным, но с нулевой толщиной, рисуется без кладки.
|
||||
// На первом этаже таких два, длиной по 2 шага, и соседние тела их накрывают —
|
||||
// поэтому браузерный смок разрывов не видит. Число закреплено здесь: станет
|
||||
// больше или короче накрытие — увидим до того, как это станет дыркой.
|
||||
const { spaceModels, GRID_STEP_N, GRID_PITCH, NORM_W } =
|
||||
await import('../test-build/space-geometry.js');
|
||||
const { wallIntervals } = await import('../test-build/wall-thickness.js');
|
||||
const { resolveOpenCuts } = await import('../test-build/open-spans.js');
|
||||
for (const plan of REAL_PLANS) {
|
||||
const { space } = JSON.parse(
|
||||
readFileSync(resolve(repoRoot, 'test/fixtures', plan.file), 'utf8'));
|
||||
const model = spaceModels({ spaces: [space], markers: [], settings: {} })[0];
|
||||
const cuts = resolveOpenCuts(
|
||||
model.rooms, space.open_spans ?? null, NORM_W, GRID_PITCH * 0.02, true);
|
||||
const intervals = wallIntervals(
|
||||
model.rooms, space.walls, cuts, GRID_STEP_N,
|
||||
space.cell_cm || 5, GRID_PITCH, NORM_W);
|
||||
const zero = intervals.filter((item) => item.kind && !(item.cm > 0));
|
||||
assert.equal(zero.length, plan.zeroThicknessSolidEdges,
|
||||
`${plan.file}: сплошных рёбер без толщины ${zero.length},`
|
||||
+ ` ожидалось ${plan.zeroThicknessSolidEdges}`);
|
||||
}
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user