@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.
Files changed (179) hide show
  1. package/LICENSE +373 -0
  2. package/README.md +45 -0
  3. package/dist/engine/rule-engine-chunk.d.ts +25 -0
  4. package/dist/engine/rule-engine-chunk.d.ts.map +1 -0
  5. package/dist/engine/rule-engine-chunk.js +43 -0
  6. package/dist/engine/rule-engine-chunk.js.map +1 -0
  7. package/dist/engine/rule-engine-compare.d.ts +17 -0
  8. package/dist/engine/rule-engine-compare.d.ts.map +1 -0
  9. package/dist/engine/rule-engine-compare.js +69 -0
  10. package/dist/engine/rule-engine-compare.js.map +1 -0
  11. package/dist/engine/rule-engine-requirements.d.ts +37 -0
  12. package/dist/engine/rule-engine-requirements.d.ts.map +1 -0
  13. package/dist/engine/rule-engine-requirements.js +293 -0
  14. package/dist/engine/rule-engine-requirements.js.map +1 -0
  15. package/dist/engine/rule-engine-sets.d.ts +46 -0
  16. package/dist/engine/rule-engine-sets.d.ts.map +1 -0
  17. package/dist/engine/rule-engine-sets.js +298 -0
  18. package/dist/engine/rule-engine-sets.js.map +1 -0
  19. package/dist/engine/rule-engine-unit.d.ts +23 -0
  20. package/dist/engine/rule-engine-unit.d.ts.map +1 -0
  21. package/dist/engine/rule-engine-unit.js +64 -0
  22. package/dist/engine/rule-engine-unit.js.map +1 -0
  23. package/dist/engine/rule-engine.d.ts +29 -0
  24. package/dist/engine/rule-engine.d.ts.map +1 -0
  25. package/dist/engine/rule-engine.js +244 -0
  26. package/dist/engine/rule-engine.js.map +1 -0
  27. package/dist/filter/effective-filter-fields.d.ts +13 -0
  28. package/dist/filter/effective-filter-fields.d.ts.map +1 -0
  29. package/dist/filter/effective-filter-fields.js +44 -0
  30. package/dist/filter/effective-filter-fields.js.map +1 -0
  31. package/dist/filter/entity-predefined-type.d.ts +24 -0
  32. package/dist/filter/entity-predefined-type.d.ts.map +1 -0
  33. package/dist/filter/entity-predefined-type.js +34 -0
  34. package/dist/filter/entity-predefined-type.js.map +1 -0
  35. package/dist/filter/filter-evaluate-groups.d.ts +36 -0
  36. package/dist/filter/filter-evaluate-groups.d.ts.map +1 -0
  37. package/dist/filter/filter-evaluate-groups.js +111 -0
  38. package/dist/filter/filter-evaluate-groups.js.map +1 -0
  39. package/dist/filter/filter-evaluate-model-tag.d.ts +22 -0
  40. package/dist/filter/filter-evaluate-model-tag.d.ts.map +1 -0
  41. package/dist/filter/filter-evaluate-model-tag.js +35 -0
  42. package/dist/filter/filter-evaluate-model-tag.js.map +1 -0
  43. package/dist/filter/filter-evaluate-mutations.d.ts +51 -0
  44. package/dist/filter/filter-evaluate-mutations.d.ts.map +1 -0
  45. package/dist/filter/filter-evaluate-mutations.js +111 -0
  46. package/dist/filter/filter-evaluate-mutations.js.map +1 -0
  47. package/dist/filter/filter-evaluate-yield.d.ts +9 -0
  48. package/dist/filter/filter-evaluate-yield.d.ts.map +1 -0
  49. package/dist/filter/filter-evaluate-yield.js +32 -0
  50. package/dist/filter/filter-evaluate-yield.js.map +1 -0
  51. package/dist/filter/filter-evaluate.d.ts +120 -0
  52. package/dist/filter/filter-evaluate.d.ts.map +1 -0
  53. package/dist/filter/filter-evaluate.js +408 -0
  54. package/dist/filter/filter-evaluate.js.map +1 -0
  55. package/dist/filter/filter-group-rule.d.ts +23 -0
  56. package/dist/filter/filter-group-rule.d.ts.map +1 -0
  57. package/dist/filter/filter-group-rule.js +69 -0
  58. package/dist/filter/filter-group-rule.js.map +1 -0
  59. package/dist/filter/filter-groups.d.ts +65 -0
  60. package/dist/filter/filter-groups.d.ts.map +1 -0
  61. package/dist/filter/filter-groups.js +136 -0
  62. package/dist/filter/filter-groups.js.map +1 -0
  63. package/dist/filter/filter-iteration-source.d.ts +26 -0
  64. package/dist/filter/filter-iteration-source.d.ts.map +1 -0
  65. package/dist/filter/filter-iteration-source.js +154 -0
  66. package/dist/filter/filter-iteration-source.js.map +1 -0
  67. package/dist/filter/filter-iteration.d.ts +5 -0
  68. package/dist/filter/filter-iteration.d.ts.map +1 -0
  69. package/dist/filter/filter-iteration.js +25 -0
  70. package/dist/filter/filter-iteration.js.map +1 -0
  71. package/dist/filter/filter-match.d.ts +114 -0
  72. package/dist/filter/filter-match.d.ts.map +1 -0
  73. package/dist/filter/filter-match.js +302 -0
  74. package/dist/filter/filter-match.js.map +1 -0
  75. package/dist/filter/filter-ops.d.ts +90 -0
  76. package/dist/filter/filter-ops.d.ts.map +1 -0
  77. package/dist/filter/filter-ops.js +202 -0
  78. package/dist/filter/filter-ops.js.map +1 -0
  79. package/dist/filter/filter-rule-guards.d.ts +4 -0
  80. package/dist/filter/filter-rule-guards.d.ts.map +1 -0
  81. package/dist/filter/filter-rule-guards.js +74 -0
  82. package/dist/filter/filter-rule-guards.js.map +1 -0
  83. package/dist/filter/filter-rules.d.ts +275 -0
  84. package/dist/filter/filter-rules.d.ts.map +1 -0
  85. package/dist/filter/filter-rules.js +68 -0
  86. package/dist/filter/filter-rules.js.map +1 -0
  87. package/dist/filter/lens-material-names.d.ts +13 -0
  88. package/dist/filter/lens-material-names.d.ts.map +1 -0
  89. package/dist/filter/lens-material-names.js +36 -0
  90. package/dist/filter/lens-material-names.js.map +1 -0
  91. package/dist/filter/measure-units.d.ts +29 -0
  92. package/dist/filter/measure-units.d.ts.map +1 -0
  93. package/dist/filter/measure-units.js +72 -0
  94. package/dist/filter/measure-units.js.map +1 -0
  95. package/dist/filter/model-tag.d.ts +65 -0
  96. package/dist/filter/model-tag.d.ts.map +1 -0
  97. package/dist/filter/model-tag.js +57 -0
  98. package/dist/filter/model-tag.js.map +1 -0
  99. package/dist/filter/read-measure-subject.d.ts +28 -0
  100. package/dist/filter/read-measure-subject.d.ts.map +1 -0
  101. package/dist/filter/read-measure-subject.js +116 -0
  102. package/dist/filter/read-measure-subject.js.map +1 -0
  103. package/dist/filter/read-subject.d.ts +72 -0
  104. package/dist/filter/read-subject.d.ts.map +1 -0
  105. package/dist/filter/read-subject.js +128 -0
  106. package/dist/filter/read-subject.js.map +1 -0
  107. package/dist/filter/subject-match.d.ts +27 -0
  108. package/dist/filter/subject-match.d.ts.map +1 -0
  109. package/dist/filter/subject-match.js +52 -0
  110. package/dist/filter/subject-match.js.map +1 -0
  111. package/dist/filter/subject-read-options.d.ts +33 -0
  112. package/dist/filter/subject-read-options.d.ts.map +1 -0
  113. package/dist/filter/subject-read-options.js +8 -0
  114. package/dist/filter/subject-read-options.js.map +1 -0
  115. package/dist/ids/ids-facet-to-rules.d.ts +20 -0
  116. package/dist/ids/ids-facet-to-rules.d.ts.map +1 -0
  117. package/dist/ids/ids-facet-to-rules.js +230 -0
  118. package/dist/ids/ids-facet-to-rules.js.map +1 -0
  119. package/dist/ids/ids-regex.d.ts +44 -0
  120. package/dist/ids/ids-regex.d.ts.map +1 -0
  121. package/dist/ids/ids-regex.js +334 -0
  122. package/dist/ids/ids-regex.js.map +1 -0
  123. package/dist/ids/ids-to-rule-set.d.ts +39 -0
  124. package/dist/ids/ids-to-rule-set.d.ts.map +1 -0
  125. package/dist/ids/ids-to-rule-set.js +103 -0
  126. package/dist/ids/ids-to-rule-set.js.map +1 -0
  127. package/dist/ids/ids-xml-writer.d.ts +11 -0
  128. package/dist/ids/ids-xml-writer.d.ts.map +1 -0
  129. package/dist/ids/ids-xml-writer.js +172 -0
  130. package/dist/ids/ids-xml-writer.js.map +1 -0
  131. package/dist/ids/rule-set-to-ids.d.ts +45 -0
  132. package/dist/ids/rule-set-to-ids.d.ts.map +1 -0
  133. package/dist/ids/rule-set-to-ids.js +140 -0
  134. package/dist/ids/rule-set-to-ids.js.map +1 -0
  135. package/dist/ids/rule-to-ids-facets.d.ts +52 -0
  136. package/dist/ids/rule-to-ids-facets.d.ts.map +1 -0
  137. package/dist/ids/rule-to-ids-facets.js +291 -0
  138. package/dist/ids/rule-to-ids-facets.js.map +1 -0
  139. package/dist/ids/stored-unit-scale.d.ts +15 -0
  140. package/dist/ids/stored-unit-scale.d.ts.map +1 -0
  141. package/dist/ids/stored-unit-scale.js +64 -0
  142. package/dist/ids/stored-unit-scale.js.map +1 -0
  143. package/dist/index.d.ts +39 -0
  144. package/dist/index.d.ts.map +1 -0
  145. package/dist/index.js +46 -0
  146. package/dist/index.js.map +1 -0
  147. package/dist/rule-set/between-chip.d.ts +54 -0
  148. package/dist/rule-set/between-chip.d.ts.map +1 -0
  149. package/dist/rule-set/between-chip.js +95 -0
  150. package/dist/rule-set/between-chip.js.map +1 -0
  151. package/dist/rule-set/requirement-invariants.d.ts +25 -0
  152. package/dist/rule-set/requirement-invariants.d.ts.map +1 -0
  153. package/dist/rule-set/requirement-invariants.js +29 -0
  154. package/dist/rule-set/requirement-invariants.js.map +1 -0
  155. package/dist/rule-set/requirement-text.d.ts +20 -0
  156. package/dist/rule-set/requirement-text.d.ts.map +1 -0
  157. package/dist/rule-set/requirement-text.js +179 -0
  158. package/dist/rule-set/requirement-text.js.map +1 -0
  159. package/dist/rule-set/rule-set-io-requirement.d.ts +22 -0
  160. package/dist/rule-set/rule-set-io-requirement.d.ts.map +1 -0
  161. package/dist/rule-set/rule-set-io-requirement.js +140 -0
  162. package/dist/rule-set/rule-set-io-requirement.js.map +1 -0
  163. package/dist/rule-set/rule-set-io-shared.d.ts +24 -0
  164. package/dist/rule-set/rule-set-io-shared.d.ts.map +1 -0
  165. package/dist/rule-set/rule-set-io-shared.js +48 -0
  166. package/dist/rule-set/rule-set-io-shared.js.map +1 -0
  167. package/dist/rule-set/rule-set-io-subject.d.ts +10 -0
  168. package/dist/rule-set/rule-set-io-subject.d.ts.map +1 -0
  169. package/dist/rule-set/rule-set-io-subject.js +67 -0
  170. package/dist/rule-set/rule-set-io-subject.js.map +1 -0
  171. package/dist/rule-set/rule-set-io.d.ts +37 -0
  172. package/dist/rule-set/rule-set-io.d.ts.map +1 -0
  173. package/dist/rule-set/rule-set-io.js +142 -0
  174. package/dist/rule-set/rule-set-io.js.map +1 -0
  175. package/dist/rule-set/rule-set.d.ts +109 -0
  176. package/dist/rule-set/rule-set.d.ts.map +1 -0
  177. package/dist/rule-set/rule-set.js +5 -0
  178. package/dist/rule-set/rule-set.js.map +1 -0
  179. package/package.json +59 -0
