@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,291 @@
|
|
|
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 { escapeXsdLiteral, hasAstralCaveat, jsRegexOf, jsRegexToIdsPattern } from './ids-regex.js';
|
|
5
|
+
const NEGATED_OPS = new Set(['ne', 'notContains', 'notMatches', 'isNotSet', 'notIn']);
|
|
6
|
+
/** A `/body/flags` literal: how a name with no declared kind says "pattern". */
|
|
7
|
+
const REGEX_LITERAL = /^\/(.+)\/([a-z]*)$/;
|
|
8
|
+
function simpleOrEnumeration(values) {
|
|
9
|
+
return values.length === 1
|
|
10
|
+
? { type: 'simpleValue', value: values[0] }
|
|
11
|
+
: { type: 'enumeration', values: [...values] };
|
|
12
|
+
}
|
|
13
|
+
/** A set/property/quantity NAME as the engine reads it (`nameMatches`). */
|
|
14
|
+
function nameConstraint(name, kind) {
|
|
15
|
+
const isRegex = kind === 'regex' || (kind === undefined && REGEX_LITERAL.test(name));
|
|
16
|
+
if (!isRegex)
|
|
17
|
+
return { type: 'simpleValue', value: name };
|
|
18
|
+
const converted = jsRegexToIdsPattern(jsRegexOf(name, kind));
|
|
19
|
+
return converted.ok ? { type: 'pattern', pattern: converted.pattern } : `name pattern "${name}": ${converted.reason}`;
|
|
20
|
+
}
|
|
21
|
+
function boundsOf(op, value) {
|
|
22
|
+
switch (op) {
|
|
23
|
+
case 'gt': return { type: 'bounds', minExclusive: value };
|
|
24
|
+
case 'gte': return { type: 'bounds', minInclusive: value };
|
|
25
|
+
case 'lt': return { type: 'bounds', maxExclusive: value };
|
|
26
|
+
case 'lte': return { type: 'bounds', maxInclusive: value };
|
|
27
|
+
default: return { type: 'simpleValue', value: String(value) };
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* The value constraint for a rule operator, `null` for a bare presence
|
|
32
|
+
* check (`isSet`), or a refusal reason.
|
|
33
|
+
*/
|
|
34
|
+
function valueConstraint(op, value, valueKind) {
|
|
35
|
+
switch (op) {
|
|
36
|
+
case 'isSet':
|
|
37
|
+
return null;
|
|
38
|
+
case 'eq':
|
|
39
|
+
return { type: 'simpleValue', value };
|
|
40
|
+
case 'contains':
|
|
41
|
+
return { type: 'pattern', pattern: `.*${escapeXsdLiteral(value)}.*` };
|
|
42
|
+
case 'startsWith':
|
|
43
|
+
return { type: 'pattern', pattern: `${escapeXsdLiteral(value)}.*` };
|
|
44
|
+
case 'matches': {
|
|
45
|
+
const converted = jsRegexToIdsPattern(jsRegexOf(value, valueKind));
|
|
46
|
+
return converted.ok ? { type: 'pattern', pattern: converted.pattern } : `pattern "${value}": ${converted.reason}`;
|
|
47
|
+
}
|
|
48
|
+
case 'gt':
|
|
49
|
+
case 'gte':
|
|
50
|
+
case 'lt':
|
|
51
|
+
case 'lte': {
|
|
52
|
+
const n = Number(value);
|
|
53
|
+
if (value.trim() === '' || !Number.isFinite(n))
|
|
54
|
+
return `"${value}" is not a number, so "${op}" has no IDS bound`;
|
|
55
|
+
return boundsOf(op, n);
|
|
56
|
+
}
|
|
57
|
+
default:
|
|
58
|
+
return `operator "${op}" has no IDS equivalent`;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
const NO_MODEL = () => ({
|
|
62
|
+
kind: 'unknown',
|
|
63
|
+
reason: 'the value is compared in model units, and converting it to the SI units IDS uses needs a loaded model',
|
|
64
|
+
});
|
|
65
|
+
/** `c` with every number multiplied by `scale`. */
|
|
66
|
+
function scaleConstraint(c, scale) {
|
|
67
|
+
if (c.type === 'simpleValue')
|
|
68
|
+
return { ...c, value: String(Number(c.value) * scale) };
|
|
69
|
+
if (c.type !== 'bounds')
|
|
70
|
+
return c;
|
|
71
|
+
const out = { ...c };
|
|
72
|
+
for (const key of ['minInclusive', 'minExclusive', 'maxInclusive', 'maxExclusive']) {
|
|
73
|
+
if (out[key] !== undefined)
|
|
74
|
+
out[key] = out[key] * scale;
|
|
75
|
+
}
|
|
76
|
+
return out;
|
|
77
|
+
}
|
|
78
|
+
const ASTRAL_NOTE = 'A pattern without the "u" flag reads an emoji or other character outside the Basic Multilingual Plane as two ' +
|
|
79
|
+
'characters in the rule engine and as one in IDS, so ".", "[^…]" and "\\D" can disagree on such values';
|
|
80
|
+
/** The astral-plane caveat, when the rule's value or set/property name is such a regex. */
|
|
81
|
+
function regexNote(rule) {
|
|
82
|
+
const regexes = [];
|
|
83
|
+
if ('op' in rule && rule.op === 'matches' && 'value' in rule && typeof rule.value === 'string') {
|
|
84
|
+
regexes.push(jsRegexOf(rule.value, 'valueKind' in rule ? rule.valueKind : undefined));
|
|
85
|
+
}
|
|
86
|
+
if (rule.kind === 'property' || rule.kind === 'quantity') {
|
|
87
|
+
const baseName = rule.kind === 'property' ? rule.propertyName : rule.quantityName;
|
|
88
|
+
const baseKind = rule.kind === 'property' ? rule.propertyNameKind : rule.quantityNameKind;
|
|
89
|
+
const names = [[rule.setName, rule.setNameKind], [baseName, baseKind]];
|
|
90
|
+
for (const [name, kind] of names) {
|
|
91
|
+
if (kind === 'regex' || (kind === undefined && REGEX_LITERAL.test(name)))
|
|
92
|
+
regexes.push(jsRegexOf(name, kind));
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
return regexes.some(hasAstralCaveat) ? ASTRAL_NOTE : undefined;
|
|
96
|
+
}
|
|
97
|
+
function mapRule(rule, scaleOf) {
|
|
98
|
+
if ('op' in rule && NEGATED_OPS.has(rule.op)) {
|
|
99
|
+
return { reason: `a negated condition ("${rule.op}") cannot be expressed in IDS 1.0` };
|
|
100
|
+
}
|
|
101
|
+
switch (rule.kind) {
|
|
102
|
+
case 'model':
|
|
103
|
+
case 'modelTag':
|
|
104
|
+
return { reason: 'targeting a model or model tag has no IDS equivalent (an IDS is run against one model)' };
|
|
105
|
+
case 'storey':
|
|
106
|
+
return { reason: 'storey membership by name has no IDS facet' };
|
|
107
|
+
case 'elevation':
|
|
108
|
+
return { reason: 'storey elevation has no IDS facet' };
|
|
109
|
+
case 'type':
|
|
110
|
+
return { reason: 'the relating type name has no IDS facet' };
|
|
111
|
+
case 'parent':
|
|
112
|
+
return { reason: 'an ancestor matched by name has no IDS facet (partOf matches a class)' };
|
|
113
|
+
case 'group':
|
|
114
|
+
// IDS's partOf IfcRelAssignsToGroup names the group's exact class only:
|
|
115
|
+
// no Name match, and no subclass expansion of `groupClass`.
|
|
116
|
+
return { reason: 'group membership by name or by class-with-subclasses has no IDS facet (partOf matches one exact class)' };
|
|
117
|
+
case 'globalId':
|
|
118
|
+
return { facet: { type: 'attribute', name: { type: 'simpleValue', value: 'GlobalId' }, value: simpleOrEnumeration(rule.values) } };
|
|
119
|
+
case 'name':
|
|
120
|
+
case 'attribute': {
|
|
121
|
+
const attrName = rule.kind === 'name' ? 'Name' : rule.name;
|
|
122
|
+
const value = valueConstraint(rule.op, rule.value, rule.valueKind);
|
|
123
|
+
if (typeof value === 'string')
|
|
124
|
+
return { reason: value };
|
|
125
|
+
return {
|
|
126
|
+
facet: { type: 'attribute', name: { type: 'simpleValue', value: attrName }, ...(value ? { value } : {}) },
|
|
127
|
+
boundsKey: value?.type === 'bounds' ? `attribute:${attrName}` : undefined,
|
|
128
|
+
};
|
|
129
|
+
}
|
|
130
|
+
case 'property':
|
|
131
|
+
case 'quantity': {
|
|
132
|
+
const isQuantity = rule.kind === 'quantity';
|
|
133
|
+
const setName = nameConstraint(rule.setName, rule.setNameKind);
|
|
134
|
+
const baseName = isQuantity
|
|
135
|
+
? nameConstraint(rule.quantityName, rule.quantityNameKind)
|
|
136
|
+
: nameConstraint(rule.propertyName, rule.propertyNameKind);
|
|
137
|
+
if (typeof setName === 'string')
|
|
138
|
+
return { reason: setName };
|
|
139
|
+
if (typeof baseName === 'string')
|
|
140
|
+
return { reason: baseName };
|
|
141
|
+
const value = isQuantity
|
|
142
|
+
? boundsOf(rule.op, rule.value)
|
|
143
|
+
: valueConstraint(rule.op, rule.value, rule.valueKind);
|
|
144
|
+
if (typeof value === 'string')
|
|
145
|
+
return { reason: value };
|
|
146
|
+
const key = `${rule.kind}:${rule.setName}:${isQuantity ? rule.quantityName : rule.propertyName}`;
|
|
147
|
+
const numeric = value !== null && (isQuantity || value.type === 'bounds'
|
|
148
|
+
|| (value.type === 'simpleValue' && value.value.trim() !== '' && Number.isFinite(Number(value.value))));
|
|
149
|
+
let exported = value;
|
|
150
|
+
if (numeric && value && rule.valueUnit !== 'si') {
|
|
151
|
+
const stored = scaleOf(rule);
|
|
152
|
+
if (stored.kind === 'unknown')
|
|
153
|
+
return { reason: stored.reason };
|
|
154
|
+
if (stored.kind === 'scale')
|
|
155
|
+
exported = scaleConstraint(value, stored.scale);
|
|
156
|
+
}
|
|
157
|
+
return {
|
|
158
|
+
facet: { type: 'property', propertySet: setName, baseName, ...(exported ? { value: exported } : {}) },
|
|
159
|
+
boundsKey: value?.type === 'bounds' ? key : undefined,
|
|
160
|
+
};
|
|
161
|
+
}
|
|
162
|
+
case 'material': {
|
|
163
|
+
// `matches .` (any non-empty name) is how the rule vocabulary, which
|
|
164
|
+
// has no material presence operator, spells "has a material"; the IDS
|
|
165
|
+
// spelling of the same check is a material facet without a value.
|
|
166
|
+
if (rule.op === 'matches' && rule.valueKind === 'regex' && rule.value === '.') {
|
|
167
|
+
return { facet: { type: 'material' } };
|
|
168
|
+
}
|
|
169
|
+
const value = valueConstraint(rule.op, rule.value, rule.valueKind);
|
|
170
|
+
if (typeof value === 'string')
|
|
171
|
+
return { reason: value };
|
|
172
|
+
return { facet: { type: 'material', ...(value ? { value } : {}) } };
|
|
173
|
+
}
|
|
174
|
+
case 'classification': {
|
|
175
|
+
if (rule.op !== 'isSet') {
|
|
176
|
+
return { reason: 'a classification value check matches a code OR a name; the IDS classification facet matches the code only' };
|
|
177
|
+
}
|
|
178
|
+
const system = rule.system?.trim();
|
|
179
|
+
return { facet: { type: 'classification', ...(system ? { system: { type: 'simpleValue', value: system } } : {}) } };
|
|
180
|
+
}
|
|
181
|
+
case 'ifcType':
|
|
182
|
+
case 'predefinedType':
|
|
183
|
+
// Folded into one entity facet by `entityFacetOf`.
|
|
184
|
+
return { reason: `${rule.kind} is handled as an entity facet` };
|
|
185
|
+
default: {
|
|
186
|
+
const exhaustive = rule;
|
|
187
|
+
return { reason: `unknown rule kind ${JSON.stringify(exhaustive)}` };
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
/** The group's `ifcType`/`predefinedType` rules as one entity facet. */
|
|
192
|
+
function entityFacetOf(rules, role, reasons) {
|
|
193
|
+
const types = rules.filter((r) => r.kind === 'ifcType');
|
|
194
|
+
const predefined = rules.filter((r) => r.kind === 'predefinedType');
|
|
195
|
+
if (types.length === 0 && predefined.length === 0)
|
|
196
|
+
return null;
|
|
197
|
+
if (role === 'requirement') {
|
|
198
|
+
reasons.push('an IFC class requirement has no exact-class form in the rule engine, while an IDS entity facet is exact-class');
|
|
199
|
+
return null;
|
|
200
|
+
}
|
|
201
|
+
if (types.length !== 1) {
|
|
202
|
+
reasons.push(types.length === 0
|
|
203
|
+
? 'a PredefinedType condition needs an IFC class condition in the same group (IDS keeps it inside the entity facet)'
|
|
204
|
+
: 'several IFC class conditions in one group have no single IDS entity facet');
|
|
205
|
+
return null;
|
|
206
|
+
}
|
|
207
|
+
const [type] = types;
|
|
208
|
+
if (type.kind !== 'ifcType')
|
|
209
|
+
return null;
|
|
210
|
+
if (type.op !== 'in')
|
|
211
|
+
return null; // negation already reported by `mapRule`'s caller
|
|
212
|
+
if (type.exactClass !== true) {
|
|
213
|
+
reasons.push('the IFC class condition includes subclasses (exactClass is off); an IDS entity facet matches the exact class only');
|
|
214
|
+
return null;
|
|
215
|
+
}
|
|
216
|
+
if (predefined.length > 1) {
|
|
217
|
+
reasons.push('several PredefinedType conditions in one group have no single IDS entity facet');
|
|
218
|
+
return null;
|
|
219
|
+
}
|
|
220
|
+
const pt = predefined[0];
|
|
221
|
+
if (pt && (pt.kind !== 'predefinedType' || pt.op !== 'in'))
|
|
222
|
+
return null;
|
|
223
|
+
return {
|
|
224
|
+
type: 'entity',
|
|
225
|
+
name: simpleOrEnumeration(type.values.map((v) => v.toUpperCase())),
|
|
226
|
+
...(pt && pt.kind === 'predefinedType' ? { predefinedType: simpleOrEnumeration(pt.values) } : {}),
|
|
227
|
+
};
|
|
228
|
+
}
|
|
229
|
+
const BOUND_KEYS = ['minInclusive', 'minExclusive', 'maxInclusive', 'maxExclusive'];
|
|
230
|
+
/** Merge `extra`'s bounds into `into`; a reason when both set the same side. */
|
|
231
|
+
function mergeBounds(into, extra) {
|
|
232
|
+
for (const key of BOUND_KEYS) {
|
|
233
|
+
if (extra[key] === undefined)
|
|
234
|
+
continue;
|
|
235
|
+
const side = key.startsWith('min') ? ['minInclusive', 'minExclusive'] : ['maxInclusive', 'maxExclusive'];
|
|
236
|
+
if (side.some((k) => into[k] !== undefined))
|
|
237
|
+
return 'two bounds on the same side of one value have no single IDS restriction';
|
|
238
|
+
into[key] = extra[key];
|
|
239
|
+
}
|
|
240
|
+
return null;
|
|
241
|
+
}
|
|
242
|
+
function facetValue(facet) {
|
|
243
|
+
return facet.type === 'attribute' || facet.type === 'property' ? facet.value : undefined;
|
|
244
|
+
}
|
|
245
|
+
/** Map one group. Every reason is collected, not just the first. */
|
|
246
|
+
export function groupToFacets(group, role, scaleOf = NO_MODEL) {
|
|
247
|
+
const reasons = [];
|
|
248
|
+
const notes = new Set();
|
|
249
|
+
if (group.rules.length === 0) {
|
|
250
|
+
return { ok: false, reasons: [role === 'applicability' ? 'the applicability is empty' : 'the requirement has no conditions'] };
|
|
251
|
+
}
|
|
252
|
+
if (group.combinator === 'OR' && group.rules.length > 1) {
|
|
253
|
+
reasons.push('conditions combined with OR cannot be expressed in IDS 1.0 (facets are always AND-ed)');
|
|
254
|
+
}
|
|
255
|
+
const facets = [];
|
|
256
|
+
for (const rule of group.rules) {
|
|
257
|
+
if ((rule.kind === 'ifcType' || rule.kind === 'predefinedType') && rule.op === 'notIn') {
|
|
258
|
+
reasons.push(`a negated condition ("notIn") cannot be expressed in IDS 1.0`);
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
const entity = entityFacetOf(group.rules, role, reasons);
|
|
262
|
+
if (entity)
|
|
263
|
+
facets.push(entity);
|
|
264
|
+
const byBoundsKey = new Map();
|
|
265
|
+
for (const rule of group.rules) {
|
|
266
|
+
if (rule.kind === 'ifcType' || rule.kind === 'predefinedType')
|
|
267
|
+
continue;
|
|
268
|
+
const mapped = mapRule(rule, scaleOf);
|
|
269
|
+
if ('reason' in mapped) {
|
|
270
|
+
reasons.push(mapped.reason);
|
|
271
|
+
continue;
|
|
272
|
+
}
|
|
273
|
+
const astral = regexNote(rule);
|
|
274
|
+
if (astral)
|
|
275
|
+
notes.add(astral);
|
|
276
|
+
const existing = mapped.boundsKey ? byBoundsKey.get(mapped.boundsKey) : undefined;
|
|
277
|
+
const existingValue = existing ? facetValue(existing) : undefined;
|
|
278
|
+
const newValue = facetValue(mapped.facet);
|
|
279
|
+
if (existingValue?.type === 'bounds' && newValue?.type === 'bounds') {
|
|
280
|
+
const clash = mergeBounds(existingValue, newValue);
|
|
281
|
+
if (clash)
|
|
282
|
+
reasons.push(clash);
|
|
283
|
+
continue;
|
|
284
|
+
}
|
|
285
|
+
if (mapped.boundsKey)
|
|
286
|
+
byBoundsKey.set(mapped.boundsKey, mapped.facet);
|
|
287
|
+
facets.push(mapped.facet);
|
|
288
|
+
}
|
|
289
|
+
return reasons.length > 0 ? { ok: false, reasons } : { ok: true, facets, notes: [...notes] };
|
|
290
|
+
}
|
|
291
|
+
//# sourceMappingURL=rule-to-ids-facets.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rule-to-ids-facets.js","sourceRoot":"","sources":["../../src/ids/rule-to-ids-facets.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* What unit a property or quantity is stored in, across the loaded models,
|
|
3
|
+
* so the IDS export can state a model-unit bound in SI (#5225 decision).
|
|
4
|
+
*
|
|
5
|
+
* Every element carrying the subject, in every model, is found with the
|
|
6
|
+
* search evaluator and read with `readSubject`, the same reader the rule
|
|
7
|
+
* engine compares with. Every value must be recorded with the same SI factor
|
|
8
|
+
* (an explicit `Unit` on one element can differ from the project unit on
|
|
9
|
+
* another); mixed factors, or no element having the value at all, is
|
|
10
|
+
* `unknown` with the reason, and the export refuses that rule.
|
|
11
|
+
*/
|
|
12
|
+
import { type EvaluatorModel } from '../filter/filter-evaluate.js';
|
|
13
|
+
import type { StoredUnitScaleOf } from './rule-to-ids-facets.js';
|
|
14
|
+
export declare function storedUnitScaleOf(models: ReadonlyArray<EvaluatorModel>): StoredUnitScaleOf;
|
|
15
|
+
//# sourceMappingURL=stored-unit-scale.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stored-unit-scale.d.ts","sourceRoot":"","sources":["../../src/ids/stored-unit-scale.ts"],"names":[],"mappings":"AAIA;;;;;;;;;;GAUG;AAEH,OAAO,EAAuB,KAAK,cAAc,EAAE,MAAM,8BAA8B,CAAC;AAGxF,OAAO,KAAK,EAAmB,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AAclF,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,aAAa,CAAC,cAAc,CAAC,GAAG,iBAAiB,CA6B1F"}
|
|
@@ -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
|
+
/**
|
|
5
|
+
* What unit a property or quantity is stored in, across the loaded models,
|
|
6
|
+
* so the IDS export can state a model-unit bound in SI (#5225 decision).
|
|
7
|
+
*
|
|
8
|
+
* Every element carrying the subject, in every model, is found with the
|
|
9
|
+
* search evaluator and read with `readSubject`, the same reader the rule
|
|
10
|
+
* engine compares with. Every value must be recorded with the same SI factor
|
|
11
|
+
* (an explicit `Unit` on one element can differ from the project unit on
|
|
12
|
+
* another); mixed factors, or no element having the value at all, is
|
|
13
|
+
* `unknown` with the reason, and the export refuses that rule.
|
|
14
|
+
*/
|
|
15
|
+
import { evaluateFilterRules } from '../filter/filter-evaluate.js';
|
|
16
|
+
import { readSubject } from '../filter/read-subject.js';
|
|
17
|
+
/** A rule that matches every element carrying `rule`'s subject. */
|
|
18
|
+
function presenceProbe(rule) {
|
|
19
|
+
if (rule.kind === 'quantity') {
|
|
20
|
+
return { kind: 'quantity', setName: rule.setName, setNameKind: rule.setNameKind, quantityName: rule.quantityName, quantityNameKind: rule.quantityNameKind, op: 'gte', value: -Number.MAX_VALUE };
|
|
21
|
+
}
|
|
22
|
+
return { kind: 'property', setName: rule.setName, setNameKind: rule.setNameKind, propertyName: rule.propertyName, propertyNameKind: rule.propertyNameKind, op: 'isSet', value: '' };
|
|
23
|
+
}
|
|
24
|
+
function label(rule) {
|
|
25
|
+
return `${rule.setName}.${rule.kind === 'quantity' ? rule.quantityName : rule.propertyName}`;
|
|
26
|
+
}
|
|
27
|
+
export function storedUnitScaleOf(models) {
|
|
28
|
+
const cache = new Map();
|
|
29
|
+
return (rule) => {
|
|
30
|
+
const key = JSON.stringify(presenceProbe(rule));
|
|
31
|
+
const cached = cache.get(key);
|
|
32
|
+
if (cached)
|
|
33
|
+
return cached;
|
|
34
|
+
const scales = new Set();
|
|
35
|
+
for (const model of models) {
|
|
36
|
+
if (!model.store)
|
|
37
|
+
continue;
|
|
38
|
+
const carriers = evaluateFilterRules(model.id, model.store, [presenceProbe(rule)], 'AND', { limit: Number.MAX_SAFE_INTEGER });
|
|
39
|
+
for (const element of carriers) {
|
|
40
|
+
const subject = readSubject(rule, { store: model.store, expressId: element.expressId });
|
|
41
|
+
for (const scale of subject.valueSiScales ?? [])
|
|
42
|
+
scales.add(scale ?? 'unitless');
|
|
43
|
+
if (scales.size > 1)
|
|
44
|
+
break;
|
|
45
|
+
}
|
|
46
|
+
if (scales.size > 1)
|
|
47
|
+
break;
|
|
48
|
+
}
|
|
49
|
+
let result;
|
|
50
|
+
if (scales.size === 0) {
|
|
51
|
+
result = { kind: 'unknown', reason: `no loaded model has ${label(rule)}, so its unit (and the SI value IDS needs) is unknown` };
|
|
52
|
+
}
|
|
53
|
+
else if (scales.size > 1) {
|
|
54
|
+
result = { kind: 'unknown', reason: `${label(rule)} is recorded in different units across the loaded elements, so no single SI value matches all of them` };
|
|
55
|
+
}
|
|
56
|
+
else {
|
|
57
|
+
const [only] = scales;
|
|
58
|
+
result = only === 'unitless' ? { kind: 'unitless' } : { kind: 'scale', scale: only };
|
|
59
|
+
}
|
|
60
|
+
cache.set(key, result);
|
|
61
|
+
return result;
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
//# sourceMappingURL=stored-unit-scale.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stored-unit-scale.js","sourceRoot":"","sources":["../../src/ids/stored-unit-scale.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `@ifc-lite/rules` — the filter-rule vocabulary, the Path-B evaluator, and
|
|
3
|
+
* the `.rules.json` information-validation engine (#5138 PR 7a). Extracted
|
|
4
|
+
* from `apps/viewer/src/lib/{search,validation}` so `packages/cli` (PR 7b)
|
|
5
|
+
* can run the SAME evaluator the viewer runs — no second implementation,
|
|
6
|
+
* no parity fixture between "what the viewer says" and "what the CLI says".
|
|
7
|
+
*
|
|
8
|
+
* No React, no store, no DOM: every export here takes plain data in
|
|
9
|
+
* (`IfcDataStore`, `EvaluatorModel[]`) and returns plain data out. The
|
|
10
|
+
* viewer's `lib/model-tags/evaluator-models.ts` (turns live store state into
|
|
11
|
+
* `EvaluatorModel[]`) and `lib/validation/rule-set-io-browser.ts`
|
|
12
|
+
* (`exportRuleSet`/`importRuleSetFile`, DOM file I/O) stay in the viewer —
|
|
13
|
+
* not this package's concern.
|
|
14
|
+
*/
|
|
15
|
+
export * from './filter/filter-rules.js';
|
|
16
|
+
export * from './filter/filter-groups.js';
|
|
17
|
+
export * from './filter/filter-rule-guards.js';
|
|
18
|
+
export * from './filter/filter-ops.js';
|
|
19
|
+
export * from './filter/filter-match.js';
|
|
20
|
+
export * from './filter/read-subject.js';
|
|
21
|
+
export * from './filter/filter-evaluate.js';
|
|
22
|
+
export * from './filter/filter-evaluate-groups.js';
|
|
23
|
+
export * from './filter/filter-evaluate-yield.js';
|
|
24
|
+
export * from './filter/filter-evaluate-mutations.js';
|
|
25
|
+
export * from './filter/filter-evaluate-model-tag.js';
|
|
26
|
+
export * from './filter/filter-iteration.js';
|
|
27
|
+
export * from './filter/filter-iteration-source.js';
|
|
28
|
+
export * from './filter/entity-predefined-type.js';
|
|
29
|
+
export * from './filter/lens-material-names.js';
|
|
30
|
+
export * from './filter/model-tag.js';
|
|
31
|
+
export * from './rule-set/rule-set.js';
|
|
32
|
+
export * from './rule-set/rule-set-io.js';
|
|
33
|
+
export * from './rule-set/rule-set-io-requirement.js';
|
|
34
|
+
export * from './rule-set/requirement-text.js';
|
|
35
|
+
export * from './rule-set/between-chip.js';
|
|
36
|
+
export * from './engine/rule-engine.js';
|
|
37
|
+
export { ruleSetToIds, type RuleSetToIdsOptions, type RuleSetToIdsResult, type RefusedRule } from './ids/rule-set-to-ids.js';
|
|
38
|
+
export { idsToRuleSet, type IdsToRuleSetOptions, type IdsToRuleSetResult, type RefusedSpecification } from './ids/ids-to-rule-set.js';
|
|
39
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAIA;;;;;;;;;;;;;GAaG;AAGH,cAAc,0BAA0B,CAAC;AACzC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,gCAAgC,CAAC;AAC/C,cAAc,wBAAwB,CAAC;AACvC,cAAc,0BAA0B,CAAC;AACzC,cAAc,0BAA0B,CAAC;AACzC,cAAc,6BAA6B,CAAC;AAC5C,cAAc,oCAAoC,CAAC;AACnD,cAAc,mCAAmC,CAAC;AAClD,cAAc,uCAAuC,CAAC;AACtD,cAAc,uCAAuC,CAAC;AACtD,cAAc,8BAA8B,CAAC;AAC7C,cAAc,qCAAqC,CAAC;AACpD,cAAc,oCAAoC,CAAC;AACnD,cAAc,iCAAiC,CAAC;AAChD,cAAc,uBAAuB,CAAC;AAGtC,cAAc,wBAAwB,CAAC;AACvC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,uCAAuC,CAAC;AACtD,cAAc,gCAAgC,CAAC;AAC/C,cAAc,4BAA4B,CAAC;AAG3C,cAAc,yBAAyB,CAAC;AAGxC,OAAO,EAAE,YAAY,EAAE,KAAK,mBAAmB,EAAE,KAAK,kBAAkB,EAAE,KAAK,WAAW,EAAE,MAAM,0BAA0B,CAAC;AAC7H,OAAO,EAAE,YAAY,EAAE,KAAK,mBAAmB,EAAE,KAAK,kBAAkB,EAAE,KAAK,oBAAoB,EAAE,MAAM,0BAA0B,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
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
|
+
/**
|
|
5
|
+
* `@ifc-lite/rules` — the filter-rule vocabulary, the Path-B evaluator, and
|
|
6
|
+
* the `.rules.json` information-validation engine (#5138 PR 7a). Extracted
|
|
7
|
+
* from `apps/viewer/src/lib/{search,validation}` so `packages/cli` (PR 7b)
|
|
8
|
+
* can run the SAME evaluator the viewer runs — no second implementation,
|
|
9
|
+
* no parity fixture between "what the viewer says" and "what the CLI says".
|
|
10
|
+
*
|
|
11
|
+
* No React, no store, no DOM: every export here takes plain data in
|
|
12
|
+
* (`IfcDataStore`, `EvaluatorModel[]`) and returns plain data out. The
|
|
13
|
+
* viewer's `lib/model-tags/evaluator-models.ts` (turns live store state into
|
|
14
|
+
* `EvaluatorModel[]`) and `lib/validation/rule-set-io-browser.ts`
|
|
15
|
+
* (`exportRuleSet`/`importRuleSetFile`, DOM file I/O) stay in the viewer —
|
|
16
|
+
* not this package's concern.
|
|
17
|
+
*/
|
|
18
|
+
// ── Filter-rule vocabulary + evaluator ──────────────────────────────────────
|
|
19
|
+
export * from './filter/filter-rules.js';
|
|
20
|
+
export * from './filter/filter-groups.js';
|
|
21
|
+
export * from './filter/filter-rule-guards.js';
|
|
22
|
+
export * from './filter/filter-ops.js';
|
|
23
|
+
export * from './filter/filter-match.js';
|
|
24
|
+
export * from './filter/read-subject.js';
|
|
25
|
+
export * from './filter/filter-evaluate.js';
|
|
26
|
+
export * from './filter/filter-evaluate-groups.js';
|
|
27
|
+
export * from './filter/filter-evaluate-yield.js';
|
|
28
|
+
export * from './filter/filter-evaluate-mutations.js';
|
|
29
|
+
export * from './filter/filter-evaluate-model-tag.js';
|
|
30
|
+
export * from './filter/filter-iteration.js';
|
|
31
|
+
export * from './filter/filter-iteration-source.js';
|
|
32
|
+
export * from './filter/entity-predefined-type.js';
|
|
33
|
+
export * from './filter/lens-material-names.js';
|
|
34
|
+
export * from './filter/model-tag.js';
|
|
35
|
+
// ── `.rules.json` shape + parse/serialize (Node/browser-portable half) ─────
|
|
36
|
+
export * from './rule-set/rule-set.js';
|
|
37
|
+
export * from './rule-set/rule-set-io.js';
|
|
38
|
+
export * from './rule-set/rule-set-io-requirement.js';
|
|
39
|
+
export * from './rule-set/requirement-text.js';
|
|
40
|
+
export * from './rule-set/between-chip.js';
|
|
41
|
+
// ── Validation engine: RuleSetFile + models -> ValidationReport ────────────
|
|
42
|
+
export * from './engine/rule-engine.js';
|
|
43
|
+
// ── IDS interchange: rule set -> IDS 1.0 export, simple IDS -> rule import (#5225)
|
|
44
|
+
export { ruleSetToIds } from './ids/rule-set-to-ids.js';
|
|
45
|
+
export { idsToRuleSet } from './ids/ids-to-rule-set.js';
|
|
46
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;+DAE+D;AAE/D;;;;;;;;;;;;;GAaG;AAEH,+EAA+E;AAC/E,cAAc,0BAA0B,CAAC;AACzC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,gCAAgC,CAAC;AAC/C,cAAc,wBAAwB,CAAC;AACvC,cAAc,0BAA0B,CAAC;AACzC,cAAc,0BAA0B,CAAC;AACzC,cAAc,6BAA6B,CAAC;AAC5C,cAAc,oCAAoC,CAAC;AACnD,cAAc,mCAAmC,CAAC;AAClD,cAAc,uCAAuC,CAAC;AACtD,cAAc,uCAAuC,CAAC;AACtD,cAAc,8BAA8B,CAAC;AAC7C,cAAc,qCAAqC,CAAC;AACpD,cAAc,oCAAoC,CAAC;AACnD,cAAc,iCAAiC,CAAC;AAChD,cAAc,uBAAuB,CAAC;AAEtC,8EAA8E;AAC9E,cAAc,wBAAwB,CAAC;AACvC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,uCAAuC,CAAC;AACtD,cAAc,gCAAgC,CAAC;AAC/C,cAAc,4BAA4B,CAAC;AAE3C,8EAA8E;AAC9E,cAAc,yBAAyB,CAAC;AAExC,oFAAoF;AACpF,OAAO,EAAE,YAAY,EAAuE,MAAM,0BAA0B,CAAC;AAC7H,OAAO,EAAE,YAAY,EAAgF,MAAM,0BAA0B,CAAC"}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `between` display folding for the rule editor (#5138 plan §6's operator
|
|
3
|
+
* table): the persisted `RuleBlock.groups` never gains a `between` rule
|
|
4
|
+
* kind — it stays a plain `gte` rule plus a plain `lte` rule on the same
|
|
5
|
+
* subject, exactly the vocabulary `readSubject`/`filter-ops.ts` already
|
|
6
|
+
* understand (plan §3, §4). "Between" only exists here, as a pure display
|
|
7
|
+
* transform the editor applies on load (fold) and reverses on save
|
|
8
|
+
* (unfold), so `RuleBlockEditor` can show ONE range chip instead of two
|
|
9
|
+
* rows that happen to share a subject.
|
|
10
|
+
*
|
|
11
|
+
* Only `property` / `quantity` / `attribute` rules fold — the three
|
|
12
|
+
* element-requirement kinds whose op is `gte`/`lte` at all (ELEMENT_
|
|
13
|
+
* REQUIREMENT_KINDS in `rule-set-io-requirement.ts`; `name`/`type`/
|
|
14
|
+
* `parent`/`material`/`classification` use `StringOp`, `ifcType`/
|
|
15
|
+
* `predefinedType` use `SetOp` — none of those has a numeric bound to
|
|
16
|
+
* pair).
|
|
17
|
+
*/
|
|
18
|
+
import type { FilterRule } from '../filter/filter-rules.js';
|
|
19
|
+
type Betweenable = Extract<FilterRule, {
|
|
20
|
+
kind: 'property' | 'quantity' | 'attribute';
|
|
21
|
+
}>;
|
|
22
|
+
export interface BetweenChip {
|
|
23
|
+
kind: 'between';
|
|
24
|
+
/** The `gte` rule — its `value` is the range minimum. */
|
|
25
|
+
min: Betweenable;
|
|
26
|
+
/** The `lte` rule on the identical subject — its `value` is the maximum. */
|
|
27
|
+
max: Betweenable;
|
|
28
|
+
}
|
|
29
|
+
export type FoldedRule = FilterRule | BetweenChip;
|
|
30
|
+
export declare function isBetweenChip(row: FoldedRule): row is BetweenChip;
|
|
31
|
+
/**
|
|
32
|
+
* Merge `gte`/`lte` pairs on the identical subject into one `BetweenChip`,
|
|
33
|
+
* regardless of which one appears first. A subject with only a `gte`, only
|
|
34
|
+
* a `lte`, or more than one of either, is left as plain rules — folding
|
|
35
|
+
* only ever removes exactly two entries and adds exactly one, never
|
|
36
|
+
* guesses which of several candidates pairs with which.
|
|
37
|
+
*
|
|
38
|
+
* Pairing happens in a PASS OF ITS OWN, before anything is written to
|
|
39
|
+
* `out`: a single combined pass that pushed a `lte` immediately (because
|
|
40
|
+
* it isn't itself a `gte`) and only later discovered, at its `gte`
|
|
41
|
+
* partner's index, that the two pair up, would leave that `lte` in `out`
|
|
42
|
+
* TWICE — once as the plain rule already pushed, once folded inside the
|
|
43
|
+
* chip — so `[lte(300), gte(100)]` (partner before the `gte` that finds
|
|
44
|
+
* it) silently produced three rules on unfold instead of two. Deciding
|
|
45
|
+
* every pair up front means the emitting pass never has to un-push
|
|
46
|
+
* something it already committed.
|
|
47
|
+
*/
|
|
48
|
+
export declare function foldBetweenPairs(rules: readonly FilterRule[]): FoldedRule[];
|
|
49
|
+
/** Reverses `foldBetweenPairs`: every `BetweenChip` becomes its `min`
|
|
50
|
+
* (`gte`) rule followed by its `max` (`lte`) rule — the exact shape
|
|
51
|
+
* `rule-set-io.ts` persists. */
|
|
52
|
+
export declare function unfoldBetweenChips(rows: readonly FoldedRule[]): FilterRule[];
|
|
53
|
+
export {};
|
|
54
|
+
//# sourceMappingURL=between-chip.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"between-chip.d.ts","sourceRoot":"","sources":["../../src/rule-set/between-chip.ts"],"names":[],"mappings":"AAIA;;;;;;;;;;;;;;;;GAgBG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,2BAA2B,CAAC;AAE5D,KAAK,WAAW,GAAG,OAAO,CAAC,UAAU,EAAE;IAAE,IAAI,EAAE,UAAU,GAAG,UAAU,GAAG,WAAW,CAAA;CAAE,CAAC,CAAC;AAExF,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,SAAS,CAAC;IAChB,yDAAyD;IACzD,GAAG,EAAE,WAAW,CAAC;IACjB,4EAA4E;IAC5E,GAAG,EAAE,WAAW,CAAC;CAClB;AAED,MAAM,MAAM,UAAU,GAAG,UAAU,GAAG,WAAW,CAAC;AAElD,wBAAgB,aAAa,CAAC,GAAG,EAAE,UAAU,GAAG,GAAG,IAAI,WAAW,CAEjE;AAiBD;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,SAAS,UAAU,EAAE,GAAG,UAAU,EAAE,CA0C3E;AAED;;iCAEiC;AACjC,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,SAAS,UAAU,EAAE,GAAG,UAAU,EAAE,CAU5E"}
|