bruce-models 7.1.54 → 7.1.55
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/dist/bruce-models.es5.js +388 -231
- package/dist/bruce-models.es5.js.map +1 -1
- package/dist/bruce-models.umd.js +388 -231
- package/dist/bruce-models.umd.js.map +1 -1
- package/dist/lib/bruce-models.js +1 -1
- package/dist/lib/calculator/calculator.js +387 -236
- package/dist/lib/calculator/calculator.js.map +1 -1
- package/dist/types/bruce-models.d.ts +1 -1
- package/dist/types/calculator/calculator.d.ts +67 -0
- package/package.json +1 -1
|
@@ -77,12 +77,234 @@ var Calculator;
|
|
|
77
77
|
EValueType[EValueType["RandomColor"] = 5] = "RandomColor";
|
|
78
78
|
})(EValueType = Calculator.EValueType || (Calculator.EValueType = {}));
|
|
79
79
|
/**
|
|
80
|
-
*
|
|
81
|
-
*
|
|
82
|
-
* When a value fails to be calculated, the 'defaultValue' is returned.
|
|
83
|
-
* If no 'defaultValue' is provided, then 'null' is returned.
|
|
80
|
+
* Decodes an effective string produced by TraceCalculate back into a structured object.
|
|
81
|
+
* Returns null if the string is null, empty, or does not match the expected format.
|
|
84
82
|
*/
|
|
85
|
-
function
|
|
83
|
+
function DecodeEffective(effective) {
|
|
84
|
+
if (!effective) {
|
|
85
|
+
return null;
|
|
86
|
+
}
|
|
87
|
+
// Format: f{index}:{type}[:{part1}[:{part2}]]
|
|
88
|
+
const match = effective.match(/^f(\d+):([^:]+)(?::([^:]+)(?::([^:]+))?)?$/);
|
|
89
|
+
if (!match) {
|
|
90
|
+
return null;
|
|
91
|
+
}
|
|
92
|
+
const fieldIndex = parseInt(match[1], 10);
|
|
93
|
+
const type = match[2];
|
|
94
|
+
const part1 = match[3] != null ? decodeEffective(match[3]) : null;
|
|
95
|
+
const part2 = match[4] != null ? decodeEffective(match[4]) : null;
|
|
96
|
+
const base = { type, fieldIndex };
|
|
97
|
+
switch (type) {
|
|
98
|
+
case "color":
|
|
99
|
+
if (part1 == null) {
|
|
100
|
+
return null;
|
|
101
|
+
}
|
|
102
|
+
return Object.assign(Object.assign({}, base), { colorStr: part1 });
|
|
103
|
+
case "gradient":
|
|
104
|
+
case "mapping":
|
|
105
|
+
return Object.assign(Object.assign(Object.assign({}, base), (part1 != null && { path: part1 })), (part2 != null && { entityValue: part2 }));
|
|
106
|
+
case "input":
|
|
107
|
+
if (part1 == null || part2 == null) {
|
|
108
|
+
return null;
|
|
109
|
+
}
|
|
110
|
+
return Object.assign(Object.assign({}, base), { template: part1, resolvedValue: part2 });
|
|
111
|
+
case "tag":
|
|
112
|
+
if (part1 == null) {
|
|
113
|
+
return null;
|
|
114
|
+
}
|
|
115
|
+
return Object.assign(Object.assign({}, base), { tagColor: part1 });
|
|
116
|
+
case "random":
|
|
117
|
+
case "fn":
|
|
118
|
+
return base;
|
|
119
|
+
default:
|
|
120
|
+
return null;
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
Calculator.DecodeEffective = DecodeEffective;
|
|
124
|
+
function encodeEffective(str) {
|
|
125
|
+
const s = String(str == null ? "" : str);
|
|
126
|
+
try {
|
|
127
|
+
if (typeof Buffer !== "undefined") {
|
|
128
|
+
return Buffer.from(s).toString("base64").replace(/=+$/, "");
|
|
129
|
+
}
|
|
130
|
+
// Browser fallback
|
|
131
|
+
return btoa(s).replace(/=+$/, "");
|
|
132
|
+
}
|
|
133
|
+
catch (e) {
|
|
134
|
+
return encodeURIComponent(s);
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
function decodeEffective(encoded) {
|
|
138
|
+
try {
|
|
139
|
+
if (typeof Buffer !== "undefined") {
|
|
140
|
+
return Buffer.from(encoded, "base64").toString("utf8");
|
|
141
|
+
}
|
|
142
|
+
return atob(encoded);
|
|
143
|
+
}
|
|
144
|
+
catch (e) {
|
|
145
|
+
return decodeURIComponent(encoded);
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
function _getMappingTrace(value, entity) {
|
|
149
|
+
const attrPaths = parseLegacyPath(value.field);
|
|
150
|
+
for (let i = 0; i < attrPaths.length; i++) {
|
|
151
|
+
const attrPath = attrPaths[i];
|
|
152
|
+
let eValue = entity_1.Entity.GetValue({
|
|
153
|
+
entity: entity,
|
|
154
|
+
path: attrPath
|
|
155
|
+
});
|
|
156
|
+
let isValueNum = !isNaN(+eValue);
|
|
157
|
+
if (eValue == null) {
|
|
158
|
+
isValueNum = false;
|
|
159
|
+
}
|
|
160
|
+
for (let j = 0; j < value.values.length; j++) {
|
|
161
|
+
const option = value.values[j];
|
|
162
|
+
const fieldValues = Array.isArray(option.fieldValue) ? option.fieldValue : [option.fieldValue];
|
|
163
|
+
for (let k = 0; k < fieldValues.length; k++) {
|
|
164
|
+
let mapValue = fieldValues[k];
|
|
165
|
+
// If mapValue is prefixed with "JS:", we evaluate it as JavaScript.
|
|
166
|
+
// This lets us do things like JS:Boolean("${}") as a quick way to map 'existence' to a target value.
|
|
167
|
+
if (typeof mapValue === "string" && mapValue.startsWith("JS:")) {
|
|
168
|
+
try {
|
|
169
|
+
let jsEval = mapValue.replace("JS:", "").trim();
|
|
170
|
+
const attrPathStr = path_utils_1.PathUtils.Wrap(attrPath);
|
|
171
|
+
jsEval = jsEval.replace("${}", "${" + attrPathStr + "}");
|
|
172
|
+
jsEval = bruce_variable_1.BruceVariable.SwapValues({
|
|
173
|
+
str: jsEval,
|
|
174
|
+
entity: entity
|
|
175
|
+
});
|
|
176
|
+
// https://rollupjs.org/guide/en/#avoiding-eval
|
|
177
|
+
// This stops eval warning.
|
|
178
|
+
const eval2 = eval;
|
|
179
|
+
mapValue = eval2(jsEval);
|
|
180
|
+
if (mapValue) {
|
|
181
|
+
return { result: option.appliedValue, attrPath, eValue };
|
|
182
|
+
}
|
|
183
|
+
else {
|
|
184
|
+
continue;
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
catch (exception) {
|
|
188
|
+
const e = exception;
|
|
189
|
+
let suppress = false;
|
|
190
|
+
if (e && typeof e == "object") {
|
|
191
|
+
const msg = e.message;
|
|
192
|
+
suppress = !!msg && (msg.includes("Unexpected end") || msg.includes("got end of script"));
|
|
193
|
+
}
|
|
194
|
+
if (!suppress) {
|
|
195
|
+
console.error(e);
|
|
196
|
+
}
|
|
197
|
+
// Eval failed, therefor not a valid mapping-row.
|
|
198
|
+
continue;
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
let isMapValueNum = !isNaN(+mapValue);
|
|
202
|
+
if (isMapValueNum == null) {
|
|
203
|
+
isMapValueNum = false;
|
|
204
|
+
}
|
|
205
|
+
if (isValueNum && (isMapValueNum || (typeof mapValue === "string" && mapValue.includes("-")))) {
|
|
206
|
+
if (+mapValue == +eValue) {
|
|
207
|
+
return { result: option.appliedValue, attrPath, eValue };
|
|
208
|
+
}
|
|
209
|
+
const mapSplit = mapValue.split("-");
|
|
210
|
+
if (mapSplit.length == 2) {
|
|
211
|
+
const min = mapSplit[0];
|
|
212
|
+
const max = mapSplit[1];
|
|
213
|
+
if (min != "") {
|
|
214
|
+
if (+eValue < +min) {
|
|
215
|
+
continue;
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
if (max != "") {
|
|
219
|
+
if (+eValue > +max) {
|
|
220
|
+
continue;
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
if (min == "" && max == "") {
|
|
224
|
+
continue;
|
|
225
|
+
}
|
|
226
|
+
return { result: option.appliedValue, attrPath, eValue };
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
else {
|
|
230
|
+
if (mapValue == eValue) {
|
|
231
|
+
return { result: option.appliedValue, attrPath, eValue };
|
|
232
|
+
}
|
|
233
|
+
// Case where Entity value is a boolean but the mapping value is a string.
|
|
234
|
+
// Common as mapping value is typically a user-entered string.
|
|
235
|
+
else if (typeof eValue === "boolean" && typeof mapValue === "string") {
|
|
236
|
+
const eValueStr = eValue ? "true" : "false";
|
|
237
|
+
if (mapValue.toLowerCase() == eValueStr) {
|
|
238
|
+
return { result: option.appliedValue, attrPath, eValue };
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
// Handling possible case where the opposite is true.
|
|
242
|
+
// Have not seen this happen yet, but preparing for any future cases.
|
|
243
|
+
else if (typeof mapValue === "boolean" && typeof eValue === "string") {
|
|
244
|
+
const mapValueStr = mapValue ? "true" : "false";
|
|
245
|
+
if (mapValueStr == eValue.toLowerCase()) {
|
|
246
|
+
return { result: option.appliedValue, attrPath, eValue };
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
return { result: null, attrPath: null, eValue: null };
|
|
254
|
+
}
|
|
255
|
+
function _getGradientTrace(value, entity, defaultToMin) {
|
|
256
|
+
const min = +value.points[0].position;
|
|
257
|
+
const max = +value.points[value.points.length - 1].position;
|
|
258
|
+
const attrPaths = parseLegacyPath(value.field);
|
|
259
|
+
for (let i = 0; i < attrPaths.length; i++) {
|
|
260
|
+
const attrPath = attrPaths[i];
|
|
261
|
+
let eValue = entity_1.Entity.GetValue({
|
|
262
|
+
entity: entity,
|
|
263
|
+
path: attrPath
|
|
264
|
+
});
|
|
265
|
+
if (typeof eValue == "string") {
|
|
266
|
+
eValue = Number(eValue);
|
|
267
|
+
}
|
|
268
|
+
if ((!eValue && eValue != 0) || isNaN(eValue)) {
|
|
269
|
+
continue;
|
|
270
|
+
}
|
|
271
|
+
if (eValue >= max) {
|
|
272
|
+
return { result: color_1.Color.ColorFromStr(value.points[value.points.length - 1].color), attrPath, eValue };
|
|
273
|
+
}
|
|
274
|
+
else if (eValue <= min) {
|
|
275
|
+
return { result: color_1.Color.ColorFromStr(value.points[0].color), attrPath, eValue };
|
|
276
|
+
}
|
|
277
|
+
for (let j = 0; j < value.points.length - 1; j++) {
|
|
278
|
+
const pointA = value.points[j];
|
|
279
|
+
const pointB = value.points[j + 1];
|
|
280
|
+
if (eValue >= pointA.position && eValue <= pointB.position) {
|
|
281
|
+
if (pointA.position == pointB.position) {
|
|
282
|
+
return { result: color_1.Color.ColorFromStr(pointA.color), attrPath, eValue };
|
|
283
|
+
}
|
|
284
|
+
const distance = (eValue - pointA.position) / (pointB.position - pointA.position);
|
|
285
|
+
const colorA = color_1.Color.ColorFromStr(pointA.color);
|
|
286
|
+
const colorB = color_1.Color.ColorFromStr(pointB.color);
|
|
287
|
+
return {
|
|
288
|
+
result: {
|
|
289
|
+
red: colorA.red + (colorB.red - colorA.red) * distance,
|
|
290
|
+
green: colorA.green + (colorB.green - colorA.green) * distance,
|
|
291
|
+
blue: colorA.blue + (colorB.blue - colorA.blue) * distance,
|
|
292
|
+
alpha: colorA.alpha + (colorB.alpha - colorA.alpha) * distance
|
|
293
|
+
},
|
|
294
|
+
attrPath,
|
|
295
|
+
eValue
|
|
296
|
+
};
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
// Fallback to min (static, no data path resolved).
|
|
301
|
+
return { result: color_1.Color.ColorFromStr(value.points[0].color), attrPath: null, eValue: null };
|
|
302
|
+
}
|
|
303
|
+
/**
|
|
304
|
+
* Like Calculate, but also returns an 'effective' key describing how the value
|
|
305
|
+
* was derived. See ITraceResult for the key format.
|
|
306
|
+
*/
|
|
307
|
+
function TraceCalculate(params) {
|
|
86
308
|
let { fields, tags, data, defaultValue, type } = params;
|
|
87
309
|
// If params doesn't include a defaultValue, use null.
|
|
88
310
|
// Though passing in undefined is valid!
|
|
@@ -90,7 +312,7 @@ var Calculator;
|
|
|
90
312
|
defaultValue = null;
|
|
91
313
|
}
|
|
92
314
|
if (fields == null) {
|
|
93
|
-
return defaultValue;
|
|
315
|
+
return { value: defaultValue, effective: null };
|
|
94
316
|
}
|
|
95
317
|
if (data == null || typeof data != "object") {
|
|
96
318
|
data = {};
|
|
@@ -135,22 +357,21 @@ var Calculator;
|
|
|
135
357
|
}
|
|
136
358
|
return false;
|
|
137
359
|
};
|
|
138
|
-
// Calculate the value.
|
|
139
360
|
let value = null;
|
|
361
|
+
let computedEffective = null;
|
|
140
362
|
for (let i = 0; i < fieldsArr.length; i++) {
|
|
141
363
|
let field = fieldsArr[i];
|
|
142
|
-
if
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
// field = JSON.parse(JSON.stringify(field));
|
|
147
|
-
}
|
|
364
|
+
// Intermediate trace parts — assembled into effective only if value resolves.
|
|
365
|
+
let traceType = null;
|
|
366
|
+
let tracePart1 = null;
|
|
367
|
+
let tracePart2 = null;
|
|
148
368
|
// Bad data has it set to 'color' but expects the input to be a number.
|
|
149
369
|
if (type == "number" && field.type == EValueType.Color) {
|
|
150
370
|
field.type = EValueType.Input;
|
|
151
371
|
}
|
|
152
372
|
// Custom resolution.
|
|
153
373
|
if (field.value instanceof Function) {
|
|
374
|
+
traceType = "fn";
|
|
154
375
|
value = field.value(data, tags);
|
|
155
376
|
if (type == "number") {
|
|
156
377
|
if (typeof value == "string" && value != "" && value != null && value != undefined) {
|
|
@@ -184,6 +405,8 @@ var Calculator;
|
|
|
184
405
|
break;
|
|
185
406
|
}
|
|
186
407
|
value = field.value;
|
|
408
|
+
traceType = "color";
|
|
409
|
+
tracePart1 = encodeEffective(value);
|
|
187
410
|
value = assertColor(value);
|
|
188
411
|
if (value && type == "string") {
|
|
189
412
|
value = `rgba(${value.red},${value.green},${value.blue},${value.alpha})`;
|
|
@@ -193,10 +416,17 @@ var Calculator;
|
|
|
193
416
|
if (type === "number") {
|
|
194
417
|
break;
|
|
195
418
|
}
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
419
|
+
{
|
|
420
|
+
const gradTrace = _getGradientTrace(field.value, data, shouldRangesDefaultToMin);
|
|
421
|
+
value = assertColor(gradTrace.result);
|
|
422
|
+
traceType = "gradient";
|
|
423
|
+
if (gradTrace.attrPath != null) {
|
|
424
|
+
tracePart1 = encodeEffective(path_utils_1.PathUtils.Wrap(gradTrace.attrPath));
|
|
425
|
+
tracePart2 = encodeEffective(String(gradTrace.eValue));
|
|
426
|
+
}
|
|
427
|
+
if (value && type == "string") {
|
|
428
|
+
value = `rgba(${value.red},${value.green},${value.blue},${value.alpha})`;
|
|
429
|
+
}
|
|
200
430
|
}
|
|
201
431
|
break;
|
|
202
432
|
case EValueType.RandomColor:
|
|
@@ -205,6 +435,7 @@ var Calculator;
|
|
|
205
435
|
}
|
|
206
436
|
value = color_1.Color.RandomColor();
|
|
207
437
|
value = assertColor(value);
|
|
438
|
+
traceType = "random";
|
|
208
439
|
if (value && type == "string") {
|
|
209
440
|
value = `rgba(${value.red},${value.green},${value.blue},${value.alpha})`;
|
|
210
441
|
}
|
|
@@ -213,12 +444,14 @@ var Calculator;
|
|
|
213
444
|
if (type === "number") {
|
|
214
445
|
break;
|
|
215
446
|
}
|
|
216
|
-
for (let
|
|
217
|
-
const tag = tags[
|
|
447
|
+
for (let ti = 0; ti < tags.length; ti++) {
|
|
448
|
+
const tag = tags[ti];
|
|
218
449
|
if (tag.Color) {
|
|
219
450
|
value = color_1.Color.ColorFromStr(tag.Color);
|
|
220
451
|
value = assertColor(value);
|
|
221
452
|
if (value) {
|
|
453
|
+
traceType = "tag";
|
|
454
|
+
tracePart1 = encodeEffective(tag.Color);
|
|
222
455
|
break;
|
|
223
456
|
}
|
|
224
457
|
}
|
|
@@ -232,31 +465,37 @@ var Calculator;
|
|
|
232
465
|
// Eg: Result is a colour, a number, a string.
|
|
233
466
|
// This means we first calculate the value, then validate it in the context of the desired type.
|
|
234
467
|
case EValueType.Input:
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
else if (type == "string") {
|
|
246
|
-
if (typeof value == "number") {
|
|
247
|
-
value = String(value);
|
|
248
|
-
}
|
|
249
|
-
else if (typeof value == "object") {
|
|
250
|
-
if (isColor(value)) {
|
|
251
|
-
value = `rgba(${value.red},${value.green},${value.blue},${value.alpha})`;
|
|
468
|
+
{
|
|
469
|
+
const inputTemplate = String(field.value);
|
|
470
|
+
value = GetInputValue(field.value, data);
|
|
471
|
+
if (value != null) {
|
|
472
|
+
traceType = "input";
|
|
473
|
+
tracePart1 = encodeEffective(inputTemplate);
|
|
474
|
+
tracePart2 = encodeEffective(String(value));
|
|
475
|
+
if (type == "number") {
|
|
476
|
+
if (typeof value == "string" && value != "" && value != null && value != undefined) {
|
|
477
|
+
value = Number(value);
|
|
252
478
|
}
|
|
253
|
-
else {
|
|
479
|
+
else if (typeof value != "number") {
|
|
254
480
|
value = null;
|
|
255
481
|
}
|
|
256
482
|
}
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
483
|
+
else if (type == "string") {
|
|
484
|
+
if (typeof value == "number") {
|
|
485
|
+
value = String(value);
|
|
486
|
+
}
|
|
487
|
+
else if (typeof value == "object") {
|
|
488
|
+
if (isColor(value)) {
|
|
489
|
+
value = `rgba(${value.red},${value.green},${value.blue},${value.alpha})`;
|
|
490
|
+
}
|
|
491
|
+
else {
|
|
492
|
+
value = null;
|
|
493
|
+
}
|
|
494
|
+
}
|
|
495
|
+
}
|
|
496
|
+
else if (type == "color") {
|
|
497
|
+
value = assertColor(value);
|
|
498
|
+
}
|
|
260
499
|
}
|
|
261
500
|
}
|
|
262
501
|
break;
|
|
@@ -264,31 +503,39 @@ var Calculator;
|
|
|
264
503
|
// Eg: mapping a value to a Client File ID, or a colour, or a number.
|
|
265
504
|
// This means we first calculate the value, then validate it in the context of the desired type.
|
|
266
505
|
case EValueType.Mapping:
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
}
|
|
276
|
-
}
|
|
277
|
-
else if (type == "string") {
|
|
278
|
-
if (typeof value == "number") {
|
|
279
|
-
value = String(value);
|
|
506
|
+
{
|
|
507
|
+
const mapTrace = _getMappingTrace(field.value, data);
|
|
508
|
+
value = mapTrace.result;
|
|
509
|
+
if (value != null) {
|
|
510
|
+
traceType = "mapping";
|
|
511
|
+
if (mapTrace.attrPath != null) {
|
|
512
|
+
tracePart1 = encodeEffective(path_utils_1.PathUtils.Wrap(mapTrace.attrPath));
|
|
513
|
+
tracePart2 = encodeEffective(String(mapTrace.eValue));
|
|
280
514
|
}
|
|
281
|
-
|
|
282
|
-
if (
|
|
283
|
-
value =
|
|
515
|
+
if (type == "number") {
|
|
516
|
+
if (typeof value == "string" && value != "" && value != null && value != undefined) {
|
|
517
|
+
value = Number(value);
|
|
284
518
|
}
|
|
285
|
-
else {
|
|
519
|
+
else if (typeof value != "number") {
|
|
286
520
|
value = null;
|
|
287
521
|
}
|
|
288
522
|
}
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
523
|
+
else if (type == "string") {
|
|
524
|
+
if (typeof value == "number") {
|
|
525
|
+
value = String(value);
|
|
526
|
+
}
|
|
527
|
+
else if (typeof value == "object") {
|
|
528
|
+
if (isColor(value)) {
|
|
529
|
+
value = `rgba(${value.red},${value.green},${value.blue},${value.alpha})`;
|
|
530
|
+
}
|
|
531
|
+
else {
|
|
532
|
+
value = null;
|
|
533
|
+
}
|
|
534
|
+
}
|
|
535
|
+
}
|
|
536
|
+
else if (type == "color") {
|
|
537
|
+
value = assertColor(typeof value === "number" ? String(value) : value);
|
|
538
|
+
}
|
|
292
539
|
}
|
|
293
540
|
}
|
|
294
541
|
break;
|
|
@@ -312,11 +559,34 @@ var Calculator;
|
|
|
312
559
|
}
|
|
313
560
|
}
|
|
314
561
|
if (value != null) {
|
|
562
|
+
if (traceType != null) {
|
|
563
|
+
if (tracePart1 != null && tracePart2 != null) {
|
|
564
|
+
computedEffective = `f${i}:${traceType}:${tracePart1}:${tracePart2}`;
|
|
565
|
+
}
|
|
566
|
+
else if (tracePart1 != null) {
|
|
567
|
+
computedEffective = `f${i}:${traceType}:${tracePart1}`;
|
|
568
|
+
}
|
|
569
|
+
else {
|
|
570
|
+
computedEffective = `f${i}:${traceType}`;
|
|
571
|
+
}
|
|
572
|
+
}
|
|
315
573
|
break;
|
|
316
574
|
}
|
|
317
575
|
}
|
|
318
|
-
|
|
319
|
-
|
|
576
|
+
return {
|
|
577
|
+
value: value != null ? value : defaultValue,
|
|
578
|
+
effective: value != null ? computedEffective : null
|
|
579
|
+
};
|
|
580
|
+
}
|
|
581
|
+
Calculator.TraceCalculate = TraceCalculate;
|
|
582
|
+
/**
|
|
583
|
+
* Calculates a value-type 'T' based on given set of fields.
|
|
584
|
+
* The supplied data + tags are fed into the calculation.
|
|
585
|
+
* When a value fails to be calculated, the 'defaultValue' is returned.
|
|
586
|
+
* If no 'defaultValue' is provided, then 'null' is returned.
|
|
587
|
+
*/
|
|
588
|
+
function Calculate(params) {
|
|
589
|
+
return TraceCalculate(params).value;
|
|
320
590
|
}
|
|
321
591
|
Calculator.Calculate = Calculate;
|
|
322
592
|
/**
|
|
@@ -328,13 +598,7 @@ var Calculator;
|
|
|
328
598
|
* @returns
|
|
329
599
|
*/
|
|
330
600
|
function GetValue(fields, entity = {}, tags = []) {
|
|
331
|
-
return
|
|
332
|
-
fields: fields,
|
|
333
|
-
data: entity,
|
|
334
|
-
defaultValue: null,
|
|
335
|
-
tags: tags,
|
|
336
|
-
type: "any"
|
|
337
|
-
});
|
|
601
|
+
return TraceGetValue(fields, entity, tags).value;
|
|
338
602
|
}
|
|
339
603
|
Calculator.GetValue = GetValue;
|
|
340
604
|
/**
|
|
@@ -345,13 +609,7 @@ var Calculator;
|
|
|
345
609
|
* @param tags
|
|
346
610
|
*/
|
|
347
611
|
function GetColor(fields, entity = {}, tags = []) {
|
|
348
|
-
return
|
|
349
|
-
fields: fields,
|
|
350
|
-
data: entity,
|
|
351
|
-
defaultValue: null,
|
|
352
|
-
tags: tags,
|
|
353
|
-
type: "color"
|
|
354
|
-
});
|
|
612
|
+
return TraceGetColor(fields, entity, tags).value;
|
|
355
613
|
}
|
|
356
614
|
Calculator.GetColor = GetColor;
|
|
357
615
|
/**
|
|
@@ -363,13 +621,7 @@ var Calculator;
|
|
|
363
621
|
* @returns
|
|
364
622
|
*/
|
|
365
623
|
function GetNumber(fields, entity = {}, tags = []) {
|
|
366
|
-
return
|
|
367
|
-
fields: fields,
|
|
368
|
-
data: entity,
|
|
369
|
-
defaultValue: null,
|
|
370
|
-
tags: tags,
|
|
371
|
-
type: "number"
|
|
372
|
-
});
|
|
624
|
+
return TraceGetNumber(fields, entity, tags).value;
|
|
373
625
|
}
|
|
374
626
|
Calculator.GetNumber = GetNumber;
|
|
375
627
|
/**
|
|
@@ -381,15 +633,61 @@ var Calculator;
|
|
|
381
633
|
* @returns
|
|
382
634
|
*/
|
|
383
635
|
function GetString(fields, entity = {}, tags = []) {
|
|
384
|
-
return
|
|
385
|
-
|
|
636
|
+
return TraceGetString(fields, entity, tags).value;
|
|
637
|
+
}
|
|
638
|
+
Calculator.GetString = GetString;
|
|
639
|
+
/**
|
|
640
|
+
* Like GetValue, but also returns 'effective' describing how the value was derived.
|
|
641
|
+
*/
|
|
642
|
+
function TraceGetValue(fields, entity = {}, tags = []) {
|
|
643
|
+
return TraceCalculate({
|
|
644
|
+
fields,
|
|
645
|
+
data: entity,
|
|
646
|
+
defaultValue: null,
|
|
647
|
+
tags,
|
|
648
|
+
type: "any"
|
|
649
|
+
});
|
|
650
|
+
}
|
|
651
|
+
Calculator.TraceGetValue = TraceGetValue;
|
|
652
|
+
/**
|
|
653
|
+
* Like GetColor, but also returns 'effective' describing how the color was derived.
|
|
654
|
+
*/
|
|
655
|
+
function TraceGetColor(fields, entity = {}, tags = []) {
|
|
656
|
+
return TraceCalculate({
|
|
657
|
+
fields,
|
|
658
|
+
data: entity,
|
|
659
|
+
defaultValue: null,
|
|
660
|
+
tags,
|
|
661
|
+
type: "color"
|
|
662
|
+
});
|
|
663
|
+
}
|
|
664
|
+
Calculator.TraceGetColor = TraceGetColor;
|
|
665
|
+
/**
|
|
666
|
+
* Like GetNumber, but also returns 'effective' describing how the number was derived.
|
|
667
|
+
*/
|
|
668
|
+
function TraceGetNumber(fields, entity = {}, tags = []) {
|
|
669
|
+
return TraceCalculate({
|
|
670
|
+
fields,
|
|
386
671
|
data: entity,
|
|
387
672
|
defaultValue: null,
|
|
388
|
-
tags
|
|
673
|
+
tags,
|
|
674
|
+
type: "number"
|
|
675
|
+
});
|
|
676
|
+
}
|
|
677
|
+
Calculator.TraceGetNumber = TraceGetNumber;
|
|
678
|
+
/**
|
|
679
|
+
* Like GetString, but also returns 'effective' describing how the string was derived.
|
|
680
|
+
*/
|
|
681
|
+
function TraceGetString(fields, entity = {}, tags = []) {
|
|
682
|
+
return TraceCalculate({
|
|
683
|
+
fields,
|
|
684
|
+
data: entity,
|
|
685
|
+
defaultValue: null,
|
|
686
|
+
tags,
|
|
389
687
|
type: "string"
|
|
390
688
|
});
|
|
391
689
|
}
|
|
392
|
-
Calculator.
|
|
690
|
+
Calculator.TraceGetString = TraceGetString;
|
|
393
691
|
/**
|
|
394
692
|
* Calculates a mapping value. This can return any value type.
|
|
395
693
|
* It is intended to be parsed and validated within a value-type context. Eg: GetColor, GetNumber, GetString.
|
|
@@ -398,114 +696,7 @@ var Calculator;
|
|
|
398
696
|
* @returns
|
|
399
697
|
*/
|
|
400
698
|
function GetMappingValue(value, entity) {
|
|
401
|
-
|
|
402
|
-
for (let i = 0; i < attrPaths.length; i++) {
|
|
403
|
-
const attrPath = attrPaths[i];
|
|
404
|
-
let eValue = entity_1.Entity.GetValue({
|
|
405
|
-
entity: entity,
|
|
406
|
-
path: attrPath
|
|
407
|
-
});
|
|
408
|
-
let isValueNum = !isNaN(+eValue);
|
|
409
|
-
if (eValue == null) {
|
|
410
|
-
isValueNum = false;
|
|
411
|
-
}
|
|
412
|
-
for (let i = 0; i < value.values.length; i++) {
|
|
413
|
-
const option = value.values[i];
|
|
414
|
-
const fieldValues = Array.isArray(option.fieldValue) ? option.fieldValue : [option.fieldValue];
|
|
415
|
-
// Check each field value in the array.
|
|
416
|
-
for (let j = 0; j < fieldValues.length; j++) {
|
|
417
|
-
let mapValue = fieldValues[j];
|
|
418
|
-
// If mapValue is prefixed with "JS:", we evaluate it as JavaScript.
|
|
419
|
-
// This lets us do things like JS:Boolean("${}") as a quick way to map 'existence' to a target value.
|
|
420
|
-
if (typeof mapValue === "string" && mapValue.startsWith("JS:")) {
|
|
421
|
-
try {
|
|
422
|
-
let jsEval = mapValue.replace("JS:", "").trim();
|
|
423
|
-
const attrPathStr = path_utils_1.PathUtils.Wrap(attrPath);
|
|
424
|
-
jsEval = jsEval.replace("${}", "${" + attrPathStr + "}");
|
|
425
|
-
jsEval = bruce_variable_1.BruceVariable.SwapValues({
|
|
426
|
-
str: jsEval,
|
|
427
|
-
entity: entity
|
|
428
|
-
});
|
|
429
|
-
// https://rollupjs.org/guide/en/#avoiding-eval
|
|
430
|
-
// This stops eval warning.
|
|
431
|
-
const eval2 = eval;
|
|
432
|
-
mapValue = eval2(jsEval);
|
|
433
|
-
// We currently expect eval to return a validity bool.
|
|
434
|
-
// So it either matches and we return it, or it doesn't and we continue.
|
|
435
|
-
if (mapValue) {
|
|
436
|
-
return option.appliedValue;
|
|
437
|
-
}
|
|
438
|
-
else {
|
|
439
|
-
continue;
|
|
440
|
-
}
|
|
441
|
-
}
|
|
442
|
-
catch (exception) {
|
|
443
|
-
const e = exception;
|
|
444
|
-
let suppress = false;
|
|
445
|
-
if (e && typeof e == "object") {
|
|
446
|
-
const msg = e.message;
|
|
447
|
-
suppress = !!msg && (msg.includes("Unexpected end") || msg.includes("got end of script"));
|
|
448
|
-
}
|
|
449
|
-
if (!suppress) {
|
|
450
|
-
console.error(e);
|
|
451
|
-
}
|
|
452
|
-
// Eval failed, therefor not a valid mapping-row.
|
|
453
|
-
continue;
|
|
454
|
-
}
|
|
455
|
-
}
|
|
456
|
-
let isMapValueNum = !isNaN(+mapValue);
|
|
457
|
-
if (isMapValueNum == null) {
|
|
458
|
-
isMapValueNum = false;
|
|
459
|
-
}
|
|
460
|
-
if (isValueNum && (isMapValueNum || (typeof mapValue === "string" && mapValue.includes("-")))) {
|
|
461
|
-
if (+mapValue == +eValue) {
|
|
462
|
-
return option.appliedValue;
|
|
463
|
-
}
|
|
464
|
-
const mapSplit = mapValue.split("-");
|
|
465
|
-
if (mapSplit.length == 2) {
|
|
466
|
-
const min = mapSplit[0];
|
|
467
|
-
const max = mapSplit[1];
|
|
468
|
-
if (min != "") {
|
|
469
|
-
if (+eValue < +min) {
|
|
470
|
-
continue;
|
|
471
|
-
}
|
|
472
|
-
}
|
|
473
|
-
if (max != "") {
|
|
474
|
-
if (+eValue > +max) {
|
|
475
|
-
continue;
|
|
476
|
-
}
|
|
477
|
-
}
|
|
478
|
-
if (min == "" && max == "") {
|
|
479
|
-
continue;
|
|
480
|
-
}
|
|
481
|
-
return option.appliedValue;
|
|
482
|
-
}
|
|
483
|
-
}
|
|
484
|
-
else {
|
|
485
|
-
if (mapValue == eValue) {
|
|
486
|
-
return option.appliedValue;
|
|
487
|
-
}
|
|
488
|
-
// Case where Entity value is a boolean but the mapping value is a string.
|
|
489
|
-
// Common as mapping value is typically a user-entered string.
|
|
490
|
-
else if (typeof eValue === "boolean" && typeof mapValue === "string") {
|
|
491
|
-
const eValueStr = eValue ? "true" : "false";
|
|
492
|
-
if (mapValue.toLowerCase() == eValueStr) {
|
|
493
|
-
return option.appliedValue;
|
|
494
|
-
}
|
|
495
|
-
}
|
|
496
|
-
// Handling possible case where the opposite is true.
|
|
497
|
-
// Have not seen this happen yet, but preparing for any future cases.
|
|
498
|
-
else if (typeof mapValue === "boolean" && typeof eValue === "string") {
|
|
499
|
-
const mapValueStr = mapValue ? "true" : "false";
|
|
500
|
-
if (mapValueStr == eValue.toLowerCase()) {
|
|
501
|
-
return option.appliedValue;
|
|
502
|
-
}
|
|
503
|
-
}
|
|
504
|
-
}
|
|
505
|
-
}
|
|
506
|
-
}
|
|
507
|
-
}
|
|
508
|
-
return null;
|
|
699
|
+
return _getMappingTrace(value, entity).result;
|
|
509
700
|
}
|
|
510
701
|
Calculator.GetMappingValue = GetMappingValue;
|
|
511
702
|
/**
|
|
@@ -518,47 +709,7 @@ var Calculator;
|
|
|
518
709
|
* @returns
|
|
519
710
|
*/
|
|
520
711
|
function GetGradientValue(value, entity, defaultToMin) {
|
|
521
|
-
|
|
522
|
-
const max = +value.points[value.points.length - 1].position;
|
|
523
|
-
const attrPaths = parseLegacyPath(value.field);
|
|
524
|
-
for (let i = 0; i < attrPaths.length; i++) {
|
|
525
|
-
const attrPath = attrPaths[i];
|
|
526
|
-
let eValue = entity_1.Entity.GetValue({
|
|
527
|
-
entity: entity,
|
|
528
|
-
path: attrPath
|
|
529
|
-
});
|
|
530
|
-
if (typeof eValue == "string") {
|
|
531
|
-
eValue = Number(eValue);
|
|
532
|
-
}
|
|
533
|
-
if ((!eValue && eValue != 0) || isNaN(eValue)) {
|
|
534
|
-
continue;
|
|
535
|
-
}
|
|
536
|
-
if (eValue >= max) {
|
|
537
|
-
return color_1.Color.ColorFromStr(value.points[value.points.length - 1].color);
|
|
538
|
-
}
|
|
539
|
-
else if (eValue <= min) {
|
|
540
|
-
return color_1.Color.ColorFromStr(value.points[0].color);
|
|
541
|
-
}
|
|
542
|
-
for (let i = 0; i < value.points.length - 1; i++) {
|
|
543
|
-
const pointA = value.points[i];
|
|
544
|
-
const pointB = value.points[i + 1];
|
|
545
|
-
if (eValue >= pointA.position && eValue <= pointB.position) {
|
|
546
|
-
if (pointA.position == pointB.position) {
|
|
547
|
-
return color_1.Color.ColorFromStr(pointA.color);
|
|
548
|
-
}
|
|
549
|
-
const distance = (eValue - pointA.position) / (pointB.position - pointA.position);
|
|
550
|
-
const colorA = color_1.Color.ColorFromStr(pointA.color);
|
|
551
|
-
const colorB = color_1.Color.ColorFromStr(pointB.color);
|
|
552
|
-
return {
|
|
553
|
-
red: colorA.red + (colorB.red - colorA.red) * distance,
|
|
554
|
-
green: colorA.green + (colorB.green - colorA.green) * distance,
|
|
555
|
-
blue: colorA.blue + (colorB.blue - colorA.blue) * distance,
|
|
556
|
-
alpha: colorA.alpha + (colorB.alpha - colorA.alpha) * distance
|
|
557
|
-
};
|
|
558
|
-
}
|
|
559
|
-
}
|
|
560
|
-
}
|
|
561
|
-
return color_1.Color.ColorFromStr(value.points[0].color);
|
|
712
|
+
return _getGradientTrace(value, entity, defaultToMin).result;
|
|
562
713
|
}
|
|
563
714
|
Calculator.GetGradientValue = GetGradientValue;
|
|
564
715
|
/**
|