@ifc-lite/rules 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +373 -0
- package/README.md +45 -0
- package/dist/engine/rule-engine-chunk.d.ts +25 -0
- package/dist/engine/rule-engine-chunk.d.ts.map +1 -0
- package/dist/engine/rule-engine-chunk.js +43 -0
- package/dist/engine/rule-engine-chunk.js.map +1 -0
- package/dist/engine/rule-engine-compare.d.ts +17 -0
- package/dist/engine/rule-engine-compare.d.ts.map +1 -0
- package/dist/engine/rule-engine-compare.js +69 -0
- package/dist/engine/rule-engine-compare.js.map +1 -0
- package/dist/engine/rule-engine-requirements.d.ts +37 -0
- package/dist/engine/rule-engine-requirements.d.ts.map +1 -0
- package/dist/engine/rule-engine-requirements.js +293 -0
- package/dist/engine/rule-engine-requirements.js.map +1 -0
- package/dist/engine/rule-engine-sets.d.ts +46 -0
- package/dist/engine/rule-engine-sets.d.ts.map +1 -0
- package/dist/engine/rule-engine-sets.js +298 -0
- package/dist/engine/rule-engine-sets.js.map +1 -0
- package/dist/engine/rule-engine-unit.d.ts +23 -0
- package/dist/engine/rule-engine-unit.d.ts.map +1 -0
- package/dist/engine/rule-engine-unit.js +64 -0
- package/dist/engine/rule-engine-unit.js.map +1 -0
- package/dist/engine/rule-engine.d.ts +29 -0
- package/dist/engine/rule-engine.d.ts.map +1 -0
- package/dist/engine/rule-engine.js +244 -0
- package/dist/engine/rule-engine.js.map +1 -0
- package/dist/filter/effective-filter-fields.d.ts +13 -0
- package/dist/filter/effective-filter-fields.d.ts.map +1 -0
- package/dist/filter/effective-filter-fields.js +44 -0
- package/dist/filter/effective-filter-fields.js.map +1 -0
- package/dist/filter/entity-predefined-type.d.ts +24 -0
- package/dist/filter/entity-predefined-type.d.ts.map +1 -0
- package/dist/filter/entity-predefined-type.js +34 -0
- package/dist/filter/entity-predefined-type.js.map +1 -0
- package/dist/filter/filter-evaluate-groups.d.ts +36 -0
- package/dist/filter/filter-evaluate-groups.d.ts.map +1 -0
- package/dist/filter/filter-evaluate-groups.js +111 -0
- package/dist/filter/filter-evaluate-groups.js.map +1 -0
- package/dist/filter/filter-evaluate-model-tag.d.ts +22 -0
- package/dist/filter/filter-evaluate-model-tag.d.ts.map +1 -0
- package/dist/filter/filter-evaluate-model-tag.js +35 -0
- package/dist/filter/filter-evaluate-model-tag.js.map +1 -0
- package/dist/filter/filter-evaluate-mutations.d.ts +51 -0
- package/dist/filter/filter-evaluate-mutations.d.ts.map +1 -0
- package/dist/filter/filter-evaluate-mutations.js +111 -0
- package/dist/filter/filter-evaluate-mutations.js.map +1 -0
- package/dist/filter/filter-evaluate-yield.d.ts +9 -0
- package/dist/filter/filter-evaluate-yield.d.ts.map +1 -0
- package/dist/filter/filter-evaluate-yield.js +32 -0
- package/dist/filter/filter-evaluate-yield.js.map +1 -0
- package/dist/filter/filter-evaluate.d.ts +120 -0
- package/dist/filter/filter-evaluate.d.ts.map +1 -0
- package/dist/filter/filter-evaluate.js +408 -0
- package/dist/filter/filter-evaluate.js.map +1 -0
- package/dist/filter/filter-group-rule.d.ts +23 -0
- package/dist/filter/filter-group-rule.d.ts.map +1 -0
- package/dist/filter/filter-group-rule.js +69 -0
- package/dist/filter/filter-group-rule.js.map +1 -0
- package/dist/filter/filter-groups.d.ts +65 -0
- package/dist/filter/filter-groups.d.ts.map +1 -0
- package/dist/filter/filter-groups.js +136 -0
- package/dist/filter/filter-groups.js.map +1 -0
- package/dist/filter/filter-iteration-source.d.ts +26 -0
- package/dist/filter/filter-iteration-source.d.ts.map +1 -0
- package/dist/filter/filter-iteration-source.js +154 -0
- package/dist/filter/filter-iteration-source.js.map +1 -0
- package/dist/filter/filter-iteration.d.ts +5 -0
- package/dist/filter/filter-iteration.d.ts.map +1 -0
- package/dist/filter/filter-iteration.js +25 -0
- package/dist/filter/filter-iteration.js.map +1 -0
- package/dist/filter/filter-match.d.ts +114 -0
- package/dist/filter/filter-match.d.ts.map +1 -0
- package/dist/filter/filter-match.js +302 -0
- package/dist/filter/filter-match.js.map +1 -0
- package/dist/filter/filter-ops.d.ts +90 -0
- package/dist/filter/filter-ops.d.ts.map +1 -0
- package/dist/filter/filter-ops.js +202 -0
- package/dist/filter/filter-ops.js.map +1 -0
- package/dist/filter/filter-rule-guards.d.ts +4 -0
- package/dist/filter/filter-rule-guards.d.ts.map +1 -0
- package/dist/filter/filter-rule-guards.js +74 -0
- package/dist/filter/filter-rule-guards.js.map +1 -0
- package/dist/filter/filter-rules.d.ts +275 -0
- package/dist/filter/filter-rules.d.ts.map +1 -0
- package/dist/filter/filter-rules.js +68 -0
- package/dist/filter/filter-rules.js.map +1 -0
- package/dist/filter/lens-material-names.d.ts +13 -0
- package/dist/filter/lens-material-names.d.ts.map +1 -0
- package/dist/filter/lens-material-names.js +36 -0
- package/dist/filter/lens-material-names.js.map +1 -0
- package/dist/filter/measure-units.d.ts +29 -0
- package/dist/filter/measure-units.d.ts.map +1 -0
- package/dist/filter/measure-units.js +72 -0
- package/dist/filter/measure-units.js.map +1 -0
- package/dist/filter/model-tag.d.ts +65 -0
- package/dist/filter/model-tag.d.ts.map +1 -0
- package/dist/filter/model-tag.js +57 -0
- package/dist/filter/model-tag.js.map +1 -0
- package/dist/filter/read-measure-subject.d.ts +28 -0
- package/dist/filter/read-measure-subject.d.ts.map +1 -0
- package/dist/filter/read-measure-subject.js +116 -0
- package/dist/filter/read-measure-subject.js.map +1 -0
- package/dist/filter/read-subject.d.ts +72 -0
- package/dist/filter/read-subject.d.ts.map +1 -0
- package/dist/filter/read-subject.js +128 -0
- package/dist/filter/read-subject.js.map +1 -0
- package/dist/filter/subject-match.d.ts +27 -0
- package/dist/filter/subject-match.d.ts.map +1 -0
- package/dist/filter/subject-match.js +52 -0
- package/dist/filter/subject-match.js.map +1 -0
- package/dist/filter/subject-read-options.d.ts +33 -0
- package/dist/filter/subject-read-options.d.ts.map +1 -0
- package/dist/filter/subject-read-options.js +8 -0
- package/dist/filter/subject-read-options.js.map +1 -0
- package/dist/ids/ids-facet-to-rules.d.ts +20 -0
- package/dist/ids/ids-facet-to-rules.d.ts.map +1 -0
- package/dist/ids/ids-facet-to-rules.js +230 -0
- package/dist/ids/ids-facet-to-rules.js.map +1 -0
- package/dist/ids/ids-regex.d.ts +44 -0
- package/dist/ids/ids-regex.d.ts.map +1 -0
- package/dist/ids/ids-regex.js +334 -0
- package/dist/ids/ids-regex.js.map +1 -0
- package/dist/ids/ids-to-rule-set.d.ts +39 -0
- package/dist/ids/ids-to-rule-set.d.ts.map +1 -0
- package/dist/ids/ids-to-rule-set.js +103 -0
- package/dist/ids/ids-to-rule-set.js.map +1 -0
- package/dist/ids/ids-xml-writer.d.ts +11 -0
- package/dist/ids/ids-xml-writer.d.ts.map +1 -0
- package/dist/ids/ids-xml-writer.js +172 -0
- package/dist/ids/ids-xml-writer.js.map +1 -0
- package/dist/ids/rule-set-to-ids.d.ts +45 -0
- package/dist/ids/rule-set-to-ids.d.ts.map +1 -0
- package/dist/ids/rule-set-to-ids.js +140 -0
- package/dist/ids/rule-set-to-ids.js.map +1 -0
- package/dist/ids/rule-to-ids-facets.d.ts +52 -0
- package/dist/ids/rule-to-ids-facets.d.ts.map +1 -0
- package/dist/ids/rule-to-ids-facets.js +291 -0
- package/dist/ids/rule-to-ids-facets.js.map +1 -0
- package/dist/ids/stored-unit-scale.d.ts +15 -0
- package/dist/ids/stored-unit-scale.d.ts.map +1 -0
- package/dist/ids/stored-unit-scale.js +64 -0
- package/dist/ids/stored-unit-scale.js.map +1 -0
- package/dist/index.d.ts +39 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +46 -0
- package/dist/index.js.map +1 -0
- package/dist/rule-set/between-chip.d.ts +54 -0
- package/dist/rule-set/between-chip.d.ts.map +1 -0
- package/dist/rule-set/between-chip.js +95 -0
- package/dist/rule-set/between-chip.js.map +1 -0
- package/dist/rule-set/requirement-invariants.d.ts +25 -0
- package/dist/rule-set/requirement-invariants.d.ts.map +1 -0
- package/dist/rule-set/requirement-invariants.js +29 -0
- package/dist/rule-set/requirement-invariants.js.map +1 -0
- package/dist/rule-set/requirement-text.d.ts +20 -0
- package/dist/rule-set/requirement-text.d.ts.map +1 -0
- package/dist/rule-set/requirement-text.js +179 -0
- package/dist/rule-set/requirement-text.js.map +1 -0
- package/dist/rule-set/rule-set-io-requirement.d.ts +22 -0
- package/dist/rule-set/rule-set-io-requirement.d.ts.map +1 -0
- package/dist/rule-set/rule-set-io-requirement.js +140 -0
- package/dist/rule-set/rule-set-io-requirement.js.map +1 -0
- package/dist/rule-set/rule-set-io-shared.d.ts +24 -0
- package/dist/rule-set/rule-set-io-shared.d.ts.map +1 -0
- package/dist/rule-set/rule-set-io-shared.js +48 -0
- package/dist/rule-set/rule-set-io-shared.js.map +1 -0
- package/dist/rule-set/rule-set-io-subject.d.ts +10 -0
- package/dist/rule-set/rule-set-io-subject.d.ts.map +1 -0
- package/dist/rule-set/rule-set-io-subject.js +67 -0
- package/dist/rule-set/rule-set-io-subject.js.map +1 -0
- package/dist/rule-set/rule-set-io.d.ts +37 -0
- package/dist/rule-set/rule-set-io.d.ts.map +1 -0
- package/dist/rule-set/rule-set-io.js +142 -0
- package/dist/rule-set/rule-set-io.js.map +1 -0
- package/dist/rule-set/rule-set.d.ts +109 -0
- package/dist/rule-set/rule-set.d.ts.map +1 -0
- package/dist/rule-set/rule-set.js +5 -0
- package/dist/rule-set/rule-set.js.map +1 -0
- package/package.json +59 -0
|
@@ -0,0 +1,293 @@
|
|
|
1
|
+
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
2
|
+
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
3
|
+
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
|
4
|
+
import { combineRuleResults, } from '../filter/filter-rules.js';
|
|
5
|
+
import { readSubject } from '../filter/read-subject.js';
|
|
6
|
+
import { toSiValues } from '../filter/subject-match.js';
|
|
7
|
+
import { matchStringAnyNone, numericOpMatches, setOpMatches, stringOpMatches, valueOpMatches, } from '../filter/filter-ops.js';
|
|
8
|
+
/** Shared with `rule-engine-sets.ts` (compare/aggregate render the same
|
|
9
|
+
* `op` vocabulary). */
|
|
10
|
+
export const OP_LABEL = {
|
|
11
|
+
eq: '=', ne: '!=', gt: '>', gte: '>=', lt: '<', lte: '<=',
|
|
12
|
+
contains: 'contains', notContains: 'not contains', startsWith: 'starts with',
|
|
13
|
+
matches: 'matches', notMatches: 'not matches',
|
|
14
|
+
};
|
|
15
|
+
function actualOf(subject) {
|
|
16
|
+
// `present === false` covers BOTH a genuinely empty `values` array and one
|
|
17
|
+
// whose only entries are `''`/whitespace (plan §4.2's "empty string is
|
|
18
|
+
// absent" — an explicitly empty `IFCLABEL` renders the same `'""'` an
|
|
19
|
+
// outright-missing property does, not a blank string).
|
|
20
|
+
if (!subject.present)
|
|
21
|
+
return '""';
|
|
22
|
+
const joined = subject.values.map(String).join('; ');
|
|
23
|
+
return subject.unit ? `${joined} ${subject.unit}` : joined;
|
|
24
|
+
}
|
|
25
|
+
function subjectLabel(rule) {
|
|
26
|
+
switch (rule.kind) {
|
|
27
|
+
case 'property': return `${rule.setName}.${rule.propertyName}`;
|
|
28
|
+
case 'quantity': return `${rule.setName}.${rule.quantityName}`;
|
|
29
|
+
case 'attribute': return rule.name;
|
|
30
|
+
case 'name': return 'Name';
|
|
31
|
+
case 'type': return 'Type';
|
|
32
|
+
case 'parent': return 'Parent';
|
|
33
|
+
case 'material': return 'Material';
|
|
34
|
+
case 'classification': return rule.system ? `Classification[${rule.system}]` : 'Classification';
|
|
35
|
+
case 'group': return rule.groupClass ? `Group[${rule.groupClass}]` : 'Group';
|
|
36
|
+
case 'ifcType': return 'IfcType';
|
|
37
|
+
case 'predefinedType': return 'PredefinedType';
|
|
38
|
+
default: return rule.kind;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
/** Maps a `FilterRule` kind onto the closed `CheckKind` reporting vocabulary
|
|
42
|
+
* (plan §5). Several kinds have no dedicated IDS facet type; the closest
|
|
43
|
+
* fit is used and documented here rather than invented silently:
|
|
44
|
+
* `attribute`/`name`/`type`/`globalId` → `attribute` (all read an IFC
|
|
45
|
+
* attribute), `parent` → `partOf` (bSI's containment/aggregation facet),
|
|
46
|
+
* `ifcType`/`predefinedType` → `entity` (bSI's entity facet covers both),
|
|
47
|
+
* `storey` → `spatial` (a `CheckKind`-only addition with no facet analogue). */
|
|
48
|
+
function checkKindOf(kind) {
|
|
49
|
+
switch (kind) {
|
|
50
|
+
case 'property': return 'property';
|
|
51
|
+
case 'quantity': return 'quantity';
|
|
52
|
+
case 'attribute':
|
|
53
|
+
case 'name':
|
|
54
|
+
case 'type':
|
|
55
|
+
case 'globalId':
|
|
56
|
+
return 'attribute';
|
|
57
|
+
case 'material': return 'material';
|
|
58
|
+
case 'classification': return 'classification';
|
|
59
|
+
case 'parent':
|
|
60
|
+
case 'group':
|
|
61
|
+
return 'partOf';
|
|
62
|
+
case 'ifcType':
|
|
63
|
+
case 'predefinedType':
|
|
64
|
+
return 'entity';
|
|
65
|
+
case 'storey': return 'spatial';
|
|
66
|
+
default: return 'attribute';
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
function renderExpected(rule) {
|
|
70
|
+
switch (rule.kind) {
|
|
71
|
+
case 'quantity':
|
|
72
|
+
return `${OP_LABEL[rule.op]} ${rule.value}`;
|
|
73
|
+
case 'property':
|
|
74
|
+
case 'attribute':
|
|
75
|
+
case 'name':
|
|
76
|
+
case 'type':
|
|
77
|
+
case 'parent':
|
|
78
|
+
case 'material':
|
|
79
|
+
case 'classification':
|
|
80
|
+
case 'group':
|
|
81
|
+
return `${OP_LABEL[rule.op] ?? rule.op} ${'value' in rule ? rule.value : ''}`;
|
|
82
|
+
case 'ifcType':
|
|
83
|
+
case 'predefinedType':
|
|
84
|
+
return `${rule.op === 'in' ? 'in' : 'not in'} [${rule.values.join(', ')}]`;
|
|
85
|
+
default:
|
|
86
|
+
return 'op' in rule ? String(rule.op) : '';
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
function isElementRule(rule) {
|
|
90
|
+
switch (rule.kind) {
|
|
91
|
+
case 'property':
|
|
92
|
+
case 'quantity':
|
|
93
|
+
case 'attribute':
|
|
94
|
+
case 'name':
|
|
95
|
+
case 'type':
|
|
96
|
+
case 'parent':
|
|
97
|
+
case 'material':
|
|
98
|
+
case 'classification':
|
|
99
|
+
case 'ifcType':
|
|
100
|
+
case 'predefinedType':
|
|
101
|
+
case 'group':
|
|
102
|
+
return true;
|
|
103
|
+
default:
|
|
104
|
+
return false;
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
function checkFilterRule(rule, ctx, opts) {
|
|
108
|
+
// `valueUnit: 'si'` (#5225): compare SI values, the same reading search uses.
|
|
109
|
+
const subject = (rule.kind === 'property' || rule.kind === 'quantity') && rule.valueUnit === 'si'
|
|
110
|
+
? toSiValues(readSubject(rule, ctx))
|
|
111
|
+
: readSubject(rule, ctx);
|
|
112
|
+
const facetType = checkKindOf(rule.kind);
|
|
113
|
+
const label = subjectLabel(rule);
|
|
114
|
+
const actual = actualOf(subject);
|
|
115
|
+
if (rule.op === 'isSet' || rule.op === 'isNotSet') {
|
|
116
|
+
const passed = rule.op === 'isSet' ? subject.present : !subject.present;
|
|
117
|
+
const expected = rule.op === 'isSet' ? 'is set' : 'is not set';
|
|
118
|
+
return { passed, reason: passed ? undefined : 'absent', actual, expected, facetType, checkedDescription: `${label} ${expected}` };
|
|
119
|
+
}
|
|
120
|
+
const expected = renderExpected(rule);
|
|
121
|
+
const checkedDescription = `${label} ${expected}`;
|
|
122
|
+
if (!subject.present) {
|
|
123
|
+
return { passed: false, reason: 'absent', actual, expected, facetType, checkedDescription };
|
|
124
|
+
}
|
|
125
|
+
switch (rule.kind) {
|
|
126
|
+
case 'quantity': {
|
|
127
|
+
const nums = subject.values.map(Number).filter(Number.isFinite);
|
|
128
|
+
if (nums.length === 0)
|
|
129
|
+
return { passed: false, reason: 'notNumeric', actual, expected, facetType, checkedDescription };
|
|
130
|
+
const passed = nums.some((v) => numericOpMatches(rule.op, v, rule.value, opts));
|
|
131
|
+
return { passed, reason: passed ? undefined : 'mismatch', actual, expected, facetType, checkedDescription };
|
|
132
|
+
}
|
|
133
|
+
case 'property':
|
|
134
|
+
case 'attribute':
|
|
135
|
+
return checkValueOp(rule, subject, opts, facetType, actual, expected, checkedDescription);
|
|
136
|
+
case 'ifcType':
|
|
137
|
+
case 'predefinedType': {
|
|
138
|
+
const candidate = String(subject.values[0] ?? '');
|
|
139
|
+
const passed = setOpMatches(rule.op, candidate, rule.values, opts);
|
|
140
|
+
return { passed, reason: passed ? undefined : 'mismatch', actual, expected, facetType, checkedDescription };
|
|
141
|
+
}
|
|
142
|
+
default: {
|
|
143
|
+
// name | type | parent | material | classification | group — StringOp (or the
|
|
144
|
+
// StringOp-compatible subset of ClassificationOp); multi-valued
|
|
145
|
+
// subjects (parent/material) match ANY for a positive op, NONE for a
|
|
146
|
+
// negative one, via the same convention search already uses.
|
|
147
|
+
const candidates = subject.values.map(String);
|
|
148
|
+
const passed = matchStringAnyNone(rule.op, candidates, rule.value, rule.valueKind, opts);
|
|
149
|
+
return { passed, reason: passed ? undefined : 'mismatch', actual, expected, facetType, checkedDescription };
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
function checkValueOp(rule, subject, opts, facetType, actual, expected, checkedDescription) {
|
|
154
|
+
const strVals = subject.values.map(String);
|
|
155
|
+
const op = rule.op;
|
|
156
|
+
if (op === 'gt' || op === 'gte' || op === 'lt' || op === 'lte') {
|
|
157
|
+
// Strict `Number(...)`, not `Number.parseFloat` — plan §4 item 4 requires
|
|
158
|
+
// a "finite f64", and `parseFloat('2HR')` (== 2) would silently accept a
|
|
159
|
+
// fire-rating STRING as a number instead of reporting `notNumeric`.
|
|
160
|
+
const rv = Number(rule.value);
|
|
161
|
+
const nums = strVals.map((v) => Number(v)).filter(Number.isFinite);
|
|
162
|
+
if (!Number.isFinite(rv) || nums.length === 0) {
|
|
163
|
+
return { passed: false, reason: 'notNumeric', actual, expected, facetType, checkedDescription };
|
|
164
|
+
}
|
|
165
|
+
const passed = nums.some((cv) => numericOpMatches(op, cv, rv, opts));
|
|
166
|
+
return { passed, reason: passed ? undefined : 'mismatch', actual, expected, facetType, checkedDescription };
|
|
167
|
+
}
|
|
168
|
+
if (op === 'eq' || op === 'ne') {
|
|
169
|
+
const rv = Number(rule.value);
|
|
170
|
+
const nums = strVals.map((v) => Number(v));
|
|
171
|
+
const allFinite = Number.isFinite(rv) && nums.length > 0 && nums.every(Number.isFinite);
|
|
172
|
+
const matchAny = allFinite
|
|
173
|
+
? nums.some((cv) => numericOpMatches('eq', cv, rv, opts))
|
|
174
|
+
: strVals.some((v) => stringOpMatches('eq', v, rule.value, undefined, opts));
|
|
175
|
+
const passed = op === 'eq' ? matchAny : !matchAny;
|
|
176
|
+
return { passed, reason: passed ? undefined : 'mismatch', actual, expected, facetType, checkedDescription };
|
|
177
|
+
}
|
|
178
|
+
// contains / notContains / matches / notMatches
|
|
179
|
+
const posOp = op === 'notContains' ? 'contains' : op === 'notMatches' ? 'matches' : op;
|
|
180
|
+
const anyPositive = strVals.some((v) => valueOpMatches(posOp, v, rule.value, rule.valueKind, opts));
|
|
181
|
+
const passed = posOp === op ? anyPositive : !anyPositive;
|
|
182
|
+
return { passed, reason: passed ? undefined : 'mismatch', actual, expected, facetType, checkedDescription };
|
|
183
|
+
}
|
|
184
|
+
function subjectKey(rule) {
|
|
185
|
+
switch (rule.kind) {
|
|
186
|
+
case 'quantity': return `quantity:${rule.setName}:${rule.quantityName}`;
|
|
187
|
+
case 'property': return `property:${rule.setName}:${rule.propertyName}`;
|
|
188
|
+
case 'attribute': return `attribute:${rule.name}`;
|
|
189
|
+
default: return null;
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
function foldBetweenPairs(rules) {
|
|
193
|
+
const used = new Set();
|
|
194
|
+
const out = [];
|
|
195
|
+
for (let i = 0; i < rules.length; i++) {
|
|
196
|
+
if (used.has(i))
|
|
197
|
+
continue;
|
|
198
|
+
const a = rules[i];
|
|
199
|
+
const keyA = subjectKey(a);
|
|
200
|
+
const opA = 'op' in a ? a.op : undefined;
|
|
201
|
+
if (keyA && (opA === 'gte' || opA === 'lte')) {
|
|
202
|
+
for (let j = i + 1; j < rules.length; j++) {
|
|
203
|
+
if (used.has(j))
|
|
204
|
+
continue;
|
|
205
|
+
const b = rules[j];
|
|
206
|
+
if (subjectKey(b) !== keyA)
|
|
207
|
+
continue;
|
|
208
|
+
const opB = 'op' in b ? b.op : undefined;
|
|
209
|
+
if ((opA === 'gte' && opB === 'lte') || (opA === 'lte' && opB === 'gte')) {
|
|
210
|
+
used.add(i);
|
|
211
|
+
used.add(j);
|
|
212
|
+
out.push({ kind: 'between', low: opA === 'gte' ? a : b, high: opA === 'lte' ? a : b });
|
|
213
|
+
break;
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
for (let i = 0; i < rules.length; i++)
|
|
219
|
+
if (!used.has(i))
|
|
220
|
+
out.push(rules[i]);
|
|
221
|
+
return out;
|
|
222
|
+
}
|
|
223
|
+
function evaluateBetween(pair, ctx, opts) {
|
|
224
|
+
const low = checkFilterRule(pair.low, ctx, opts);
|
|
225
|
+
const high = checkFilterRule(pair.high, ctx, opts);
|
|
226
|
+
const passed = low.passed && high.passed;
|
|
227
|
+
const label = subjectLabel(pair.low);
|
|
228
|
+
const lowVal = 'value' in pair.low ? pair.low.value : '';
|
|
229
|
+
const highVal = 'value' in pair.high ? pair.high.value : '';
|
|
230
|
+
const expected = `>= ${lowVal} and <= ${highVal}`;
|
|
231
|
+
return {
|
|
232
|
+
passed,
|
|
233
|
+
reason: passed ? undefined : (low.reason ?? high.reason),
|
|
234
|
+
actual: low.actual,
|
|
235
|
+
expected,
|
|
236
|
+
facetType: low.facetType,
|
|
237
|
+
checkedDescription: `${label} ${expected}`,
|
|
238
|
+
};
|
|
239
|
+
}
|
|
240
|
+
function evaluateGroup(group, ctx, opts) {
|
|
241
|
+
const elementRules = group.rules.filter(isElementRule);
|
|
242
|
+
if (elementRules.length !== group.rules.length) {
|
|
243
|
+
throw new Error(`rule-engine: applicability-only rule kind used in an element requirement (group has ${group.rules.length - elementRules.length} such rule(s))`);
|
|
244
|
+
}
|
|
245
|
+
// `between` is a gte+lte pair AND'd on the identical subject (plan §5's
|
|
246
|
+
// operator table) — only a shorthand within an AND group. In an OR group
|
|
247
|
+
// the two rules are independent alternatives (`Width >= 0.25` OR `Width
|
|
248
|
+
// <= 0.35` — 0.20 satisfies the second on its own), so folding them would
|
|
249
|
+
// silently require BOTH, changing what the group matches (review finding).
|
|
250
|
+
const items = group.combinator === 'AND' ? foldBetweenPairs(elementRules) : elementRules;
|
|
251
|
+
const outcomes = items.map((item) => 'kind' in item && item.kind === 'between' ? evaluateBetween(item, ctx, opts) : checkFilterRule(item, ctx, opts));
|
|
252
|
+
if (outcomes.length === 0)
|
|
253
|
+
return { passed: false, failingCount: 0, representative: { passed: false, actual: '', expected: '', facetType: 'attribute', checkedDescription: 'empty group' } };
|
|
254
|
+
const passed = combineRuleResults(group.combinator, outcomes.map((o) => o.passed));
|
|
255
|
+
const failingCount = outcomes.filter((o) => !o.passed).length;
|
|
256
|
+
const representative = outcomes.find((o) => !o.passed) ?? outcomes[0];
|
|
257
|
+
return { passed, failingCount, representative };
|
|
258
|
+
}
|
|
259
|
+
/**
|
|
260
|
+
* Check one applicable element against `block` (plan §4.4). `requirementId`/
|
|
261
|
+
* `requirementLabel` seed the singular `requirementResults[0]` every entity
|
|
262
|
+
* row carries — the rule's own id/name, since one `InformationRule`'s
|
|
263
|
+
* `element` requirement is ONE requirement, not one per underlying
|
|
264
|
+
* `FilterRule` (a `between` pair, or several AND'd rules in a group, are
|
|
265
|
+
* still a single pass/fail question).
|
|
266
|
+
*/
|
|
267
|
+
export function checkElementForEntity(requirementId, block, el, store, opts) {
|
|
268
|
+
const ctx = { store, expressId: el.expressId };
|
|
269
|
+
const groupOutcomes = block.groups.map((g) => evaluateGroup(g, ctx, opts));
|
|
270
|
+
const passedGroup = groupOutcomes.find((g) => g.passed);
|
|
271
|
+
const chosen = passedGroup
|
|
272
|
+
?? groupOutcomes.reduce((best, g) => (g.failingCount < best.failingCount ? g : best), groupOutcomes[0]);
|
|
273
|
+
const passed = !!passedGroup;
|
|
274
|
+
const requirementResult = {
|
|
275
|
+
requirement: { id: requirementId, label: chosen.representative.checkedDescription, optionality: 'required' },
|
|
276
|
+
status: passed ? 'pass' : 'fail',
|
|
277
|
+
facetType: chosen.representative.facetType,
|
|
278
|
+
checkedDescription: chosen.representative.checkedDescription,
|
|
279
|
+
failureReason: passed ? undefined : chosen.representative.reason,
|
|
280
|
+
actualValue: chosen.representative.actual,
|
|
281
|
+
expectedValue: chosen.representative.expected,
|
|
282
|
+
};
|
|
283
|
+
return {
|
|
284
|
+
expressId: el.expressId,
|
|
285
|
+
modelId: el.modelId,
|
|
286
|
+
entityType: el.ifcType,
|
|
287
|
+
entityName: el.name || undefined,
|
|
288
|
+
globalId: el.globalId,
|
|
289
|
+
passed,
|
|
290
|
+
requirementResults: [requirementResult],
|
|
291
|
+
};
|
|
292
|
+
}
|
|
293
|
+
//# sourceMappingURL=rule-engine-requirements.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rule-engine-requirements.js","sourceRoot":"","sources":["../../src/engine/rule-engine-requirements.ts"],"names":[],"mappings":"AAAA;;+DAE+D;AAsB/D,OAAO,EACL,kBAAkB,GAenB,MAAM,2BAA2B,CAAC;AAGnC,OAAO,EAAE,WAAW,EAA8C,MAAM,2BAA2B,CAAC;AACpG,OAAO,EAAE,UAAU,EAAE,MAAM,4BAA4B,CAAC;AACxD,OAAO,EACL,kBAAkB,EAClB,gBAAgB,EAChB,YAAY,EACZ,eAAe,EACf,cAAc,GAEf,MAAM,yBAAyB,CAAC;AAejC;wBACwB;AACxB,MAAM,CAAC,MAAM,QAAQ,GAA2B;IAC9C,EAAE,EAAE,GAAG,EAAE,EAAE,EAAE,IAAI,EAAE,EAAE,EAAE,GAAG,EAAE,GAAG,EAAE,IAAI,EAAE,EAAE,EAAE,GAAG,EAAE,GAAG,EAAE,IAAI;IACzD,QAAQ,EAAE,UAAU,EAAE,WAAW,EAAE,cAAc,EAAE,UAAU,EAAE,aAAa;IAC5E,OAAO,EAAE,SAAS,EAAE,UAAU,EAAE,aAAa;CAC9C,CAAC;AAEF,SAAS,QAAQ,CAAC,OAAqB;IACrC,2EAA2E;IAC3E,uEAAuE;IACvE,sEAAsE;IACtE,uDAAuD;IACvD,IAAI,CAAC,OAAO,CAAC,OAAO;QAAE,OAAO,IAAI,CAAC;IAClC,MAAM,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACrD,OAAO,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,MAAM,IAAI,OAAO,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC;AAC7D,CAAC;AAED,SAAS,YAAY,CAAC,IAAgB;IACpC,QAAQ,IAAI,CAAC,IAAI,EAAE,CAAC;QAClB,KAAK,UAAU,CAAC,CAAC,OAAO,GAAG,IAAI,CAAC,OAAO,IAAI,IAAI,CAAC,YAAY,EAAE,CAAC;QAC/D,KAAK,UAAU,CAAC,CAAC,OAAO,GAAG,IAAI,CAAC,OAAO,IAAI,IAAI,CAAC,YAAY,EAAE,CAAC;QAC/D,KAAK,WAAW,CAAC,CAAC,OAAO,IAAI,CAAC,IAAI,CAAC;QACnC,KAAK,MAAM,CAAC,CAAC,OAAO,MAAM,CAAC;QAC3B,KAAK,MAAM,CAAC,CAAC,OAAO,MAAM,CAAC;QAC3B,KAAK,QAAQ,CAAC,CAAC,OAAO,QAAQ,CAAC;QAC/B,KAAK,UAAU,CAAC,CAAC,OAAO,UAAU,CAAC;QACnC,KAAK,gBAAgB,CAAC,CAAC,OAAO,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,kBAAkB,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,gBAAgB,CAAC;QAChG,KAAK,OAAO,CAAC,CAAC,OAAO,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,SAAS,IAAI,CAAC,UAAU,GAAG,CAAC,CAAC,CAAC,OAAO,CAAC;QAC7E,KAAK,SAAS,CAAC,CAAC,OAAO,SAAS,CAAC;QACjC,KAAK,gBAAgB,CAAC,CAAC,OAAO,gBAAgB,CAAC;QAC/C,OAAO,CAAC,CAAC,OAAO,IAAI,CAAC,IAAI,CAAC;IAC5B,CAAC;AACH,CAAC;AAED;;;;;;iFAMiF;AACjF,SAAS,WAAW,CAAC,IAAwB;IAC3C,QAAQ,IAAI,EAAE,CAAC;QACb,KAAK,UAAU,CAAC,CAAC,OAAO,UAAU,CAAC;QACnC,KAAK,UAAU,CAAC,CAAC,OAAO,UAAU,CAAC;QACnC,KAAK,WAAW,CAAC;QACjB,KAAK,MAAM,CAAC;QACZ,KAAK,MAAM,CAAC;QACZ,KAAK,UAAU;YACb,OAAO,WAAW,CAAC;QACrB,KAAK,UAAU,CAAC,CAAC,OAAO,UAAU,CAAC;QACnC,KAAK,gBAAgB,CAAC,CAAC,OAAO,gBAAgB,CAAC;QAC/C,KAAK,QAAQ,CAAC;QACd,KAAK,OAAO;YACV,OAAO,QAAQ,CAAC;QAClB,KAAK,SAAS,CAAC;QACf,KAAK,gBAAgB;YACnB,OAAO,QAAQ,CAAC;QAClB,KAAK,QAAQ,CAAC,CAAC,OAAO,SAAS,CAAC;QAChC,OAAO,CAAC,CAAC,OAAO,WAAW,CAAC;IAC9B,CAAC;AACH,CAAC;AAED,SAAS,cAAc,CAAC,IAAgB;IACtC,QAAQ,IAAI,CAAC,IAAI,EAAE,CAAC;QAClB,KAAK,UAAU;YACb,OAAO,GAAG,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,IAAI,CAAC,KAAK,EAAE,CAAC;QAC9C,KAAK,UAAU,CAAC;QAChB,KAAK,WAAW,CAAC;QACjB,KAAK,MAAM,CAAC;QACZ,KAAK,MAAM,CAAC;QACZ,KAAK,QAAQ,CAAC;QACd,KAAK,UAAU,CAAC;QAChB,KAAK,gBAAgB,CAAC;QACtB,KAAK,OAAO;YACV,OAAO,GAAG,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,IAAI,CAAC,EAAE,IAAI,OAAO,IAAI,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC;QAChF,KAAK,SAAS,CAAC;QACf,KAAK,gBAAgB;YACnB,OAAO,GAAG,IAAI,CAAC,EAAE,KAAK,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,QAAQ,KAAK,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC;QAC7E;YACE,OAAO,IAAI,IAAI,IAAI,CAAC,CAAC,CAAC,MAAM,CAAE,IAAwB,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;IACpE,CAAC;AACH,CAAC;AAWD,SAAS,aAAa,CAAC,IAAgB;IACrC,QAAQ,IAAI,CAAC,IAAI,EAAE,CAAC;QAClB,KAAK,UAAU,CAAC;QAAC,KAAK,UAAU,CAAC;QAAC,KAAK,WAAW,CAAC;QAAC,KAAK,MAAM,CAAC;QAAC,KAAK,MAAM,CAAC;QAC7E,KAAK,QAAQ,CAAC;QAAC,KAAK,UAAU,CAAC;QAAC,KAAK,gBAAgB,CAAC;QAAC,KAAK,SAAS,CAAC;QAAC,KAAK,gBAAgB,CAAC;QAC7F,KAAK,OAAO;YACV,OAAO,IAAI,CAAC;QACd;YACE,OAAO,KAAK,CAAC;IACjB,CAAC;AACH,CAAC;AAED,SAAS,eAAe,CAAC,IAAiB,EAAE,GAAuB,EAAE,IAAoB;IACvF,8EAA8E;IAC9E,MAAM,OAAO,GAAG,CAAC,IAAI,CAAC,IAAI,KAAK,UAAU,IAAI,IAAI,CAAC,IAAI,KAAK,UAAU,CAAC,IAAI,IAAI,CAAC,SAAS,KAAK,IAAI;QAC/F,CAAC,CAAC,UAAU,CAAC,WAAW,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;QACpC,CAAC,CAAC,WAAW,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;IAC3B,MAAM,SAAS,GAAG,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACzC,MAAM,KAAK,GAAG,YAAY,CAAC,IAAI,CAAC,CAAC;IACjC,MAAM,MAAM,GAAG,QAAQ,CAAC,OAAO,CAAC,CAAC;IAEjC,IAAI,IAAI,CAAC,EAAE,KAAK,OAAO,IAAI,IAAI,CAAC,EAAE,KAAK,UAAU,EAAE,CAAC;QAClD,MAAM,MAAM,GAAG,IAAI,CAAC,EAAE,KAAK,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC;QACxE,MAAM,QAAQ,GAAG,IAAI,CAAC,EAAE,KAAK,OAAO,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,YAAY,CAAC;QAC/D,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,SAAS,EAAE,kBAAkB,EAAE,GAAG,KAAK,IAAI,QAAQ,EAAE,EAAE,CAAC;IACpI,CAAC;IAED,MAAM,QAAQ,GAAG,cAAc,CAAC,IAAI,CAAC,CAAC;IACtC,MAAM,kBAAkB,GAAG,GAAG,KAAK,IAAI,QAAQ,EAAE,CAAC;IAClD,IAAI,CAAC,OAAO,CAAC,OAAO,EAAE,CAAC;QACrB,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,SAAS,EAAE,kBAAkB,EAAE,CAAC;IAC9F,CAAC;IAED,QAAQ,IAAI,CAAC,IAAI,EAAE,CAAC;QAClB,KAAK,UAAU,CAAC,CAAC,CAAC;YAChB,MAAM,IAAI,GAAG,OAAO,CAAC,MAAM,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;YAChE,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC;gBAAE,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,EAAE,QAAQ,EAAE,SAAS,EAAE,kBAAkB,EAAE,CAAC;YACvH,MAAM,MAAM,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,gBAAgB,CAAC,IAAI,CAAC,EAAE,EAAE,CAAC,EAAE,IAAI,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC,CAAC;YAChF,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,UAAU,EAAE,MAAM,EAAE,QAAQ,EAAE,SAAS,EAAE,kBAAkB,EAAE,CAAC;QAC9G,CAAC;QACD,KAAK,UAAU,CAAC;QAChB,KAAK,WAAW;YACd,OAAO,YAAY,CAAC,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,kBAAkB,CAAC,CAAC;QAC5F,KAAK,SAAS,CAAC;QACf,KAAK,gBAAgB,CAAC,CAAC,CAAC;YACtB,MAAM,SAAS,GAAG,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC;YAClD,MAAM,MAAM,GAAG,YAAY,CAAC,IAAI,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;YACnE,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,UAAU,EAAE,MAAM,EAAE,QAAQ,EAAE,SAAS,EAAE,kBAAkB,EAAE,CAAC;QAC9G,CAAC;QACD,OAAO,CAAC,CAAC,CAAC;YACR,8EAA8E;YAC9E,gEAAgE;YAChE,qEAAqE;YACrE,6DAA6D;YAC7D,MAAM,UAAU,GAAG,OAAO,CAAC,MAAM,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;YAC9C,MAAM,MAAM,GAAG,kBAAkB,CAAC,IAAI,CAAC,EAAE,EAAE,UAAU,EAAE,IAAI,CAAC,KAAK,EAAE,IAAI,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC;YACzF,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,UAAU,EAAE,MAAM,EAAE,QAAQ,EAAE,SAAS,EAAE,kBAAkB,EAAE,CAAC;QAC9G,CAAC;IACH,CAAC;AACH,CAAC;AAED,SAAS,YAAY,CACnB,IAAkC,EAClC,OAAqB,EACrB,IAAoB,EACpB,SAAoB,EACpB,MAAc,EACd,QAAgB,EAChB,kBAA0B;IAE1B,MAAM,OAAO,GAAG,OAAO,CAAC,MAAM,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;IAC3C,MAAM,EAAE,GAAG,IAAI,CAAC,EAA4C,CAAC;IAE7D,IAAI,EAAE,KAAK,IAAI,IAAI,EAAE,KAAK,KAAK,IAAI,EAAE,KAAK,IAAI,IAAI,EAAE,KAAK,KAAK,EAAE,CAAC;QAC/D,0EAA0E;QAC1E,yEAAyE;QACzE,oEAAoE;QACpE,MAAM,EAAE,GAAG,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAC9B,MAAM,IAAI,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;QACnE,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,EAAE,CAAC,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAC9C,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,EAAE,QAAQ,EAAE,SAAS,EAAE,kBAAkB,EAAE,CAAC;QAClG,CAAC;QACD,MAAM,MAAM,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,gBAAgB,CAAC,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,IAAI,CAAC,CAAC,CAAC;QACrE,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,UAAU,EAAE,MAAM,EAAE,QAAQ,EAAE,SAAS,EAAE,kBAAkB,EAAE,CAAC;IAC9G,CAAC;IACD,IAAI,EAAE,KAAK,IAAI,IAAI,EAAE,KAAK,IAAI,EAAE,CAAC;QAC/B,MAAM,EAAE,GAAG,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAC9B,MAAM,IAAI,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC;QAC3C,MAAM,SAAS,GAAG,MAAM,CAAC,QAAQ,CAAC,EAAE,CAAC,IAAI,IAAI,CAAC,MAAM,GAAG,CAAC,IAAI,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;QACxF,MAAM,QAAQ,GAAG,SAAS;YACxB,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,gBAAgB,CAAC,IAAI,EAAE,EAAE,EAAE,EAAE,EAAE,IAAI,CAAC,CAAC;YACzD,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,eAAe,CAAC,IAAI,EAAE,CAAC,EAAE,IAAI,CAAC,KAAK,EAAE,SAAS,EAAE,IAAI,CAAC,CAAC,CAAC;QAC/E,MAAM,MAAM,GAAG,EAAE,KAAK,IAAI,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC;QAClD,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,UAAU,EAAE,MAAM,EAAE,QAAQ,EAAE,SAAS,EAAE,kBAAkB,EAAE,CAAC;IAC9G,CAAC;IACD,gDAAgD;IAChD,MAAM,KAAK,GAAY,EAAE,KAAK,aAAa,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,EAAE,KAAK,YAAY,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC;IAChG,MAAM,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,cAAc,CAAC,KAAK,EAAE,CAAC,EAAE,IAAI,CAAC,KAAK,EAAE,IAAI,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC,CAAC;IACpG,MAAM,MAAM,GAAG,KAAK,KAAK,EAAE,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,WAAW,CAAC;IACzD,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,UAAU,EAAE,MAAM,EAAE,QAAQ,EAAE,SAAS,EAAE,kBAAkB,EAAE,CAAC;AAC9G,CAAC;AAOD,SAAS,UAAU,CAAC,IAAgB;IAClC,QAAQ,IAAI,CAAC,IAAI,EAAE,CAAC;QAClB,KAAK,UAAU,CAAC,CAAC,OAAO,YAAY,IAAI,CAAC,OAAO,IAAI,IAAI,CAAC,YAAY,EAAE,CAAC;QACxE,KAAK,UAAU,CAAC,CAAC,OAAO,YAAY,IAAI,CAAC,OAAO,IAAI,IAAI,CAAC,YAAY,EAAE,CAAC;QACxE,KAAK,WAAW,CAAC,CAAC,OAAO,aAAa,IAAI,CAAC,IAAI,EAAE,CAAC;QAClD,OAAO,CAAC,CAAC,OAAO,IAAI,CAAC;IACvB,CAAC;AACH,CAAC;AAED,SAAS,gBAAgB,CAAC,KAA6B;IACrD,MAAM,IAAI,GAAG,IAAI,GAAG,EAAU,CAAC;IAC/B,MAAM,GAAG,GAAgB,EAAE,CAAC;IAC5B,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACtC,IAAI,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;YAAE,SAAS;QAC1B,MAAM,CAAC,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;QACnB,MAAM,IAAI,GAAG,UAAU,CAAC,CAAC,CAAC,CAAC;QAC3B,MAAM,GAAG,GAAG,IAAI,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC;QACzC,IAAI,IAAI,IAAI,CAAC,GAAG,KAAK,KAAK,IAAI,GAAG,KAAK,KAAK,CAAC,EAAE,CAAC;YAC7C,KAAK,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;gBAC1C,IAAI,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;oBAAE,SAAS;gBAC1B,MAAM,CAAC,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;gBACnB,IAAI,UAAU,CAAC,CAAC,CAAC,KAAK,IAAI;oBAAE,SAAS;gBACrC,MAAM,GAAG,GAAG,IAAI,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC;gBACzC,IAAI,CAAC,GAAG,KAAK,KAAK,IAAI,GAAG,KAAK,KAAK,CAAC,IAAI,CAAC,GAAG,KAAK,KAAK,IAAI,GAAG,KAAK,KAAK,CAAC,EAAE,CAAC;oBACzE,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;oBAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;oBACzB,GAAG,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,SAAS,EAAE,GAAG,EAAE,GAAG,KAAK,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,GAAG,KAAK,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAiB,CAAC,CAAC;oBACtG,MAAM;gBACR,CAAC;YACH,CAAC;QACH,CAAC;IACH,CAAC;IACD,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,EAAE;QAAE,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;YAAE,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;IAC5E,OAAO,GAAG,CAAC;AACb,CAAC;AAED,SAAS,eAAe,CAAC,IAAiB,EAAE,GAAuB,EAAE,IAAoB;IACvF,MAAM,GAAG,GAAG,eAAe,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,EAAE,IAAI,CAAC,CAAC;IACjD,MAAM,IAAI,GAAG,eAAe,CAAC,IAAI,CAAC,IAAI,EAAE,GAAG,EAAE,IAAI,CAAC,CAAC;IACnD,MAAM,MAAM,GAAG,GAAG,CAAC,MAAM,IAAI,IAAI,CAAC,MAAM,CAAC;IACzC,MAAM,KAAK,GAAG,YAAY,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IACrC,MAAM,MAAM,GAAG,OAAO,IAAI,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC;IACzD,MAAM,OAAO,GAAG,OAAO,IAAI,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC;IAC5D,MAAM,QAAQ,GAAG,MAAM,MAAM,WAAW,OAAO,EAAE,CAAC;IAClD,OAAO;QACL,MAAM;QACN,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,MAAM,IAAI,IAAI,CAAC,MAAM,CAAC;QACxD,MAAM,EAAE,GAAG,CAAC,MAAM;QAClB,QAAQ;QACR,SAAS,EAAE,GAAG,CAAC,SAAS;QACxB,kBAAkB,EAAE,GAAG,KAAK,IAAI,QAAQ,EAAE;KAC3C,CAAC;AACJ,CAAC;AAID,SAAS,aAAa,CAAC,KAAkB,EAAE,GAAuB,EAAE,IAAoB;IACtF,MAAM,YAAY,GAAG,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,aAAa,CAAC,CAAC;IACvD,IAAI,YAAY,CAAC,MAAM,KAAK,KAAK,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC;QAC/C,MAAM,IAAI,KAAK,CAAC,uFAAuF,KAAK,CAAC,KAAK,CAAC,MAAM,GAAG,YAAY,CAAC,MAAM,gBAAgB,CAAC,CAAC;IACnK,CAAC;IACD,wEAAwE;IACxE,yEAAyE;IACzE,wEAAwE;IACxE,0EAA0E;IAC1E,2EAA2E;IAC3E,MAAM,KAAK,GAAG,KAAK,CAAC,UAAU,KAAK,KAAK,CAAC,CAAC,CAAC,gBAAgB,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,YAAY,CAAC;IACzF,MAAM,QAAQ,GAAG,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAClC,MAAM,IAAI,IAAI,IAAI,IAAI,CAAC,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,eAAe,CAAC,IAAI,EAAE,GAAG,EAAE,IAAI,CAAC,CAAC,CAAC,CAAC,eAAe,CAAC,IAAI,EAAE,GAAG,EAAE,IAAI,CAAC,CAChH,CAAC;IACF,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,YAAY,EAAE,CAAC,EAAE,cAAc,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,EAAE,EAAE,QAAQ,EAAE,EAAE,EAAE,SAAS,EAAE,WAAW,EAAE,kBAAkB,EAAE,aAAa,EAAE,EAAE,CAAC;IAC7L,MAAM,MAAM,GAAG,kBAAkB,CAAC,KAAK,CAAC,UAAU,EAAE,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC;IACnF,MAAM,YAAY,GAAG,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,MAAM,CAAC;IAC9D,MAAM,cAAc,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,QAAQ,CAAC,CAAC,CAAC,CAAC;IACtE,OAAO,EAAE,MAAM,EAAE,YAAY,EAAE,cAAc,EAAE,CAAC;AAClD,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,qBAAqB,CACnC,aAAqB,EACrB,KAAgB,EAChB,EAAmB,EACnB,KAAmB,EACnB,IAAoB;IAEpB,MAAM,GAAG,GAAuB,EAAE,KAAK,EAAE,SAAS,EAAE,EAAE,CAAC,SAAS,EAAE,CAAC;IACnE,MAAM,aAAa,GAAG,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,aAAa,CAAC,CAAC,EAAE,GAAG,EAAE,IAAI,CAAC,CAAC,CAAC;IAC3E,MAAM,WAAW,GAAG,aAAa,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC;IACxD,MAAM,MAAM,GAAG,WAAW;WACrB,aAAa,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,YAAY,GAAG,IAAI,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,aAAa,CAAC,CAAC,CAAC,CAAC,CAAC;IAC1G,MAAM,MAAM,GAAG,CAAC,CAAC,WAAW,CAAC;IAC7B,MAAM,iBAAiB,GAAsB;QAC3C,WAAW,EAAE,EAAE,EAAE,EAAE,aAAa,EAAE,KAAK,EAAE,MAAM,CAAC,cAAc,CAAC,kBAAkB,EAAE,WAAW,EAAE,UAAU,EAAE;QAC5G,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM;QAChC,SAAS,EAAE,MAAM,CAAC,cAAc,CAAC,SAAS;QAC1C,kBAAkB,EAAE,MAAM,CAAC,cAAc,CAAC,kBAAkB;QAC5D,aAAa,EAAE,MAAM,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,MAAM,CAAC,cAAc,CAAC,MAAM;QAChE,WAAW,EAAE,MAAM,CAAC,cAAc,CAAC,MAAM;QACzC,aAAa,EAAE,MAAM,CAAC,cAAc,CAAC,QAAQ;KAC9C,CAAC;IACF,OAAO;QACL,SAAS,EAAE,EAAE,CAAC,SAAS;QACvB,OAAO,EAAE,EAAE,CAAC,OAAO;QACnB,UAAU,EAAE,EAAE,CAAC,OAAO;QACtB,UAAU,EAAE,EAAE,CAAC,IAAI,IAAI,SAAS;QAChC,QAAQ,EAAE,EAAE,CAAC,QAAQ;QACrB,MAAM;QACN,kBAAkB,EAAE,CAAC,iBAAiB,CAAC;KACxC,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Set-level requirement checking (#5138 PR 3) — `unique` (plan §4.5) and
|
|
3
|
+
* `aggregate` (§4.6). Unlike `element` (per-entity, `rule-engine-
|
|
4
|
+
* requirements.ts`), these produce `SetResult`s describing a GROUP of
|
|
5
|
+
* entities. `compare` (§4.7) is per-entity like `element`, not a set kind —
|
|
6
|
+
* it lives in `rule-engine-compare.ts` (split out once this file crossed the
|
|
7
|
+
* module-size budget), reusing `describeSubject`/`baseRow` from here.
|
|
8
|
+
*/
|
|
9
|
+
import type { IfcDataStore } from '@ifc-lite/parser';
|
|
10
|
+
import type { EntityResult, RequirementResult, SetResult } from '@ifc-lite/ids';
|
|
11
|
+
import type { FilteredElement, EvaluatorModel } from '../filter/filter-evaluate.js';
|
|
12
|
+
import type { Subject, UniqueRequirement, AggregateRequirement } from '../rule-set/rule-set.js';
|
|
13
|
+
import { type ValidationOpts } from './rule-engine-requirements.js';
|
|
14
|
+
import { type RuleEngineProgress } from './rule-engine-chunk.js';
|
|
15
|
+
/** Shared with `rule-engine-compare.ts` (same `Subject` label rendering). */
|
|
16
|
+
export declare function describeSubject(subject: Subject): string;
|
|
17
|
+
/** Shared with `rule-engine-compare.ts`. */
|
|
18
|
+
export declare function baseRow(el: FilteredElement, passed: boolean, result: RequirementResult): EntityResult;
|
|
19
|
+
/** The shape every requirement-kind checker returns, folded by
|
|
20
|
+
* `rule-engine.ts`'s `finalizeSpecification`. `setResults`/
|
|
21
|
+
* `setResultsTruncated` are optional — `element`/`compare` never populate
|
|
22
|
+
* them (they are per-entity kinds, not set kinds). */
|
|
23
|
+
export interface SetCheckOutcome {
|
|
24
|
+
entityResults: EntityResult[];
|
|
25
|
+
setResults?: SetResult[];
|
|
26
|
+
setResultsTruncated?: boolean;
|
|
27
|
+
/**
|
|
28
|
+
* `aggregate` only (#5177): the number of DISTINCT applicable elements that
|
|
29
|
+
* fail the rule, i.e. every element excluded for an absent/non-numeric
|
|
30
|
+
* subject plus every member of a group whose aggregate fails — the same
|
|
31
|
+
* attribution `checkUnique` makes by giving every duplicate member a
|
|
32
|
+
* failing row. `checkAggregate` does not emit a row per failing-group
|
|
33
|
+
* member (a whole federation's worth of rows for no reporting value), so
|
|
34
|
+
* `entityResults` alone under-counts; this is the count it would have had.
|
|
35
|
+
* Taken on the full, pre-cap `setResults`, so it stays exact when
|
|
36
|
+
* `setResultsTruncated` is true.
|
|
37
|
+
*/
|
|
38
|
+
failedElementCount?: number;
|
|
39
|
+
}
|
|
40
|
+
export declare function checkUnique(requirementId: string, requirement: UniqueRequirement, applicable: readonly FilteredElement[], storesById: ReadonlyMap<string, IfcDataStore>, opts: ValidationOpts, ruleIndex: number, signal: AbortSignal | undefined, onProgress: ((p: RuleEngineProgress) => void) | undefined): Promise<SetCheckOutcome>;
|
|
41
|
+
export declare function checkAggregate(requirementId: string, requirement: AggregateRequirement, applicable: readonly FilteredElement[], storesById: ReadonlyMap<string, IfcDataStore>, models: ReadonlyArray<EvaluatorModel>, opts: ValidationOpts, ruleIndex: number, signal: AbortSignal | undefined, onProgress: ((p: RuleEngineProgress) => void) | undefined): Promise<SetCheckOutcome>;
|
|
42
|
+
/** Failing groups first, then largest first. The cap slices from the front,
|
|
43
|
+
* so a failing group must never sit behind 1 000 passing ones — otherwise the
|
|
44
|
+
* truncated list is all-pass and the rule reads `pass` (review on #5160). */
|
|
45
|
+
export declare function orderSetResultsForCap(results: SetResult[]): void;
|
|
46
|
+
//# sourceMappingURL=rule-engine-sets.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rule-engine-sets.d.ts","sourceRoot":"","sources":["../../src/engine/rule-engine-sets.ts"],"names":[],"mappings":"AAIA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AACrD,OAAO,KAAK,EAAE,YAAY,EAAqB,iBAAiB,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAInG,OAAO,KAAK,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,8BAA8B,CAAC;AAEpF,OAAO,KAAK,EAAE,OAAO,EAAE,iBAAiB,EAAE,oBAAoB,EAAE,MAAM,yBAAyB,CAAC;AAChG,OAAO,EAAY,KAAK,cAAc,EAAE,MAAM,+BAA+B,CAAC;AAC9E,OAAO,EAAkC,KAAK,kBAAkB,EAAE,MAAM,wBAAwB,CAAC;AAIjG,6EAA6E;AAC7E,wBAAgB,eAAe,CAAC,OAAO,EAAE,OAAO,GAAG,MAAM,CASxD;AAeD,4CAA4C;AAC5C,wBAAgB,OAAO,CAAC,EAAE,EAAE,eAAe,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,iBAAiB,GAAG,YAAY,CAUrG;AAID;;;uDAGuD;AACvD,MAAM,WAAW,eAAe;IAC9B,aAAa,EAAE,YAAY,EAAE,CAAC;IAC9B,UAAU,CAAC,EAAE,SAAS,EAAE,CAAC;IACzB,mBAAmB,CAAC,EAAE,OAAO,CAAC;IAC9B;;;;;;;;;;OAUG;IACH,kBAAkB,CAAC,EAAE,MAAM,CAAC;CAC7B;AAED,wBAAsB,WAAW,CAC/B,aAAa,EAAE,MAAM,EACrB,WAAW,EAAE,iBAAiB,EAC9B,UAAU,EAAE,SAAS,eAAe,EAAE,EACtC,UAAU,EAAE,WAAW,CAAC,MAAM,EAAE,YAAY,CAAC,EAC7C,IAAI,EAAE,cAAc,EACpB,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,WAAW,GAAG,SAAS,EAC/B,UAAU,EAAE,CAAC,CAAC,CAAC,EAAE,kBAAkB,KAAK,IAAI,CAAC,GAAG,SAAS,GACxD,OAAO,CAAC,eAAe,CAAC,CAmE1B;AAiGD,wBAAsB,cAAc,CAClC,aAAa,EAAE,MAAM,EACrB,WAAW,EAAE,oBAAoB,EACjC,UAAU,EAAE,SAAS,eAAe,EAAE,EACtC,UAAU,EAAE,WAAW,CAAC,MAAM,EAAE,YAAY,CAAC,EAC7C,MAAM,EAAE,aAAa,CAAC,cAAc,CAAC,EACrC,IAAI,EAAE,cAAc,EACpB,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,WAAW,GAAG,SAAS,EAC/B,UAAU,EAAE,CAAC,CAAC,CAAC,EAAE,kBAAkB,KAAK,IAAI,CAAC,GAAG,SAAS,GACxD,OAAO,CAAC,eAAe,CAAC,CAqF1B;AAED;;8EAE8E;AAC9E,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,SAAS,EAAE,GAAG,IAAI,CAEhE"}
|