@@ -0,0 +1,298 @@
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 { collectSpatialAncestors } from '@ifc-lite/data';
5
+ import { numericOpMatches } from '../filter/filter-ops.js';
6
+ import { evaluateFilterGroupsFederated } from '../filter/filter-evaluate-groups.js';
7
+ import { readSubject } from '../filter/read-subject.js';
8
+ import { OP_LABEL } from './rule-engine-requirements.js';
9
+ import { maybeYieldChunk, finalProgress } from './rule-engine-chunk.js';
10
+ const SET_RESULT_CAP = 1_000;
11
+ /** Shared with `rule-engine-compare.ts` (same `Subject` label rendering). */
12
+ export function describeSubject(subject) {
13
+ switch (subject.kind) {
14
+ case 'property': return `${subject.setName}.${subject.propertyName}`;
15
+ case 'quantity': return `${subject.setName}.${subject.quantityName}`;
16
+ case 'attribute': return subject.name;
17
+ case 'classification': return subject.system ? `Classification[${subject.system}]` : 'Classification';
18
+ case 'group': return subject.groupClass ? `Group[${subject.groupClass}]` : 'Group';
19
+ default: return subject.kind;
20
+ }
21
+ }
22
+ /**
23
+ * Fold a raw subject value into a bucket/group key. `globalId` is NEVER
24
+ * case-folded, `caseSensitive` or not — review finding: same rule
25
+ * `filter-ops.ts`'s `globalIdOpMatches` already applies (a GlobalId is a
26
+ * 22-char base64 GUID where case IS the identity; folding it would merge
27
+ * two genuinely different elements' ids, e.g. `abc`/`ABC`, into one
28
+ * "duplicate").
29
+ */
30
+ function foldKey(value, subjectKind, caseSensitive) {
31
+ if (subjectKind === 'globalId')
32
+ return value;
33
+ return caseSensitive ? value : value.toLowerCase();
34
+ }
35
+ /** Shared with `rule-engine-compare.ts`. */
36
+ export function baseRow(el, passed, result) {
37
+ return {
38
+ expressId: el.expressId,
39
+ modelId: el.modelId,
40
+ entityType: el.ifcType,
41
+ entityName: el.name || undefined,
42
+ globalId: el.globalId,
43
+ passed,
44
+ requirementResults: [result],
45
+ };
46
+ }
47
+ export async function checkUnique(requirementId, requirement, applicable, storesById, opts, ruleIndex, signal, onProgress) {
48
+ const label = `unique(${describeSubject(requirement.subject)})`;
49
+ const perModel = requirement.scope === 'perModel';
50
+ const entityResults = [];
51
+ // scope key ('' for federation, else modelId) -> folded value -> members.
52
+ const buckets = new Map();
53
+ for (let i = 0; i < applicable.length; i++) {
54
+ const el = applicable[i];
55
+ const store = storesById.get(el.modelId);
56
+ if (store) {
57
+ const subject = readSubject(requirement.subject, { store, expressId: el.expressId });
58
+ if (!subject.present) {
59
+ entityResults.push(baseRow(el, false, {
60
+ requirement: { id: requirementId, label, optionality: 'required' },
61
+ status: 'fail', facetType: 'unique', checkedDescription: label,
62
+ failureReason: 'absent', actualValue: '""', expectedValue: 'unique',
63
+ }));
64
+ }
65
+ else {
66
+ const scopeKey = perModel ? el.modelId : '';
67
+ let scoped = buckets.get(scopeKey);
68
+ if (!scoped)
69
+ buckets.set(scopeKey, (scoped = new Map()));
70
+ for (const raw of subject.values) {
71
+ const s = String(raw);
72
+ if (s.trim().length === 0)
73
+ continue;
74
+ const key = foldKey(s, requirement.subject.kind, opts.caseSensitive);
75
+ let bucket = scoped.get(key);
76
+ if (!bucket)
77
+ scoped.set(key, (bucket = []));
78
+ bucket.push({ el, value: s });
79
+ }
80
+ }
81
+ }
82
+ await maybeYieldChunk(i + 1, applicable.length, ruleIndex, signal, onProgress);
83
+ }
84
+ finalProgress(applicable.length, ruleIndex, signal, onProgress);
85
+ const dupGroups = [];
86
+ for (const scoped of buckets.values()) {
87
+ for (const members of scoped.values()) {
88
+ if (members.length > 1)
89
+ dupGroups.push({ value: members[0].value, members });
90
+ }
91
+ }
92
+ dupGroups.sort((a, b) => b.members.length - a.members.length);
93
+ for (const g of dupGroups) {
94
+ const actual = `${g.value} (${g.members.length}×)`;
95
+ for (const m of g.members) {
96
+ entityResults.push(baseRow(m.el, false, {
97
+ requirement: { id: requirementId, label, optionality: 'required' },
98
+ status: 'fail', facetType: 'unique', checkedDescription: label,
99
+ failureReason: 'duplicate', actualValue: actual, expectedValue: 'unique',
100
+ }));
101
+ }
102
+ }
103
+ const setResultsTruncated = dupGroups.length > SET_RESULT_CAP;
104
+ const setResults = dupGroups.slice(0, SET_RESULT_CAP).map((g) => ({
105
+ kind: 'duplicate',
106
+ label: g.value,
107
+ actual: `${g.value} (${g.members.length}×)`,
108
+ expected: 'unique',
109
+ passed: false,
110
+ failureReason: 'duplicate',
111
+ members: g.members.map((m) => ({ modelId: m.el.modelId, expressId: m.el.expressId })),
112
+ }));
113
+ return { setResults, setResultsTruncated, entityResults };
114
+ }
115
+ function newAccumulator(keyLabel) {
116
+ return { count: 0, sum: 0, min: Infinity, max: -Infinity, units: new Set(), skipped: 0, keyLabel, members: [] };
117
+ }
118
+ /** The DIRECT (nearest) spatial parent — `collectSpatialAncestors`'s BFS
119
+ * walk yields nearest-first, so its first entry is exactly that; plan
120
+ * §4.6 asks for the direct parent's identity, not the whole ancestor
121
+ * chain `parent=` (search) matches against. */
122
+ function directParentOf(store, expressId) {
123
+ if (!store.relationships)
124
+ return undefined;
125
+ return collectSpatialAncestors(store.relationships, expressId)[0];
126
+ }
127
+ /**
128
+ * Every group key `el` contributes to — plural, per plan §3: "an element
129
+ * contributes to every key it carries", so a multi-valued `groupBy` subject
130
+ * (`material`, `classification`) lands the same element in EVERY matching
131
+ * group, not just its first value. `parent` stays single-valued (an element
132
+ * has exactly one direct spatial parent); everything else de-dupes an
133
+ * element's own repeated values so one element can't double-count itself
134
+ * into the SAME group twice.
135
+ */
136
+ function groupKeysOf(requirement, el, store, caseSensitive) {
137
+ if (!requirement.groupBy)
138
+ return [{ key: '*', label: '' }];
139
+ if (requirement.groupBy.subject.kind === 'parent') {
140
+ const parentId = directParentOf(store, el.expressId);
141
+ if (parentId === undefined)
142
+ return [];
143
+ return [{ key: `${el.modelId}:${parentId}`, label: store.entities.getName(parentId) }];
144
+ }
145
+ const subject = readSubject(requirement.groupBy.subject, { store, expressId: el.expressId });
146
+ if (!subject.present)
147
+ return [];
148
+ const out = [];
149
+ const seen = new Set();
150
+ for (const raw of subject.values) {
151
+ const s = String(raw);
152
+ if (s.trim().length === 0)
153
+ continue;
154
+ const key = foldKey(s, requirement.groupBy.subject.kind, caseSensitive);
155
+ if (seen.has(key))
156
+ continue;
157
+ seen.add(key);
158
+ out.push({ key, label: s });
159
+ }
160
+ return out;
161
+ }
162
+ /** Seed every group the `universe` block defines with an EMPTY accumulator,
163
+ * so a group with zero contributing members (e.g. an `IfcElementAssembly`
164
+ * with no `IfcPlate`) still produces a `count 0` set result that can fail —
165
+ * without this, that key never appears at all (plan §4.6, §11 risk). */
166
+ async function seedUniverse(requirement, models, storesById, caseSensitive, groups) {
167
+ const universe = requirement.groupBy?.universe;
168
+ if (!universe)
169
+ return;
170
+ const universeEls = await evaluateFilterGroupsFederated(models, universe.groups, { limit: Number.MAX_SAFE_INTEGER });
171
+ for (const uel of universeEls) {
172
+ const store = storesById.get(uel.modelId);
173
+ if (!store)
174
+ continue;
175
+ if (requirement.groupBy?.subject.kind === 'parent') {
176
+ const key = `${uel.modelId}:${uel.expressId}`;
177
+ if (!groups.has(key))
178
+ groups.set(key, newAccumulator(store.entities.getName(uel.expressId)));
179
+ continue;
180
+ }
181
+ if (!requirement.groupBy)
182
+ continue;
183
+ const subject = readSubject(requirement.groupBy.subject, { store, expressId: uel.expressId });
184
+ for (const raw of subject.values) {
185
+ const s = String(raw);
186
+ if (s.trim().length === 0)
187
+ continue;
188
+ const key = foldKey(s, requirement.groupBy.subject.kind, caseSensitive);
189
+ if (!groups.has(key))
190
+ groups.set(key, newAccumulator(s));
191
+ }
192
+ }
193
+ }
194
+ export async function checkAggregate(requirementId, requirement, applicable, storesById, models, opts, ruleIndex, signal, onProgress) {
195
+ const label = `${requirement.fn}(${requirement.subject ? describeSubject(requirement.subject) : ''})`;
196
+ const groups = new Map();
197
+ await seedUniverse(requirement, models, storesById, opts.caseSensitive, groups);
198
+ const entityResults = [];
199
+ const excludedRow = (el, reason) => baseRow(el, false, {
200
+ requirement: { id: requirementId, label, optionality: 'required' },
201
+ status: 'fail', facetType: 'aggregate', checkedDescription: label,
202
+ failureReason: reason, actualValue: reason === 'absent' ? '""' : '(non-numeric)', expectedValue: 'numeric',
203
+ });
204
+ const accFor = (key, groupLabel) => {
205
+ let acc = groups.get(key);
206
+ if (!acc)
207
+ groups.set(key, (acc = newAccumulator(groupLabel)));
208
+ return acc;
209
+ };
210
+ for (let i = 0; i < applicable.length; i++) {
211
+ const el = applicable[i];
212
+ const store = storesById.get(el.modelId);
213
+ if (store) {
214
+ const groupKeys = groupKeysOf(requirement, el, store, opts.caseSensitive);
215
+ if (groupKeys.length > 0) {
216
+ if (requirement.fn === 'count') {
217
+ for (const gk of groupKeys) {
218
+ const acc = accFor(gk.key, gk.label);
219
+ acc.members.push({ modelId: el.modelId, expressId: el.expressId });
220
+ acc.count++;
221
+ }
222
+ }
223
+ else {
224
+ const subject = readSubject(requirement.subject, { store, expressId: el.expressId });
225
+ const nums = subject.present ? subject.values.map(Number).filter(Number.isFinite) : [];
226
+ const reason = !subject.present ? 'absent' : nums.length === 0 ? 'notNumeric' : undefined;
227
+ for (const gk of groupKeys) {
228
+ const acc = accFor(gk.key, gk.label);
229
+ acc.members.push({ modelId: el.modelId, expressId: el.expressId });
230
+ if (reason) {
231
+ acc.skipped++;
232
+ continue;
233
+ }
234
+ acc.count++;
235
+ for (const n of nums) {
236
+ acc.sum += n;
237
+ if (n < acc.min)
238
+ acc.min = n;
239
+ if (n > acc.max)
240
+ acc.max = n;
241
+ }
242
+ if (subject.unit)
243
+ acc.units.add(subject.unit);
244
+ }
245
+ // One entity row per excluded ELEMENT (not per group it belongs to).
246
+ if (reason)
247
+ entityResults.push(excludedRow(el, reason));
248
+ }
249
+ }
250
+ }
251
+ await maybeYieldChunk(i + 1, applicable.length, ruleIndex, signal, onProgress);
252
+ }
253
+ finalProgress(applicable.length, ruleIndex, signal, onProgress);
254
+ const setResults = [];
255
+ for (const acc of groups.values()) {
256
+ const value = requirement.fn === 'count' ? acc.count
257
+ : requirement.fn === 'sum' ? acc.sum
258
+ : requirement.fn === 'min' ? (acc.count > 0 ? acc.min : 0)
259
+ : requirement.fn === 'max' ? (acc.count > 0 ? acc.max : 0)
260
+ : (acc.count > 0 ? acc.sum / acc.count : 0); // avg
261
+ const unitMismatch = acc.units.size > 1;
262
+ const unitSuffix = acc.units.size === 1 ? ` ${[...acc.units][0]}` : '';
263
+ const passed = !unitMismatch && numericOpMatches(requirement.op, value, requirement.value, opts);
264
+ setResults.push({
265
+ kind: 'aggregate',
266
+ label,
267
+ groupKey: requirement.groupBy ? acc.keyLabel : undefined,
268
+ actual: unitMismatch ? `mixed units: ${[...acc.units].join(', ')}` : `${value}${unitSuffix}`,
269
+ expected: `${OP_LABEL[requirement.op]} ${requirement.value}`,
270
+ passed,
271
+ failureReason: passed ? undefined : (unitMismatch ? 'mismatch' : 'aggregate'),
272
+ skipped: acc.skipped > 0 ? acc.skipped : undefined,
273
+ members: acc.members,
274
+ });
275
+ }
276
+ // Counted on the FULL (pre-cap) list — see `failedElementCount`'s doc. A
277
+ // key set, because an element can sit in several groups (groupBy material).
278
+ const failedElements = new Set(entityResults.map((r) => `${r.modelId}:${r.expressId}`));
279
+ for (const set of setResults) {
280
+ if (set.passed)
281
+ continue;
282
+ for (const m of set.members)
283
+ failedElements.add(`${m.modelId}:${m.expressId}`);
284
+ }
285
+ orderSetResultsForCap(setResults);
286
+ const setResultsTruncated = setResults.length > SET_RESULT_CAP;
287
+ return {
288
+ setResults: setResults.slice(0, SET_RESULT_CAP), setResultsTruncated, entityResults,
289
+ failedElementCount: failedElements.size,
290
+ };
291
+ }
292
+ /** Failing groups first, then largest first. The cap slices from the front,
293
+ * so a failing group must never sit behind 1 000 passing ones — otherwise the
294
+ * truncated list is all-pass and the rule reads `pass` (review on #5160). */
295
+ export function orderSetResultsForCap(results) {
296
+ results.sort((a, b) => Number(a.passed) - Number(b.passed) || b.members.length - a.members.length);
297
+ }
298
+ //# sourceMappingURL=rule-engine-sets.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rule-engine-sets.js","sourceRoot":"","sources":["../../src/engine/rule-engine-sets.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,23 @@
1
+ /**
2
+ * `unit` requirement checking (#5300): "Width is recorded in mm". Per
3
+ * element, like `compare`. `readSubject` reports the unit every value of a
4
+ * property/quantity subject is recorded in (its explicit `Unit`, else the
5
+ * project unit for its measure type); an element passes when the subject
6
+ * is present and EVERY value is recorded in the required unit.
7
+ *
8
+ * Units compare by display symbol, the one spelling the viewer shows for a
9
+ * unit (`mm`, `m²`), after folding the ASCII exponent spellings a person
10
+ * types (`m2`, `m^2`) onto the superscripts the resolver emits. Nothing
11
+ * else is folded: `mm` and `Mm` are different units.
12
+ */
13
+ import type { IfcDataStore } from '@ifc-lite/parser';
14
+ import type { EntityResult } from '@ifc-lite/ids';
15
+ import type { FilteredElement } from '../filter/filter-evaluate.js';
16
+ import type { UnitRequirement } from '../rule-set/rule-set.js';
17
+ import { type RuleEngineProgress } from './rule-engine-chunk.js';
18
+ /** `m2` / `m^2` / `m²` all read as `m²`; everything else is compared as typed. */
19
+ export declare function normalizeUnitSymbol(symbol: string): string;
20
+ export declare function checkUnit(requirementId: string, requirement: UnitRequirement, applicable: readonly FilteredElement[], storesById: ReadonlyMap<string, IfcDataStore>, ruleIndex: number, signal: AbortSignal | undefined, onProgress: ((p: RuleEngineProgress) => void) | undefined): Promise<{
21
+ entityResults: EntityResult[];
22
+ }>;
23
+ //# sourceMappingURL=rule-engine-unit.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rule-engine-unit.d.ts","sourceRoot":"","sources":["../../src/engine/rule-engine-unit.ts"],"names":[],"mappings":"AAIA;;;;;;;;;;;GAWG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AACrD,OAAO,KAAK,EAAE,YAAY,EAAqB,MAAM,eAAe,CAAC;AACrE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,8BAA8B,CAAC;AAEpE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAE/D,OAAO,EAAkC,KAAK,kBAAkB,EAAE,MAAM,wBAAwB,CAAC;AAIjG,kFAAkF;AAClF,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAE1D;AAOD,wBAAsB,SAAS,CAC7B,aAAa,EAAE,MAAM,EACrB,WAAW,EAAE,eAAe,EAC5B,UAAU,EAAE,SAAS,eAAe,EAAE,EACtC,UAAU,EAAE,WAAW,CAAC,MAAM,EAAE,YAAY,CAAC,EAC7C,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;IAAE,aAAa,EAAE,YAAY,EAAE,CAAA;CAAE,CAAC,CA6C5C"}
@@ -0,0 +1,64 @@
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 { readSubject } from '../filter/read-subject.js';
5
+ import { baseRow, describeSubject } from './rule-engine-sets.js';
6
+ import { maybeYieldChunk, finalProgress } from './rule-engine-chunk.js';
7
+ const SUPERSCRIPT = { '2': '²', '3': '³' };
8
+ /** `m2` / `m^2` / `m²` all read as `m²`; everything else is compared as typed. */
9
+ export function normalizeUnitSymbol(symbol) {
10
+ return symbol.trim().replace(/([A-Za-zµ])\^?([23])(?![0-9])/g, (_, base, exp) => `${base}${SUPERSCRIPT[exp]}`);
11
+ }
12
+ /** What a value's unit reads as in a failure message. */
13
+ function unitLabel(unit) {
14
+ return unit ?? 'no unit';
15
+ }
16
+ export async function checkUnit(requirementId, requirement, applicable, storesById, ruleIndex, signal, onProgress) {
17
+ const wanted = normalizeUnitSymbol(requirement.unit);
18
+ // A blank unit is an unfinished rule, not a check every element fails:
19
+ // report it as the rule's error (`rule-engine.ts`'s per-rule guard).
20
+ if (wanted.length === 0)
21
+ throw new Error('the unit requirement names no unit');
22
+ const label = `${describeSubject(requirement.subject)} recorded in ${wanted}`;
23
+ const facetType = requirement.subject.kind;
24
+ const entityResults = [];
25
+ for (let i = 0; i < applicable.length; i++) {
26
+ const el = applicable[i];
27
+ const store = storesById.get(el.modelId);
28
+ if (!store) {
29
+ await maybeYieldChunk(i + 1, applicable.length, ruleIndex, signal, onProgress);
30
+ continue;
31
+ }
32
+ const subject = readSubject(requirement.subject, { store, expressId: el.expressId });
33
+ let passed = false;
34
+ let reason;
35
+ let actual = '""';
36
+ if (subject.present) {
37
+ // Only the values that are actually there: an explicitly empty label
38
+ // next to a real one is not a second, unit-less recording.
39
+ const recorded = subject.values
40
+ .map((value, index) => ({ value: String(value), unit: subject.valueUnits?.[index] }))
41
+ .filter((v) => v.value.trim().length > 0);
42
+ actual = recorded.map((v) => `${v.value} ${unitLabel(v.unit)}`).join('; ');
43
+ passed = recorded.length > 0
44
+ && recorded.every((v) => v.unit !== undefined && normalizeUnitSymbol(v.unit) === wanted);
45
+ reason = passed ? undefined : 'mismatch';
46
+ }
47
+ else {
48
+ reason = 'absent';
49
+ }
50
+ entityResults.push(baseRow(el, passed, {
51
+ requirement: { id: requirementId, label, optionality: 'required' },
52
+ status: passed ? 'pass' : 'fail',
53
+ facetType,
54
+ checkedDescription: label,
55
+ failureReason: reason,
56
+ actualValue: actual,
57
+ expectedValue: wanted,
58
+ }));
59
+ await maybeYieldChunk(i + 1, applicable.length, ruleIndex, signal, onProgress);
60
+ }
61
+ finalProgress(applicable.length, ruleIndex, signal, onProgress);
62
+ return { entityResults };
63
+ }
64
+ //# sourceMappingURL=rule-engine-unit.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rule-engine-unit.js","sourceRoot":"","sources":["../../src/engine/rule-engine-unit.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,29 @@
1
+ import { type ValidationReport } from '@ifc-lite/ids';
2
+ import type { EvaluatorModel } from '../filter/filter-evaluate.js';
3
+ import type { RuleSetFile, RuleSetTargets } from '../rule-set/rule-set.js';
4
+ import { type RuleEngineProgress } from './rule-engine-chunk.js';
5
+ export type { RuleEngineProgress };
6
+ export interface RunRuleSetOptions {
7
+ ruleSet: RuleSetFile;
8
+ /** Every currently-loaded model as the evaluator sees it (#5138 PR 7a: the
9
+ * caller — the viewer's `evaluatorModelsFromState` or the CLI's
10
+ * `loadModelForDelivery` — builds this list; the engine no longer knows
11
+ * about a "model tag state" shape). */
12
+ models: ReadonlyArray<EvaluatorModel>;
13
+ /** Every tag id that currently exists, for `modelTag` rule resolution
14
+ * (plan: a rule naming a since-deleted tag is UNRESOLVED, never silently
15
+ * broad). Omit when the caller has no tag concept (e.g. the CLI). */
16
+ definedModelTagIds?: ReadonlySet<string>;
17
+ signal?: AbortSignal;
18
+ onProgress?: (progress: RuleEngineProgress) => void;
19
+ }
20
+ /** `targets` narrows the loaded-model list to the rule set's declared
21
+ * default targets (plan §3: never a local model id; both lists OR'd;
22
+ * empty/absent = every loaded model). */
23
+ export declare function resolveTargetModels(models: ReadonlyArray<EvaluatorModel>, targets: RuleSetTargets | undefined): EvaluatorModel[];
24
+ /** Run every rule in `ruleSet` against the targeted models and return one
25
+ * `ValidationReport`. Rejects with `AbortError` on cancellation; the report
26
+ * object is constructed only after the loop completes, so a caller can
27
+ * never observe a partial one. */
28
+ export declare function runRuleSet(options: RunRuleSetOptions): Promise<ValidationReport>;
29
+ //# sourceMappingURL=rule-engine.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rule-engine.d.ts","sourceRoot":"","sources":["../../src/engine/rule-engine.ts"],"names":[],"mappings":"AAkBA,OAAO,EAML,KAAK,gBAAgB,EACtB,MAAM,eAAe,CAAC;AAKvB,OAAO,KAAK,EAAE,cAAc,EAAmB,MAAM,8BAA8B,CAAC;AAGpF,OAAO,KAAK,EAA8B,WAAW,EAAE,cAAc,EAAE,MAAM,yBAAyB,CAAC;AAKvG,OAAO,EAAkC,KAAK,kBAAkB,EAAE,MAAM,wBAAwB,CAAC;AAEjG,YAAY,EAAE,kBAAkB,EAAE,CAAC;AAEnC,MAAM,WAAW,iBAAiB;IAChC,OAAO,EAAE,WAAW,CAAC;IACrB;;;4CAGwC;IACxC,MAAM,EAAE,aAAa,CAAC,cAAc,CAAC,CAAC;IACtC;;0EAEsE;IACtE,kBAAkB,CAAC,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;IACzC,MAAM,CAAC,EAAE,WAAW,CAAC;IACrB,UAAU,CAAC,EAAE,CAAC,QAAQ,EAAE,kBAAkB,KAAK,IAAI,CAAC;CACrD;AAED;;0CAE0C;AAC1C,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,aAAa,CAAC,cAAc,CAAC,EAAE,OAAO,EAAE,cAAc,GAAG,SAAS,GAAG,cAAc,EAAE,CAWhI;AA2JD;;;mCAGmC;AACnC,wBAAsB,UAAU,CAAC,OAAO,EAAE,iBAAiB,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAuFtF"}