@reekon-tools/boldr-utils 1.4.17 → 1.4.19
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.
|
@@ -102,6 +102,24 @@ export const calculateFormula = (formula, formulas, columns, tableConfig, measur
|
|
|
102
102
|
currentMappings[variable] = mapping;
|
|
103
103
|
}
|
|
104
104
|
}
|
|
105
|
+
// Validate that all required inputs are filled out
|
|
106
|
+
const missingInputs = [];
|
|
107
|
+
for (const [variable, mapping] of Object.entries(currentMappings)) {
|
|
108
|
+
const mappingObj = typeof mapping === 'string'
|
|
109
|
+
? { id: mapping, type: 'column' }
|
|
110
|
+
: mapping;
|
|
111
|
+
// Only check column references (formula references are handled separately)
|
|
112
|
+
if (mappingObj.type === 'column' || !mappingObj.type) {
|
|
113
|
+
const columnId = mappingObj.id;
|
|
114
|
+
if (!(columnId in valueMap)) {
|
|
115
|
+
missingInputs.push(variable);
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
if (missingInputs.length > 0) {
|
|
120
|
+
console.warn(`Not all inputs are filled out. Missing values for: ${missingInputs.join(', ')}`);
|
|
121
|
+
return null;
|
|
122
|
+
}
|
|
105
123
|
const result = evaluateFormula({
|
|
106
124
|
expression: formula.expression,
|
|
107
125
|
mappings: currentMappings,
|
|
@@ -1,52 +1,8 @@
|
|
|
1
1
|
import { Units } from '../types/firestore.js';
|
|
2
2
|
import { create, all } from 'mathjs';
|
|
3
|
-
//
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
const radToDeg = (radians) => (radians * 180) / Math.PI;
|
|
7
|
-
// Create a custom mathjs instance with degree-based trigonometric functions
|
|
8
|
-
const math = create(all);
|
|
9
|
-
// Create degree-based trigonometric functions that accept degrees as input
|
|
10
|
-
// and return results in degrees for inverse functions
|
|
11
|
-
// These functions handle mathjs types by converting to numbers
|
|
12
|
-
const degreeTrigFunctions = {
|
|
13
|
-
sin: (x) => {
|
|
14
|
-
const degrees = typeof x === 'number' ? x : Number(x);
|
|
15
|
-
return Math.sin(degToRad(degrees));
|
|
16
|
-
},
|
|
17
|
-
cos: (x) => {
|
|
18
|
-
const degrees = typeof x === 'number' ? x : Number(x);
|
|
19
|
-
return Math.cos(degToRad(degrees));
|
|
20
|
-
},
|
|
21
|
-
tan: (x) => {
|
|
22
|
-
const degrees = typeof x === 'number' ? x : Number(x);
|
|
23
|
-
return Math.tan(degToRad(degrees));
|
|
24
|
-
},
|
|
25
|
-
asin: (x) => {
|
|
26
|
-
const value = typeof x === 'number' ? x : Number(x);
|
|
27
|
-
return radToDeg(Math.asin(value));
|
|
28
|
-
},
|
|
29
|
-
acos: (x) => {
|
|
30
|
-
const value = typeof x === 'number' ? x : Number(x);
|
|
31
|
-
return radToDeg(Math.acos(value));
|
|
32
|
-
},
|
|
33
|
-
atan: (x) => {
|
|
34
|
-
const value = typeof x === 'number' ? x : Number(x);
|
|
35
|
-
return radToDeg(Math.atan(value));
|
|
36
|
-
},
|
|
37
|
-
atan2: (y, x) => {
|
|
38
|
-
const yVal = typeof y === 'number' ? y : Number(y);
|
|
39
|
-
const xVal = typeof x === 'number' ? x : Number(x);
|
|
40
|
-
return radToDeg(Math.atan2(yVal, xVal));
|
|
41
|
-
},
|
|
42
|
-
};
|
|
43
|
-
// Override the trigonometric functions in mathjs using import
|
|
44
|
-
// The override: true option ensures existing functions are replaced
|
|
45
|
-
math.import(degreeTrigFunctions, { override: true });
|
|
46
|
-
// Verify the functions are overridden
|
|
47
|
-
if (typeof math.sin !== 'function') {
|
|
48
|
-
console.warn('Warning: math.sin override may have failed');
|
|
49
|
-
}
|
|
3
|
+
// Create a custom mathjs instance configured to use degrees instead of radians
|
|
4
|
+
// @ts-ignore
|
|
5
|
+
const math = create(all, { angle: 'deg' });
|
|
50
6
|
const compile = math.compile.bind(math);
|
|
51
7
|
const mathUnit = math.unit.bind(math);
|
|
52
8
|
// Cache for evaluated formulas to improve performance
|
|
@@ -169,30 +125,6 @@ export function evaluateFormula({ expression, mappings, valueMap, unit, formulas
|
|
|
169
125
|
}
|
|
170
126
|
evaluationStack.add(formulaId);
|
|
171
127
|
try {
|
|
172
|
-
// Validate that all required inputs are available before building scope
|
|
173
|
-
const missingInputs = [];
|
|
174
|
-
for (const [variable, rawMapping] of Object.entries(currentMappings)) {
|
|
175
|
-
const mapping = normalizeMapping(rawMapping);
|
|
176
|
-
if (mapping.type === 'measurement') {
|
|
177
|
-
// Check if column reference exists in valueMap
|
|
178
|
-
if (!(mapping.id in valueMap)) {
|
|
179
|
-
missingInputs.push(variable);
|
|
180
|
-
}
|
|
181
|
-
}
|
|
182
|
-
else if (mapping.type === 'formula') {
|
|
183
|
-
// Check if formula reference exists
|
|
184
|
-
const referencedFormula = formulas.find((f) => f.id === mapping.id);
|
|
185
|
-
if (!referencedFormula) {
|
|
186
|
-
missingInputs.push(variable);
|
|
187
|
-
}
|
|
188
|
-
// Note: We don't validate nested formula inputs here to avoid double evaluation
|
|
189
|
-
// The nested formula will validate its own inputs when evaluated
|
|
190
|
-
}
|
|
191
|
-
}
|
|
192
|
-
// If any direct inputs are missing, throw an error
|
|
193
|
-
if (missingInputs.length > 0) {
|
|
194
|
-
throw new Error(`Missing required inputs for formula ${formulaId}: ${missingInputs.join(', ')}`);
|
|
195
|
-
}
|
|
196
128
|
const scope = {};
|
|
197
129
|
const normalizedUnit = normalizeUnitForMathJS(unit);
|
|
198
130
|
// Build scope by resolving each variable
|
|
@@ -200,7 +132,6 @@ export function evaluateFormula({ expression, mappings, valueMap, unit, formulas
|
|
|
200
132
|
const mapping = normalizeMapping(rawMapping);
|
|
201
133
|
if (mapping.type === 'measurement') {
|
|
202
134
|
// Handle measurement/column reference
|
|
203
|
-
// At this point we know it exists (validated above), but use ?? 0 as fallback
|
|
204
135
|
const micrometers = valueMap[mapping.id] ?? 0;
|
|
205
136
|
if (micrometers === 0) {
|
|
206
137
|
console.warn(`⚠️ Zero or missing value for mapping ID "${mapping.id}"`);
|
|
@@ -215,7 +146,6 @@ export function evaluateFormula({ expression, mappings, valueMap, unit, formulas
|
|
|
215
146
|
throw new Error(`Referenced formula not found: ${mapping.id}`);
|
|
216
147
|
}
|
|
217
148
|
// Recursively evaluate the referenced formula
|
|
218
|
-
// If it has missing inputs, it will throw an error which we'll catch
|
|
219
149
|
const nestedResult = evaluateNestedFormula(referencedFormula.id, referencedFormula.expression, referencedFormula.variableToColumnMap);
|
|
220
150
|
// Convert result to current unit with error handling
|
|
221
151
|
let resultInUnit;
|
|
@@ -292,14 +222,8 @@ export function evaluateFormula({ expression, mappings, valueMap, unit, formulas
|
|
|
292
222
|
return result;
|
|
293
223
|
}
|
|
294
224
|
catch (err) {
|
|
295
|
-
const errorMessage = err instanceof Error ? err.message : String(err);
|
|
296
|
-
// If the error is about missing inputs, return null to match the behavior in temp.ts
|
|
297
|
-
if (errorMessage.includes('Missing required inputs') || errorMessage.includes('missing')) {
|
|
298
|
-
console.warn('❌ Formula evaluation failed due to missing inputs:', errorMessage);
|
|
299
|
-
return null;
|
|
300
|
-
}
|
|
301
225
|
console.warn('❌ Formula evaluation failed:', err);
|
|
302
|
-
return
|
|
226
|
+
return err instanceof Error ? err.message : 'Error';
|
|
303
227
|
}
|
|
304
228
|
}
|
|
305
229
|
// Legacy createFormulaScope function for backward compatibility
|
|
@@ -248,6 +248,36 @@ export interface Measurement extends FirestoreDoc, Timestamps, CreatedBy {
|
|
|
248
248
|
type?: MeasurementType;
|
|
249
249
|
note?: string;
|
|
250
250
|
}
|
|
251
|
+
export interface Label extends FirestoreDoc, Timestamps {
|
|
252
|
+
name: string;
|
|
253
|
+
projectId: string;
|
|
254
|
+
jobId: string;
|
|
255
|
+
rows: LabelRow[];
|
|
256
|
+
rowSizes: number[];
|
|
257
|
+
isPublic: boolean;
|
|
258
|
+
}
|
|
259
|
+
export interface LabelRow {
|
|
260
|
+
id: string;
|
|
261
|
+
cells: LabelCell[];
|
|
262
|
+
colSizes: number[];
|
|
263
|
+
}
|
|
264
|
+
export interface LabelCell {
|
|
265
|
+
id: string;
|
|
266
|
+
type: 'none' | 'image' | 'text' | 'qr' | 'company' | 'icon' | 'measurement';
|
|
267
|
+
fileId?: string;
|
|
268
|
+
value?: string;
|
|
269
|
+
groupId?: string;
|
|
270
|
+
columnId?: string;
|
|
271
|
+
index?: number;
|
|
272
|
+
columnType?: ColumnType;
|
|
273
|
+
textOptions?: {
|
|
274
|
+
bold: boolean;
|
|
275
|
+
italic: boolean;
|
|
276
|
+
underline: boolean;
|
|
277
|
+
verticalAlign: 'top' | 'center' | 'bottom';
|
|
278
|
+
horizontalAlign: 'left' | 'center' | 'right';
|
|
279
|
+
};
|
|
280
|
+
}
|
|
251
281
|
export declare enum Units {
|
|
252
282
|
Centimeters = "cm",
|
|
253
283
|
Millimeters = "mm",
|