formulab 0.10.1 → 0.10.3

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/README.md CHANGED
@@ -1,659 +1,659 @@
1
- # formulab
2
-
3
- > Industrial & manufacturing calculation library for engineers
4
-
5
- [![npm version](https://img.shields.io/npm/v/formulab.svg)](https://www.npmjs.com/package/formulab)
6
- [![CI](https://github.com/iyulab/formulab/actions/workflows/ci.yml/badge.svg)](https://github.com/iyulab/formulab/actions/workflows/ci.yml)
7
- [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
8
- [![TypeScript](https://img.shields.io/badge/TypeScript-Ready-blue.svg)](https://www.typescriptlang.org/)
9
-
10
- A comprehensive collection of engineering formulas and calculations for manufacturing, quality control, logistics, and industrial applications. Zero dependencies, fully typed, tree-shakeable.
11
-
12
- ## Features
13
-
14
- - **174 industrial calculations + 8 type guards** — OEE, Cpk, SPC control charts, Gage R&R, Weibull, metal weight, CNC machining, GD&T, pipe flow, CBM, NIOSH lifting, PMV/PPD, arc flash, battery SOH, GHG emissions, PID tuning, and more
15
- - **14 specialized domains** — Quality, Metal, Chemical, Electronics, Construction, Automotive, Logistics, Energy, Safety, Food, Utility, Battery, Environmental, Machining
16
- - **Zero dependencies** — Lightweight and fast
17
- - **TypeScript first** — Full type definitions included
18
- - **Tree-shakeable** — Import only what you need
19
- - **2,494 tests** — Coverage thresholds: 90% lines, 95% functions, 85% branches ([CI pipeline](https://github.com/iyulab/formulab/actions/workflows/ci.yml))
20
- - **Research-based** — Golden reference tests verified against NIOSH 94-110, AIAG/ASTM E2587, JIPM, ASME B16.5, ISO 22514-2, and more
21
-
22
- ## Verification Status
23
-
24
- | Domain | Functions | Golden Tests | Key References |
25
- |--------|-----------|-------------|----------------|
26
- | Quality | 18 | oee, cpk, controlChart, gageRR | ISO 22400-2, AIAG/ASTM E2587, JIPM, AIAG MSA |
27
- | Metal | 25 | metalWeight | Machinery's Handbook, ASME B36.10/B16.5 |
28
- | Logistics | 17 | cbm | Physical formula |
29
- | Safety | 14 | nioshLifting | NIOSH 94-110, ISO 7730, IEEE 1584, OSHA |
30
- | Chemical | 12 | — | Darcy-Weisbach, Fourier, API 520, ISA |
31
- | Electronics | 11 | — | IPC-2221 |
32
- | Construction | 12 | — | AISC, Timoshenko |
33
- | Automotive | 9 | — | AASHTO, SAE J1772 |
34
- | Energy | 15 | — | NREL PVWatts, ISO 50001 |
35
- | Food | 6 | — | HACCP, ICH Q1A |
36
- | Utility | 16 | — | — |
37
- | Battery | 10 | — | IEEE 1188, IEC 62620, Battery University |
38
- | Environmental | 10 | — | GHG Protocol, IPCC AR6, IEA 2023 |
39
- | Machining | 12 | — | Machinery's Handbook, ASME Y14.5, Sandvik Coromant |
40
-
41
- > Functions with golden reference tests have been verified against authoritative engineering sources.
42
- > See each function's JSDoc for specific references.
43
-
44
- ## Numerical Accuracy & Testing
45
-
46
- ### Floating-Point Handling
47
-
48
- All calculations use a sign-aware `roundTo()` utility with epsilon correction to avoid IEEE 754 rounding artifacts:
49
-
50
- ```typescript
51
- roundTo(0.615, 2) // → 0.62 (not 0.61)
52
- roundTo(-2.555, 2) // → -2.56 (sign-aware)
53
- ```
54
-
55
- Non-finite values (`NaN`, `Infinity`) pass through unchanged. All validation errors throw `RangeError` — no function returns NaN or Infinity for invalid inputs. Each function's JSDoc specifies output precision (typically 2-4 decimal places) and `@throws` conditions.
56
-
57
- ### Golden Reference Tests
58
-
59
- The following functions include tests verified against published reference values:
60
-
61
- | Function | Standard / Source | What is verified |
62
- |----------|-------------------|------------------|
63
- | `nioshLifting()` | NIOSH Publication 94-110 | LC=23kg ideal, FM/CM table values, RWL calculation |
64
- | `oee()` | JIPM TPM Handbook | World-class OEE (A≥90%, P≥95%, Q≥99.9%), perfect 100% |
65
- | `cpk()` | ISO 22514-2 | Six Sigma Cpk=2.0, minimum capable Cpk≈1.33, off-center penalty |
66
- | `controlChart()` | AIAG/ASTM E2587-16 | A2, D3, D4, d2 constants for n=2, 3, 5 |
67
- | `cbm()` | Physical formula | 20ft container 33.2m³, 1m³ cube reference |
68
- | `metalWeight()` | Machinery's Handbook | Steel plate density 7.85 g/cm³ |
69
- | `flangeSpec()` | ASME B16.5 | Class 150/300/600 flange dimensions |
70
- | `pipeSpec()` | ASME B36.10 | SCH40/80/160 wall thickness |
71
- | `awgProperties()` | ANSI/AWG | AWG 0-40 diameter, resistance |
72
-
73
- ### Edge Case Handling
74
-
75
- Functions validate or handle these boundary conditions:
76
-
77
- - **Division by zero**: `cpk()` with zero standard deviation, `oee()` with zero planned time
78
- - **Out-of-range inputs**: `tolerance()` rejects invalid IT grades, `aql()` validates lot sizes
79
- - **Physical impossibility**: `pressFit()` rejects negative interference, `nioshLifting()` clamps multipliers to [0, 1]
80
- - **Extreme values**: `aql()` handles 1M-unit lots, `awgProperties()` covers AWG 0-40
81
-
82
- ### Optimization Functions — Algorithms & Limitations
83
-
84
- Three functions solve NP-hard combinatorial problems using **heuristic** algorithms. They provide good practical results but **do not guarantee optimal solutions**:
85
-
86
- | Function | Algorithm | Complexity | Optimality |
87
- |----------|-----------|-----------|-----------|
88
- | `tsp()` | Nearest Neighbor + 2-Opt local search; brute force for n ≤ 10 | O(n²) per NN start, O(n!) exact for n ≤ 10 | **Heuristic** — no approximation ratio guarantee; exact only for n ≤ 10 |
89
- | `pallet3d()` | Bottom-Left-Fill + First Fit Decreasing with AABB collision & stability checks | O(m² × n) where m = placed boxes | **Heuristic** — greedy placement; enforces physical constraints (80% support, weight limit) |
90
- | `cuttingStock()` | First Fit Decreasing (FFD) or Best Fit Decreasing (BFD), user-selectable | O(q²) worst case | **FFD: ≤ 11/9 × OPT + 1** (proven bound); not optimal |
91
-
92
- > For mission-critical optimization requiring proven-optimal solutions, use dedicated solvers (e.g., OR-Tools, Gurobi). These functions are designed for quick shop-floor estimates.
93
-
94
- ### CI Pipeline
95
-
96
- GitHub Actions runs on every push to `main` and every pull request:
97
-
98
- - **Matrix**: Node.js 18, 20
99
- - **Steps**: `pnpm install` → `tsc` (type check) → `vitest run --coverage`
100
- - **Coverage enforcement**: Fails if below thresholds (lines 90%, functions 95%, branches 85%, statements 90%)
101
-
102
- ```bash
103
- # Run tests locally
104
- pnpm test
105
-
106
- # Run with coverage report
107
- pnpm test:coverage
108
- ```
109
-
110
- ## Installation
111
-
112
- ```bash
113
- npm install formulab
114
- ```
115
-
116
- ```bash
117
- pnpm add formulab
118
- ```
119
-
120
- ## Quick Start
121
-
122
- ```typescript
123
- import { oee, metalWeight, cbm } from 'formulab';
124
-
125
- // Calculate OEE (Overall Equipment Effectiveness)
126
- const result = oee({
127
- rawData: {
128
- plannedTime: 480, // minutes (8 hours)
129
- runTime: 432, // minutes (90% availability)
130
- totalCount: 1000,
131
- goodCount: 990, // 99% quality
132
- idealCycleTime: 0.456, // minutes per piece (95% performance)
133
- },
134
- });
135
- console.log(result.percentages.oee); // 84.6%
136
-
137
- // Calculate metal weight
138
- const weight = metalWeight({
139
- shape: 'plate',
140
- materialName: 'steel',
141
- length: 1000, // mm
142
- width: 500, // mm
143
- thickness: 10, // mm
144
- });
145
- console.log(weight.weight); // 39.25 kg
146
-
147
- // Calculate CBM (Cubic Meter)
148
- const volume = cbm({
149
- length: 120,
150
- width: 80,
151
- height: 100,
152
- quantity: 1,
153
- unit: 'cm',
154
- });
155
- console.log(volume.totalCbm); // 0.96 m³
156
- ```
157
-
158
- ## Domains
159
-
160
- ### Quality & Production (18 functions)
161
-
162
- ```typescript
163
- import { oee, cpk, taktTime, dpmo, controlChart, gageRR, weibull } from 'formulab/quality';
164
- ```
165
-
166
- | Function | Description |
167
- |----------|-------------|
168
- | `oee()` | Overall Equipment Effectiveness |
169
- | `cpk()` | Process Capability Index |
170
- | `controlChart()` | SPC X-bar/R and X-bar/S charts |
171
- | `cycleTime()` | Cycle Time analysis |
172
- | `taktTime()` | Takt Time calculation |
173
- | `aql()` | AQL sampling inspection |
174
- | `downtime()` | Downtime analysis |
175
- | `dpmo()` | Defects Per Million Opportunities |
176
- | `lineBalancing()` | Line balancing optimization |
177
- | `mtbf()` | Mean Time Between Failures |
178
- | `ppk()` | Process Performance Index |
179
- | `ppm()` | Parts Per Million conversion |
180
- | `rpn()` | Risk Priority Number (FMEA) |
181
- | `yieldCalc()` | First Pass Yield / RTY |
182
- | `gageRR()` | Gage R&R (AIAG MSA Average & Range) |
183
- | `cmk()` | Machine capability index Cm/Cmk |
184
- | `weibull()` | Weibull reliability analysis |
185
- | `paretoAnalysis()` | Pareto 80/20 ABC classification |
186
-
187
- ### Metal & Machining (25 functions)
188
-
189
- ```typescript
190
- import { metalWeight, bendAllowance, cutting, bearing } from 'formulab/metal';
191
- ```
192
-
193
- | Function | Description |
194
- |----------|-------------|
195
- | `metalWeight()` | Weight calculation for various shapes |
196
- | `bendAllowance()` | Sheet metal bend allowance |
197
- | `flatPattern()` | Flat pattern length calculation |
198
- | `kFactorReverse()` | K-factor reverse engineering |
199
- | `pressTonnage()` | Press brake tonnage |
200
- | `bearing()` | L10 bearing life calculation |
201
- | `bolt()` | Bolt torque and preload |
202
- | `cutting()` | Cutting speed, feed rate, RPM |
203
- | `cuttingStock()` | 1D cutting stock heuristic (FFD/BFD) |
204
- | `gear()` | Gear module calculation |
205
- | `hardness()` | Hardness conversion (HRC, HB, HV) |
206
- | `material()` | Material properties lookup |
207
- | `pressFit()` | Press fit interference |
208
- | `roughness()` | Surface roughness conversion |
209
- | `screw()` | Screw specification |
210
- | `spring()` | Spring design calculation |
211
- | `tap()` | Tap drill size |
212
- | `thread()` | Thread dimensions |
213
- | `tolerance()` | ISO tolerance (IT grades) |
214
- | `vibration()` | Natural frequency analysis |
215
- | `weldHeat()` | Weld heat input calculation |
216
- | `welding()` | Welding parameters |
217
- | `materialGradeConverter()` | ASTM/EN/JIS/GB/KS grade cross-reference |
218
- | `pipeSpec()` | ANSI/ASME pipe dimensions lookup |
219
- | `flangeSpec()` | ASME B16.5 flange dimensions lookup |
220
-
221
- ### Chemical & Process (12 functions)
222
-
223
- ```typescript
224
- import { dilution, concentration, ph, reactor, pipeFlow, heatTransfer, flowControl, pid } from 'formulab/chemical';
225
- ```
226
-
227
- | Function | Description |
228
- |----------|-------------|
229
- | `batch()` | Batch scaling calculation |
230
- | `concentration()` | Concentration conversion |
231
- | `dilution()` | Dilution (C1V1 = C2V2) |
232
- | `heatTransfer()` | Conduction/convection/radiation heat transfer |
233
- | `ph()` | pH and buffer calculations |
234
- | `pipeFlow()` | Darcy-Weisbach pipe flow pressure drop |
235
- | `reactor()` | Reactor sizing |
236
- | `shelfLife()` | Shelf life prediction (Arrhenius) |
237
- | `injectionCycle()` | Injection molding cycle time |
238
- | `flowControl()` | Control valve Cv/Kv sizing (ISA/IEC 60534) |
239
- | `reliefValve()` | Safety relief valve sizing (API 520/526) |
240
- | `pid()` | PID controller tuning (Z-N / Cohen-Coon) |
241
-
242
- ### Electronics & SMT (11 functions)
243
-
244
- ```typescript
245
- import { traceWidth, solderPaste, resistorDecode, ohmsLaw } from 'formulab/electronics';
246
- ```
247
-
248
- | Function | Description |
249
- |----------|-------------|
250
- | `ohmsLaw()` | Ohm's Law V/I/R/P calculator |
251
- | `reflowProfile()` | Reflow temperature profile |
252
- | `resistorDecode()` | Resistor color code decoder |
253
- | `smtTakt()` | SMT line takt time |
254
- | `solderPaste()` | Solder paste volume calculation |
255
- | `traceWidth()` | PCB trace width (IPC-2221) |
256
- | `awgProperties()` | AWG wire properties |
257
- | `capacitorDecode()` | Capacitor code decoder |
258
- | `ledResistor()` | LED resistor calculation |
259
- | `stencilAperture()` | Stencil aperture design |
260
- | `viaCurrent()` | Via current capacity |
261
-
262
- ### Construction (12 functions)
263
-
264
- ```typescript
265
- import { concreteMix, rebarWeight, slope, stair, momentOfInertia } from 'formulab/construction';
266
- ```
267
-
268
- | Function | Description |
269
- |----------|-------------|
270
- | `momentOfInertia()` | Section properties (Ix, Sx, rx) for 7 shapes |
271
- | `beamLoad()` | Beam load calculation |
272
- | `concreteMix()` | Concrete mix ratio |
273
- | `earthwork()` | Earthwork volume |
274
- | `formwork()` | Formwork area calculation |
275
- | `rebarWeight()` | Rebar weight by size |
276
- | `slope()` | Slope conversion (%, degree, ratio) |
277
- | `aggregate()` | Aggregate volume calculation |
278
- | `brick()` | Brick quantity estimation |
279
- | `pert()` | PERT schedule analysis |
280
- | `roof()` | Roof calculation |
281
- | `stair()` | Stair dimension calculation |
282
-
283
- ### Automotive (9 functions)
284
-
285
- ```typescript
286
- import { batteryRuntime, evCharging, torque, brakingDistance, chargingLoss } from 'formulab/automotive';
287
- ```
288
-
289
- | Function | Description |
290
- |----------|-------------|
291
- | `brakingDistance()` | Stopping distance (AASHTO method) |
292
- | `batteryRuntime()` | Battery capacity/runtime |
293
- | `evCharging()` | EV charging time estimation |
294
- | `fuelEconomy()` | Fuel economy conversion |
295
- | `gearRatio()` | Gear ratio calculation |
296
- | `tireCompare()` | Tire size comparison |
297
- | `torque()` | Torque conversion |
298
- | `power()` | Power conversion (HP, kW) |
299
- | `chargingLoss()` | EV charging loss/efficiency |
300
-
301
- ### Logistics & Inventory (17 functions)
302
-
303
- ```typescript
304
- import { cbm, eoq, safetyStock, kanban, inventoryTurnover, abcAnalysis } from 'formulab/logistics';
305
- ```
306
-
307
- | Function | Description |
308
- |----------|-------------|
309
- | `abcAnalysis()` | ABC inventory classification by annual value |
310
- | `cbm()` | Cubic meter calculation |
311
- | `containerFit()` | Container capacity estimation |
312
- | `dimWeight()` | Dimensional weight |
313
- | `eoq()` | Economic Order Quantity |
314
- | `fillRate()` | Fill rate calculation |
315
- | `freightClass()` | NMFC freight class |
316
- | `inventoryTurnover()` | Inventory turnover ratio & days of supply |
317
- | `kanban()` | Kanban quantity |
318
- | `loadCapacity()` | Forklift load capacity derating |
319
- | `pallet3d()` | 3D pallet loading heuristic (BLF + FFD) |
320
- | `palletStack()` | Pallet stacking calculation |
321
- | `pickTime()` | Picking time estimation |
322
- | `safetyStock()` | Safety stock calculation |
323
- | `serviceLevel()` | Service level calculation |
324
- | `shipping()` | Shipping cost estimation |
325
- | `tsp()` | TSP heuristic (NN + 2-Opt; exact for n ≤ 10) |
326
-
327
- ### Energy & Utilities (15 functions)
328
-
329
- ```typescript
330
- import { powerCost, motorEfficiency, carbonFootprint, solarOutput, boilerEfficiency, heatPump, cusum } from 'formulab/energy';
331
- ```
332
-
333
- | Function | Description |
334
- |----------|-------------|
335
- | `boilerEfficiency()` | Boiler thermal efficiency (direct method) |
336
- | `carbonFootprint()` | Scope 2 emissions |
337
- | `compressedAirCost()` | Compressed air cost |
338
- | `cusum()` | CUSUM energy anomaly detection |
339
- | `degreeDay()` | Heating/Cooling degree days (HDD/CDD) |
340
- | `heatPump()` | Heat pump COP & Carnot efficiency |
341
- | `insulationRoi()` | Insulation ROI & payback |
342
- | `ledRoi()` | LED lighting retrofit ROI |
343
- | `motorEfficiency()` | Motor upgrade ROI |
344
- | `pfCorrection()` | Power factor correction |
345
- | `powerCost()` | Electricity cost with demand |
346
- | `solarOutput()` | Solar panel output estimation (PVWatts-based) |
347
- | `transformerLoss()` | Transformer loss & efficiency |
348
- | `vfdSavings()` | VFD energy savings |
349
- | `windOutput()` | Wind turbine output with Rayleigh CF |
350
-
351
- ### Safety & Ergonomics (14 functions)
352
-
353
- ```typescript
354
- import { nioshLifting, noiseExposure, wbgtCalculate, ventilationRate, thermalComfort, arcFlash, lel } from 'formulab/safety';
355
- ```
356
-
357
- | Function | Description |
358
- |----------|-------------|
359
- | `arcFlash()` | Arc flash incident energy & PPE (IEEE 1584) |
360
- | `confinedSpace()` | Confined space atmospheric assessment (OSHA) |
361
- | `ergonomicRisk()` | REBA ergonomic risk scoring |
362
- | `fallClearance()` | Fall protection clearance |
363
- | `havsCalculate()` | Hand-arm vibration exposure |
364
- | `illuminance()` | Workplace illuminance (Lumen Method) |
365
- | `ladderAngle()` | Ladder safety angle (OSHA 4:1) |
366
- | `lel()` | Mixed gas LEL (Le Chatelier's rule) |
367
- | `nioshLifting()` | NIOSH lifting equation |
368
- | `noiseExposure()` | TWA/Dose calculation |
369
- | `respiratorCalculate()` | Respirator MUC calculation |
370
- | `thermalComfort()` | PMV/PPD thermal comfort (ISO 7730) |
371
- | `ventilationRate()` | Required ventilation ACH/CFM (ASHRAE/OSHA) |
372
- | `wbgtCalculate()` | WBGT heat stress index |
373
-
374
- ### Food & HACCP (6 functions)
375
-
376
- ```typescript
377
- import { calorie, nutrition, haccp, waterActivity, stabilityStudy } from 'formulab/food';
378
- ```
379
-
380
- | Function | Description |
381
- |----------|-------------|
382
- | `calorie()` | Calorie requirement (BMR/TDEE) |
383
- | `expiry()` | Expiry date calculation |
384
- | `nutrition()` | Nutrition facts calculation |
385
- | `haccp()` | HACCP checklist generation |
386
- | `waterActivity()` | Water activity microbial risk (HACCP) |
387
- | `stabilityStudy()` | Accelerated stability (Arrhenius, ICH Q1A) |
388
-
389
- ### Utility (16 functions)
390
-
391
- ```typescript
392
- import { solveAssignment, calculateUnit, statistics, regression, npv } from 'formulab/utility';
393
- ```
394
-
395
- | Function | Description |
396
- |----------|-------------|
397
- | `solveAssignment()` | Hungarian algorithm optimization |
398
- | `calculateUnit()` | Unit conversion (7 categories) |
399
- | `getUnitCategories()` | Get unit categories |
400
- | `statistics()` | Descriptive statistics (mean, median, stdDev, etc.) |
401
- | `percentile()` | Percentile/quantile calculation |
402
- | `correlation()` | Pearson correlation coefficient |
403
- | `regression()` | Simple linear regression |
404
- | `movingAverage()` | SMA/EMA/WMA moving average |
405
- | `linearInterpolation()` | 1D linear interpolation |
406
- | `bilinearInterpolation()` | 2D bilinear interpolation |
407
- | `roi()` | Return on Investment |
408
- | `npv()` | Net Present Value |
409
- | `depreciation()` | Asset depreciation (SL/DDB/SYD) |
410
- | `lcc()` | Life Cycle Cost analysis |
411
- | `normalize()` | Data normalization (min-max/z-score) |
412
- | `histogram()` | Frequency distribution histogram |
413
- | `weightedScore()` | Weighted scoring model |
414
-
415
- ### Battery (10 functions)
416
-
417
- ```typescript
418
- import { energyDensity, cRate, stateOfHealth, cycleLife } from 'formulab/battery';
419
- ```
420
-
421
- | Function | Description |
422
- |----------|-------------|
423
- | `energyDensity()` | Wh/kg and Wh/L energy density |
424
- | `cRate()` | C-rate ↔ current/time conversion |
425
- | `stateOfHealth()` | SOH % with degradation status |
426
- | `batteryPackConfig()` | Series/parallel cell configuration |
427
- | `cycleLife()` | Cycle life estimation (chemistry/DOD/temp) |
428
- | `internalResistance()` | DCIR from OCV and load voltage |
429
- | `selfDischarge()` | Self-discharge rate calculation |
430
- | `thermalRunaway()` | Thermal safety margin analysis |
431
- | `bmsBalancing()` | BMS cell balancing time estimation |
432
- | `chargingProfile()` | CC-CV charging profile timing |
433
-
434
- ### Environmental (10 functions)
435
-
436
- ```typescript
437
- import { scope1Emissions, scope2Emissions, gwpCalculator, esgSummary } from 'formulab/environmental';
438
- ```
439
-
440
- | Function | Description |
441
- |----------|-------------|
442
- | `scope1Emissions()` | Fuel combustion direct emissions (6 fuels) |
443
- | `scope2Emissions()` | Purchased electricity emissions (12 regions) |
444
- | `scope3Emissions()` | Supply chain spend-based emissions (8 categories) |
445
- | `vocEmissions()` | VOC emissions with capture/destruction |
446
- | `productCarbonFootprint()` | Product lifecycle carbon footprint |
447
- | `gwpCalculator()` | GWP conversion (8 gases × 3 time horizons) |
448
- | `energyIntensity()` | Energy intensity (MJ/unit, kWh/unit) |
449
- | `waterFootprint()` | Water footprint (blue/green/grey) |
450
- | `emissionsIntensity()` | Emissions intensity per unit/revenue/employee |
451
- | `esgSummary()` | ESG reduction tracking and projections |
452
-
453
- ### Machining & CNC (12 functions)
454
-
455
- ```typescript
456
- import { truePosition, boltCircle, toolDeflection, threadOverWires } from 'formulab/machining';
457
- ```
458
-
459
- | Function | Description |
460
- |----------|-------------|
461
- | `truePosition()` | GD&T True Position (diametral, MMC bonus) |
462
- | `boltCircle()` | Bolt hole pattern coordinates |
463
- | `sineBarHeight()` | Sine bar gauge block height |
464
- | `radialChipThinning()` | Chip load compensation for light radial cuts |
465
- | `toolDeflection()` | End mill cantilever deflection |
466
- | `cuspHeight()` | Ball mill scallop height |
467
- | `effectiveDiameter()` | Ball mill effective cutting diameter |
468
- | `boringBarDeflection()` | Boring bar deflection with L/D guidance |
469
- | `threadOverWires()` | 3-wire thread measurement |
470
- | `gaugeBlockStack()` | Gauge block combination (47/88/81-pc sets) |
471
- | `triangleSolver()` | Triangle solver (SSS/SAS/ASA/SSA) |
472
- | `cycleTimeEstimator()` | CNC cycle time estimation |
473
-
474
- ## API Examples
475
-
476
- ### OEE Calculation
477
-
478
- ```typescript
479
- import { oee } from 'formulab/quality';
480
-
481
- const result = oee({
482
- rawData: {
483
- plannedTime: 480, // minutes
484
- runTime: 420, // actual running time
485
- totalCount: 1000, // total pieces produced
486
- goodCount: 990, // good pieces
487
- idealCycleTime: 0.4, // minutes per piece
488
- },
489
- });
490
-
491
- console.log(result);
492
- // {
493
- // factors: { availability: 0.875, performance: 0.952, quality: 0.99, oee: 0.825 },
494
- // percentages: { availability: 87.5, performance: 95.2, quality: 99, oee: 82.5 }
495
- // }
496
- ```
497
-
498
- ### NIOSH Lifting Equation
499
-
500
- ```typescript
501
- import { nioshLifting } from 'formulab/safety';
502
-
503
- const result = nioshLifting({
504
- loadWeight: 23, // kg
505
- horizontalDistance: 25, // cm
506
- verticalDistance: 75, // cm (height at lift origin)
507
- verticalTravel: 25, // cm (vertical travel distance)
508
- asymmetryAngle: 0, // degrees
509
- coupling: 'good', // 'good' | 'fair' | 'poor'
510
- frequency: 1, // lifts per minute
511
- duration: 'short', // 'short' | 'medium' | 'long'
512
- });
513
-
514
- console.log(result);
515
- // {
516
- // rwl: 21.62, // Recommended Weight Limit (kg)
517
- // liftingIndex: 1.06, // LI = Load / RWL
518
- // riskLevel: 'moderate',
519
- // hm: 1.0, vm: 1.0, dm: 1.0, am: 1.0, fm: 0.94, cm: 1.0
520
- // }
521
- ```
522
-
523
- ### Dimensional Weight
524
-
525
- ```typescript
526
- import { dimWeight } from 'formulab/logistics';
527
-
528
- const result = dimWeight({
529
- length: 60,
530
- width: 40,
531
- height: 30,
532
- unit: 'cm',
533
- carrier: 'international',
534
- });
535
-
536
- console.log(result);
537
- // {
538
- // dimWeight: 14.4,
539
- // actualVolume: 0.072,
540
- // cbm: 0.072,
541
- // }
542
- ```
543
-
544
- ## Type Guards for Discriminated Unions
545
-
546
- formulab provides runtime type guard functions for all [discriminated union](https://www.typescriptlang.org/docs/handbook/2/narrowing.html#discriminated-unions) input types. These enable type-safe integration when working with dynamic data (e.g., form inputs, API responses):
547
-
548
- ```typescript
549
- import { isCRateInput, cRate } from 'formulab/battery';
550
-
551
- // Form data from user input (Record<string, unknown>)
552
- const formData: unknown = { mode: 'currentToRate', capacityAh: 100, currentA: 50 };
553
-
554
- if (isCRateInput(formData)) {
555
- const result = cRate(formData); // Type-safe, no 'as any' needed
556
- }
557
- ```
558
-
559
- ### Available Type Guards
560
-
561
- | Guard | Domain | Discriminant | Variants |
562
- |-------|--------|-------------|----------|
563
- | `isCRateInput()` | battery | `mode` | currentToRate, rateToCurrent |
564
- | `isDilutionInput()` | chemical | `solveFor` | c1, v1, c2, v2 |
565
- | `isReactorInput()` | chemical | `shape` | cylindrical, spherical |
566
- | `isHeatTransferInput()` | chemical | `mode` | conduction, convection, radiation |
567
- | `isMomentOfInertiaInput()` | construction | `shape` | rectangle, circle, hollowRectangle, hollowCircle, iBeam, tSection, cChannel |
568
- | `isOhmsLawInput()` | electronics | `solveFor` | voltage, current, resistance, power |
569
- | `isMetalWeightInput()` | metal | `shape` | plate, round, pipe, angle |
570
- | `isBoltInput()` | metal | `mode` | torqueToPreload, preloadToTorque |
571
-
572
- ## Error Handling
573
-
574
- See [ERRORS.md](./ERRORS.md) for the complete error behavior specification. Key points:
575
-
576
- - **All validation failures** throw `RangeError` with descriptive messages
577
- - **No silent NaN/Infinity** — every function guarantees finite outputs for valid inputs
578
- - Every `@throws` condition is documented in each function's JSDoc
579
-
580
- ```typescript
581
- import { metalWeight } from 'formulab/metal';
582
-
583
- try {
584
- const result = metalWeight({ shape: 'plate', materialName: 'steel', length: 0, width: 100, thickness: 10 });
585
- } catch (e) {
586
- if (e instanceof RangeError) {
587
- console.log(e.message); // "length must be positive"
588
- }
589
- }
590
- ```
591
-
592
- ## Tree Shaking
593
-
594
- Import only what you need to minimize bundle size:
595
-
596
- ```typescript
597
- // Recommended - domain-specific import
598
- import { oee } from 'formulab/quality';
599
- import { metalWeight } from 'formulab/metal';
600
-
601
- // Also works - main entry point (tree-shakeable)
602
- import { oee, metalWeight } from 'formulab';
603
-
604
- // Avoid - imports entire module
605
- import * as formulab from 'formulab';
606
- ```
607
-
608
- ## TypeScript Support
609
-
610
- Full TypeScript support with detailed type definitions:
611
-
612
- ```typescript
613
- import type {
614
- OeeInput,
615
- OeeResult,
616
- CpkInput,
617
- CpkResult,
618
- MetalWeightInput,
619
- MetalWeightResult,
620
- } from 'formulab';
621
- ```
622
-
623
- ## Browser Support
624
-
625
- formulab works in all modern browsers and Node.js:
626
-
627
- - Node.js 18+
628
- - Chrome 80+
629
- - Firefox 75+
630
- - Safari 13+
631
- - Edge 80+
632
-
633
- ## Contributing
634
-
635
- Contributions are welcome! Please see our [GitHub repository](https://github.com/iyulab/formulab).
636
-
637
- ```bash
638
- # Clone the repository
639
- git clone https://github.com/iyulab/formulab.git
640
-
641
- # Install dependencies
642
- pnpm install
643
-
644
- # Run tests
645
- pnpm test
646
-
647
- # Build
648
- pnpm build
649
- ```
650
-
651
- ## License
652
-
653
- MIT © [iyulab](https://github.com/iyulab)
654
-
655
- ---
656
-
657
- <p align="center">
658
- Made with engineering precision by <a href="https://github.com/iyulab">iyulab</a>
659
- </p>
1
+ # formulab
2
+
3
+ > Industrial & manufacturing calculation library for engineers
4
+
5
+ [![npm version](https://img.shields.io/npm/v/formulab.svg)](https://www.npmjs.com/package/formulab)
6
+ [![CI](https://github.com/iyulab/formulab/actions/workflows/ci.yml/badge.svg)](https://github.com/iyulab/formulab/actions/workflows/ci.yml)
7
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
8
+ [![TypeScript](https://img.shields.io/badge/TypeScript-Ready-blue.svg)](https://www.typescriptlang.org/)
9
+
10
+ A comprehensive collection of engineering formulas and calculations for manufacturing, quality control, logistics, and industrial applications. Zero dependencies, fully typed, tree-shakeable.
11
+
12
+ ## Features
13
+
14
+ - **174 industrial calculations + 8 type guards** — OEE, Cpk, SPC control charts, Gage R&R, Weibull, metal weight, CNC machining, GD&T, pipe flow, CBM, NIOSH lifting, PMV/PPD, arc flash, battery SOH, GHG emissions, PID tuning, and more
15
+ - **14 specialized domains** — Quality, Metal, Chemical, Electronics, Construction, Automotive, Logistics, Energy, Safety, Food, Utility, Battery, Environmental, Machining
16
+ - **Zero dependencies** — Lightweight and fast
17
+ - **TypeScript first** — Full type definitions included
18
+ - **Tree-shakeable** — Import only what you need
19
+ - **2,494 tests** — Coverage thresholds: 90% lines, 95% functions, 85% branches ([CI pipeline](https://github.com/iyulab/formulab/actions/workflows/ci.yml))
20
+ - **Research-based** — Golden reference tests verified against NIOSH 94-110, AIAG/ASTM E2587, JIPM, ASME B16.5, ISO 22514-2, and more
21
+
22
+ ## Verification Status
23
+
24
+ | Domain | Functions | Golden Tests | Key References |
25
+ |--------|-----------|-------------|----------------|
26
+ | Quality | 18 | oee, cpk, controlChart, gageRR | ISO 22400-2, AIAG/ASTM E2587, JIPM, AIAG MSA |
27
+ | Metal | 25 | metalWeight | Machinery's Handbook, ASME B36.10/B16.5 |
28
+ | Logistics | 17 | cbm | Physical formula |
29
+ | Safety | 14 | nioshLifting | NIOSH 94-110, ISO 7730, IEEE 1584, OSHA |
30
+ | Chemical | 12 | — | Darcy-Weisbach, Fourier, API 520, ISA |
31
+ | Electronics | 11 | — | IPC-2221 |
32
+ | Construction | 12 | — | AISC, Timoshenko |
33
+ | Automotive | 9 | — | AASHTO, SAE J1772 |
34
+ | Energy | 15 | — | NREL PVWatts, ISO 50001 |
35
+ | Food | 6 | — | HACCP, ICH Q1A |
36
+ | Utility | 16 | — | — |
37
+ | Battery | 10 | — | IEEE 1188, IEC 62620, Battery University |
38
+ | Environmental | 10 | — | GHG Protocol, IPCC AR6, IEA 2023 |
39
+ | Machining | 12 | — | Machinery's Handbook, ASME Y14.5, Sandvik Coromant |
40
+
41
+ > Functions with golden reference tests have been verified against authoritative engineering sources.
42
+ > See each function's JSDoc for specific references.
43
+
44
+ ## Numerical Accuracy & Testing
45
+
46
+ ### Floating-Point Handling
47
+
48
+ All calculations use a sign-aware `roundTo()` utility with epsilon correction to avoid IEEE 754 rounding artifacts:
49
+
50
+ ```typescript
51
+ roundTo(0.615, 2) // → 0.62 (not 0.61)
52
+ roundTo(-2.555, 2) // → -2.56 (sign-aware)
53
+ ```
54
+
55
+ Non-finite values (`NaN`, `Infinity`) pass through unchanged. All validation errors throw `RangeError` — no function returns NaN or Infinity for invalid inputs. Each function's JSDoc specifies output precision (typically 2-4 decimal places) and `@throws` conditions.
56
+
57
+ ### Golden Reference Tests
58
+
59
+ The following functions include tests verified against published reference values:
60
+
61
+ | Function | Standard / Source | What is verified |
62
+ |----------|-------------------|------------------|
63
+ | `nioshLifting()` | NIOSH Publication 94-110 | LC=23kg ideal, FM/CM table values, RWL calculation |
64
+ | `oee()` | JIPM TPM Handbook | World-class OEE (A≥90%, P≥95%, Q≥99.9%), perfect 100% |
65
+ | `cpk()` | ISO 22514-2 | Six Sigma Cpk=2.0, minimum capable Cpk≈1.33, off-center penalty |
66
+ | `controlChart()` | AIAG/ASTM E2587-16 | A2, D3, D4, d2 constants for n=2, 3, 5 |
67
+ | `cbm()` | Physical formula | 20ft container 33.2m³, 1m³ cube reference |
68
+ | `metalWeight()` | Machinery's Handbook | Steel plate density 7.85 g/cm³ |
69
+ | `flangeSpec()` | ASME B16.5 | Class 150/300/600 flange dimensions |
70
+ | `pipeSpec()` | ASME B36.10 | SCH40/80/160 wall thickness |
71
+ | `awgProperties()` | ANSI/AWG | AWG 0-40 diameter, resistance |
72
+
73
+ ### Edge Case Handling
74
+
75
+ Functions validate or handle these boundary conditions:
76
+
77
+ - **Division by zero**: `cpk()` with zero standard deviation, `oee()` with zero planned time
78
+ - **Out-of-range inputs**: `tolerance()` rejects invalid IT grades, `aql()` validates lot sizes
79
+ - **Physical impossibility**: `pressFit()` rejects negative interference, `nioshLifting()` clamps multipliers to [0, 1]
80
+ - **Extreme values**: `aql()` handles 1M-unit lots, `awgProperties()` covers AWG 0-40
81
+
82
+ ### Optimization Functions — Algorithms & Limitations
83
+
84
+ Three functions solve NP-hard combinatorial problems using **heuristic** algorithms. They provide good practical results but **do not guarantee optimal solutions**:
85
+
86
+ | Function | Algorithm | Complexity | Optimality |
87
+ |----------|-----------|-----------|-----------|
88
+ | `tsp()` | Nearest Neighbor + 2-Opt local search; brute force for n ≤ 10 | O(n²) per NN start, O(n!) exact for n ≤ 10 | **Heuristic** — no approximation ratio guarantee; exact only for n ≤ 10 |
89
+ | `pallet3d()` | Bottom-Left-Fill + First Fit Decreasing with AABB collision & stability checks | O(m² × n) where m = placed boxes | **Heuristic** — greedy placement; enforces physical constraints (80% support, weight limit) |
90
+ | `cuttingStock()` | First Fit Decreasing (FFD) or Best Fit Decreasing (BFD), user-selectable | O(q²) worst case | **FFD: ≤ 11/9 × OPT + 1** (proven bound); not optimal |
91
+
92
+ > For mission-critical optimization requiring proven-optimal solutions, use dedicated solvers (e.g., OR-Tools, Gurobi). These functions are designed for quick shop-floor estimates.
93
+
94
+ ### CI Pipeline
95
+
96
+ GitHub Actions runs on every push to `main` and every pull request:
97
+
98
+ - **Matrix**: Node.js 18, 20
99
+ - **Steps**: `pnpm install` → `tsc` (type check) → `vitest run --coverage`
100
+ - **Coverage enforcement**: Fails if below thresholds (lines 90%, functions 95%, branches 85%, statements 90%)
101
+
102
+ ```bash
103
+ # Run tests locally
104
+ pnpm test
105
+
106
+ # Run with coverage report
107
+ pnpm test:coverage
108
+ ```
109
+
110
+ ## Installation
111
+
112
+ ```bash
113
+ npm install formulab
114
+ ```
115
+
116
+ ```bash
117
+ pnpm add formulab
118
+ ```
119
+
120
+ ## Quick Start
121
+
122
+ ```typescript
123
+ import { oee, metalWeight, cbm } from 'formulab';
124
+
125
+ // Calculate OEE (Overall Equipment Effectiveness)
126
+ const result = oee({
127
+ rawData: {
128
+ plannedTime: 480, // minutes (8 hours)
129
+ runTime: 432, // minutes (90% availability)
130
+ totalCount: 1000,
131
+ goodCount: 990, // 99% quality
132
+ idealCycleTime: 0.456, // minutes per piece (95% performance)
133
+ },
134
+ });
135
+ console.log(result.percentages.oee); // 84.6%
136
+
137
+ // Calculate metal weight
138
+ const weight = metalWeight({
139
+ shape: 'plate',
140
+ materialName: 'steel',
141
+ length: 1000, // mm
142
+ width: 500, // mm
143
+ thickness: 10, // mm
144
+ });
145
+ console.log(weight.weight); // 39.25 kg
146
+
147
+ // Calculate CBM (Cubic Meter)
148
+ const volume = cbm({
149
+ length: 120,
150
+ width: 80,
151
+ height: 100,
152
+ quantity: 1,
153
+ unit: 'cm',
154
+ });
155
+ console.log(volume.totalCbm); // 0.96 m³
156
+ ```
157
+
158
+ ## Domains
159
+
160
+ ### Quality & Production (18 functions)
161
+
162
+ ```typescript
163
+ import { oee, cpk, taktTime, dpmo, controlChart, gageRR, weibull } from 'formulab/quality';
164
+ ```
165
+
166
+ | Function | Description |
167
+ |----------|-------------|
168
+ | `oee()` | Overall Equipment Effectiveness |
169
+ | `cpk()` | Process Capability Index |
170
+ | `controlChart()` | SPC X-bar/R and X-bar/S charts |
171
+ | `cycleTime()` | Cycle Time analysis |
172
+ | `taktTime()` | Takt Time calculation |
173
+ | `aql()` | AQL sampling inspection |
174
+ | `downtime()` | Downtime analysis |
175
+ | `dpmo()` | Defects Per Million Opportunities |
176
+ | `lineBalancing()` | Line balancing optimization |
177
+ | `mtbf()` | Mean Time Between Failures |
178
+ | `ppk()` | Process Performance Index |
179
+ | `ppm()` | Parts Per Million conversion |
180
+ | `rpn()` | Risk Priority Number (FMEA) |
181
+ | `yieldCalc()` | First Pass Yield / RTY |
182
+ | `gageRR()` | Gage R&R (AIAG MSA Average & Range) |
183
+ | `cmk()` | Machine capability index Cm/Cmk |
184
+ | `weibull()` | Weibull reliability analysis |
185
+ | `paretoAnalysis()` | Pareto 80/20 ABC classification |
186
+
187
+ ### Metal & Machining (25 functions)
188
+
189
+ ```typescript
190
+ import { metalWeight, bendAllowance, cutting, bearing } from 'formulab/metal';
191
+ ```
192
+
193
+ | Function | Description |
194
+ |----------|-------------|
195
+ | `metalWeight()` | Weight calculation for various shapes |
196
+ | `bendAllowance()` | Sheet metal bend allowance |
197
+ | `flatPattern()` | Flat pattern length calculation |
198
+ | `kFactorReverse()` | K-factor reverse engineering |
199
+ | `pressTonnage()` | Press brake tonnage |
200
+ | `bearing()` | L10 bearing life calculation |
201
+ | `bolt()` | Bolt torque and preload |
202
+ | `cutting()` | Cutting speed, feed rate, RPM |
203
+ | `cuttingStock()` | 1D cutting stock heuristic (FFD/BFD) |
204
+ | `gear()` | Gear module calculation |
205
+ | `hardness()` | Hardness conversion (HRC, HB, HV) |
206
+ | `material()` | Material properties lookup |
207
+ | `pressFit()` | Press fit interference |
208
+ | `roughness()` | Surface roughness conversion |
209
+ | `screw()` | Screw specification |
210
+ | `spring()` | Spring design calculation |
211
+ | `tap()` | Tap drill size |
212
+ | `thread()` | Thread dimensions |
213
+ | `tolerance()` | ISO tolerance (IT grades) |
214
+ | `vibration()` | Natural frequency analysis |
215
+ | `weldHeat()` | Weld heat input calculation |
216
+ | `welding()` | Welding parameters |
217
+ | `materialGradeConverter()` | ASTM/EN/JIS/GB/KS grade cross-reference |
218
+ | `pipeSpec()` | ANSI/ASME pipe dimensions lookup |
219
+ | `flangeSpec()` | ASME B16.5 flange dimensions lookup |
220
+
221
+ ### Chemical & Process (12 functions)
222
+
223
+ ```typescript
224
+ import { dilution, concentration, ph, reactor, pipeFlow, heatTransfer, flowControl, pid } from 'formulab/chemical';
225
+ ```
226
+
227
+ | Function | Description |
228
+ |----------|-------------|
229
+ | `batch()` | Batch scaling calculation |
230
+ | `concentration()` | Concentration conversion |
231
+ | `dilution()` | Dilution (C1V1 = C2V2) |
232
+ | `heatTransfer()` | Conduction/convection/radiation heat transfer |
233
+ | `ph()` | pH and buffer calculations |
234
+ | `pipeFlow()` | Darcy-Weisbach pipe flow pressure drop |
235
+ | `reactor()` | Reactor sizing |
236
+ | `shelfLife()` | Shelf life prediction (Arrhenius) |
237
+ | `injectionCycle()` | Injection molding cycle time |
238
+ | `flowControl()` | Control valve Cv/Kv sizing (ISA/IEC 60534) |
239
+ | `reliefValve()` | Safety relief valve sizing (API 520/526) |
240
+ | `pid()` | PID controller tuning (Z-N / Cohen-Coon) |
241
+
242
+ ### Electronics & SMT (11 functions)
243
+
244
+ ```typescript
245
+ import { traceWidth, solderPaste, resistorDecode, ohmsLaw } from 'formulab/electronics';
246
+ ```
247
+
248
+ | Function | Description |
249
+ |----------|-------------|
250
+ | `ohmsLaw()` | Ohm's Law V/I/R/P calculator |
251
+ | `reflowProfile()` | Reflow temperature profile |
252
+ | `resistorDecode()` | Resistor color code decoder |
253
+ | `smtTakt()` | SMT line takt time |
254
+ | `solderPaste()` | Solder paste volume calculation |
255
+ | `traceWidth()` | PCB trace width (IPC-2221) |
256
+ | `awgProperties()` | AWG wire properties |
257
+ | `capacitorDecode()` | Capacitor code decoder |
258
+ | `ledResistor()` | LED resistor calculation |
259
+ | `stencilAperture()` | Stencil aperture design |
260
+ | `viaCurrent()` | Via current capacity |
261
+
262
+ ### Construction (12 functions)
263
+
264
+ ```typescript
265
+ import { concreteMix, rebarWeight, slope, stair, momentOfInertia } from 'formulab/construction';
266
+ ```
267
+
268
+ | Function | Description |
269
+ |----------|-------------|
270
+ | `momentOfInertia()` | Section properties (Ix, Sx, rx) for 7 shapes |
271
+ | `beamLoad()` | Beam load calculation |
272
+ | `concreteMix()` | Concrete mix ratio |
273
+ | `earthwork()` | Earthwork volume |
274
+ | `formwork()` | Formwork area calculation |
275
+ | `rebarWeight()` | Rebar weight by size |
276
+ | `slope()` | Slope conversion (%, degree, ratio) |
277
+ | `aggregate()` | Aggregate volume calculation |
278
+ | `brick()` | Brick quantity estimation |
279
+ | `pert()` | PERT schedule analysis |
280
+ | `roof()` | Roof calculation |
281
+ | `stair()` | Stair dimension calculation |
282
+
283
+ ### Automotive (9 functions)
284
+
285
+ ```typescript
286
+ import { batteryRuntime, evCharging, torque, brakingDistance, chargingLoss } from 'formulab/automotive';
287
+ ```
288
+
289
+ | Function | Description |
290
+ |----------|-------------|
291
+ | `brakingDistance()` | Stopping distance (AASHTO method) |
292
+ | `batteryRuntime()` | Battery capacity/runtime |
293
+ | `evCharging()` | EV charging time estimation |
294
+ | `fuelEconomy()` | Fuel economy conversion |
295
+ | `gearRatio()` | Gear ratio calculation |
296
+ | `tireCompare()` | Tire size comparison |
297
+ | `torque()` | Torque conversion |
298
+ | `power()` | Power conversion (HP, kW) |
299
+ | `chargingLoss()` | EV charging loss/efficiency |
300
+
301
+ ### Logistics & Inventory (17 functions)
302
+
303
+ ```typescript
304
+ import { cbm, eoq, safetyStock, kanban, inventoryTurnover, abcAnalysis } from 'formulab/logistics';
305
+ ```
306
+
307
+ | Function | Description |
308
+ |----------|-------------|
309
+ | `abcAnalysis()` | ABC inventory classification by annual value |
310
+ | `cbm()` | Cubic meter calculation |
311
+ | `containerFit()` | Container capacity estimation |
312
+ | `dimWeight()` | Dimensional weight |
313
+ | `eoq()` | Economic Order Quantity |
314
+ | `fillRate()` | Fill rate calculation |
315
+ | `freightClass()` | NMFC freight class |
316
+ | `inventoryTurnover()` | Inventory turnover ratio & days of supply |
317
+ | `kanban()` | Kanban quantity |
318
+ | `loadCapacity()` | Forklift load capacity derating |
319
+ | `pallet3d()` | 3D pallet loading heuristic (BLF + FFD) |
320
+ | `palletStack()` | Pallet stacking calculation |
321
+ | `pickTime()` | Picking time estimation |
322
+ | `safetyStock()` | Safety stock calculation |
323
+ | `serviceLevel()` | Service level calculation |
324
+ | `shipping()` | Shipping cost estimation |
325
+ | `tsp()` | TSP heuristic (NN + 2-Opt; exact for n ≤ 10) |
326
+
327
+ ### Energy & Utilities (15 functions)
328
+
329
+ ```typescript
330
+ import { powerCost, motorEfficiency, carbonFootprint, solarOutput, boilerEfficiency, heatPump, cusum } from 'formulab/energy';
331
+ ```
332
+
333
+ | Function | Description |
334
+ |----------|-------------|
335
+ | `boilerEfficiency()` | Boiler thermal efficiency (direct method) |
336
+ | `carbonFootprint()` | Scope 2 emissions |
337
+ | `compressedAirCost()` | Compressed air cost |
338
+ | `cusum()` | CUSUM energy anomaly detection |
339
+ | `degreeDay()` | Heating/Cooling degree days (HDD/CDD) |
340
+ | `heatPump()` | Heat pump COP & Carnot efficiency |
341
+ | `insulationRoi()` | Insulation ROI & payback |
342
+ | `ledRoi()` | LED lighting retrofit ROI |
343
+ | `motorEfficiency()` | Motor upgrade ROI |
344
+ | `pfCorrection()` | Power factor correction |
345
+ | `powerCost()` | Electricity cost with demand |
346
+ | `solarOutput()` | Solar panel output estimation (PVWatts-based) |
347
+ | `transformerLoss()` | Transformer loss & efficiency |
348
+ | `vfdSavings()` | VFD energy savings |
349
+ | `windOutput()` | Wind turbine output with Rayleigh CF |
350
+
351
+ ### Safety & Ergonomics (14 functions)
352
+
353
+ ```typescript
354
+ import { nioshLifting, noiseExposure, wbgtCalculate, ventilationRate, thermalComfort, arcFlash, lel } from 'formulab/safety';
355
+ ```
356
+
357
+ | Function | Description |
358
+ |----------|-------------|
359
+ | `arcFlash()` | Arc flash incident energy & PPE (IEEE 1584) |
360
+ | `confinedSpace()` | Confined space atmospheric assessment (OSHA) |
361
+ | `ergonomicRisk()` | REBA ergonomic risk scoring |
362
+ | `fallClearance()` | Fall protection clearance |
363
+ | `havsCalculate()` | Hand-arm vibration exposure |
364
+ | `illuminance()` | Workplace illuminance (Lumen Method) |
365
+ | `ladderAngle()` | Ladder safety angle (OSHA 4:1) |
366
+ | `lel()` | Mixed gas LEL (Le Chatelier's rule) |
367
+ | `nioshLifting()` | NIOSH lifting equation |
368
+ | `noiseExposure()` | TWA/Dose calculation |
369
+ | `respiratorCalculate()` | Respirator MUC calculation |
370
+ | `thermalComfort()` | PMV/PPD thermal comfort (ISO 7730) |
371
+ | `ventilationRate()` | Required ventilation ACH/CFM (ASHRAE/OSHA) |
372
+ | `wbgtCalculate()` | WBGT heat stress index |
373
+
374
+ ### Food & HACCP (6 functions)
375
+
376
+ ```typescript
377
+ import { calorie, nutrition, haccp, waterActivity, stabilityStudy } from 'formulab/food';
378
+ ```
379
+
380
+ | Function | Description |
381
+ |----------|-------------|
382
+ | `calorie()` | Calorie requirement (BMR/TDEE) |
383
+ | `expiry()` | Expiry date calculation |
384
+ | `nutrition()` | Nutrition facts calculation |
385
+ | `haccp()` | HACCP checklist generation |
386
+ | `waterActivity()` | Water activity microbial risk (HACCP) |
387
+ | `stabilityStudy()` | Accelerated stability (Arrhenius, ICH Q1A) |
388
+
389
+ ### Utility (16 functions)
390
+
391
+ ```typescript
392
+ import { solveAssignment, calculateUnit, statistics, regression, npv } from 'formulab/utility';
393
+ ```
394
+
395
+ | Function | Description |
396
+ |----------|-------------|
397
+ | `solveAssignment()` | Hungarian algorithm optimization |
398
+ | `calculateUnit()` | Unit conversion (7 categories) |
399
+ | `getUnitCategories()` | Get unit categories |
400
+ | `statistics()` | Descriptive statistics (mean, median, stdDev, etc.) |
401
+ | `percentile()` | Percentile/quantile calculation |
402
+ | `correlation()` | Pearson correlation coefficient |
403
+ | `regression()` | Simple linear regression |
404
+ | `movingAverage()` | SMA/EMA/WMA moving average |
405
+ | `linearInterpolation()` | 1D linear interpolation |
406
+ | `bilinearInterpolation()` | 2D bilinear interpolation |
407
+ | `roi()` | Return on Investment |
408
+ | `npv()` | Net Present Value |
409
+ | `depreciation()` | Asset depreciation (SL/DDB/SYD) |
410
+ | `lcc()` | Life Cycle Cost analysis |
411
+ | `normalize()` | Data normalization (min-max/z-score) |
412
+ | `histogram()` | Frequency distribution histogram |
413
+ | `weightedScore()` | Weighted scoring model |
414
+
415
+ ### Battery (10 functions)
416
+
417
+ ```typescript
418
+ import { energyDensity, cRate, stateOfHealth, cycleLife } from 'formulab/battery';
419
+ ```
420
+
421
+ | Function | Description |
422
+ |----------|-------------|
423
+ | `energyDensity()` | Wh/kg and Wh/L energy density |
424
+ | `cRate()` | C-rate ↔ current/time conversion |
425
+ | `stateOfHealth()` | SOH % with degradation status |
426
+ | `batteryPackConfig()` | Series/parallel cell configuration |
427
+ | `cycleLife()` | Cycle life estimation (chemistry/DOD/temp) |
428
+ | `internalResistance()` | DCIR from OCV and load voltage |
429
+ | `selfDischarge()` | Self-discharge rate calculation |
430
+ | `thermalRunaway()` | Thermal safety margin analysis |
431
+ | `bmsBalancing()` | BMS cell balancing time estimation |
432
+ | `chargingProfile()` | CC-CV charging profile timing |
433
+
434
+ ### Environmental (10 functions)
435
+
436
+ ```typescript
437
+ import { scope1Emissions, scope2Emissions, gwpCalculator, esgSummary } from 'formulab/environmental';
438
+ ```
439
+
440
+ | Function | Description |
441
+ |----------|-------------|
442
+ | `scope1Emissions()` | Fuel combustion direct emissions (6 fuels) |
443
+ | `scope2Emissions()` | Purchased electricity emissions (12 regions) |
444
+ | `scope3Emissions()` | Supply chain spend-based emissions (8 categories) |
445
+ | `vocEmissions()` | VOC emissions with capture/destruction |
446
+ | `productCarbonFootprint()` | Product lifecycle carbon footprint |
447
+ | `gwpCalculator()` | GWP conversion (8 gases × 3 time horizons) |
448
+ | `energyIntensity()` | Energy intensity (MJ/unit, kWh/unit) |
449
+ | `waterFootprint()` | Water footprint (blue/green/grey) |
450
+ | `emissionsIntensity()` | Emissions intensity per unit/revenue/employee |
451
+ | `esgSummary()` | ESG reduction tracking and projections |
452
+
453
+ ### Machining & CNC (12 functions)
454
+
455
+ ```typescript
456
+ import { truePosition, boltCircle, toolDeflection, threadOverWires } from 'formulab/machining';
457
+ ```
458
+
459
+ | Function | Description |
460
+ |----------|-------------|
461
+ | `truePosition()` | GD&T True Position (diametral, MMC bonus) |
462
+ | `boltCircle()` | Bolt hole pattern coordinates |
463
+ | `sineBarHeight()` | Sine bar gauge block height |
464
+ | `radialChipThinning()` | Chip load compensation for light radial cuts |
465
+ | `toolDeflection()` | End mill cantilever deflection |
466
+ | `cuspHeight()` | Ball mill scallop height |
467
+ | `effectiveDiameter()` | Ball mill effective cutting diameter |
468
+ | `boringBarDeflection()` | Boring bar deflection with L/D guidance |
469
+ | `threadOverWires()` | 3-wire thread measurement |
470
+ | `gaugeBlockStack()` | Gauge block combination (47/88/81-pc sets) |
471
+ | `triangleSolver()` | Triangle solver (SSS/SAS/ASA/SSA) |
472
+ | `cycleTimeEstimator()` | CNC cycle time estimation |
473
+
474
+ ## API Examples
475
+
476
+ ### OEE Calculation
477
+
478
+ ```typescript
479
+ import { oee } from 'formulab/quality';
480
+
481
+ const result = oee({
482
+ rawData: {
483
+ plannedTime: 480, // minutes
484
+ runTime: 420, // actual running time
485
+ totalCount: 1000, // total pieces produced
486
+ goodCount: 990, // good pieces
487
+ idealCycleTime: 0.4, // minutes per piece
488
+ },
489
+ });
490
+
491
+ console.log(result);
492
+ // {
493
+ // factors: { availability: 0.875, performance: 0.952, quality: 0.99, oee: 0.825 },
494
+ // percentages: { availability: 87.5, performance: 95.2, quality: 99, oee: 82.5 }
495
+ // }
496
+ ```
497
+
498
+ ### NIOSH Lifting Equation
499
+
500
+ ```typescript
501
+ import { nioshLifting } from 'formulab/safety';
502
+
503
+ const result = nioshLifting({
504
+ loadWeight: 23, // kg
505
+ horizontalDistance: 25, // cm
506
+ verticalDistance: 75, // cm (height at lift origin)
507
+ verticalTravel: 25, // cm (vertical travel distance)
508
+ asymmetryAngle: 0, // degrees
509
+ coupling: 'good', // 'good' | 'fair' | 'poor'
510
+ frequency: 1, // lifts per minute
511
+ duration: 'short', // 'short' | 'medium' | 'long'
512
+ });
513
+
514
+ console.log(result);
515
+ // {
516
+ // rwl: 21.62, // Recommended Weight Limit (kg)
517
+ // liftingIndex: 1.06, // LI = Load / RWL
518
+ // riskLevel: 'moderate',
519
+ // hm: 1.0, vm: 1.0, dm: 1.0, am: 1.0, fm: 0.94, cm: 1.0
520
+ // }
521
+ ```
522
+
523
+ ### Dimensional Weight
524
+
525
+ ```typescript
526
+ import { dimWeight } from 'formulab/logistics';
527
+
528
+ const result = dimWeight({
529
+ length: 60,
530
+ width: 40,
531
+ height: 30,
532
+ unit: 'cm',
533
+ carrier: 'international',
534
+ });
535
+
536
+ console.log(result);
537
+ // {
538
+ // dimWeight: 14.4,
539
+ // actualVolume: 0.072,
540
+ // cbm: 0.072,
541
+ // }
542
+ ```
543
+
544
+ ## Type Guards for Discriminated Unions
545
+
546
+ formulab provides runtime type guard functions for all [discriminated union](https://www.typescriptlang.org/docs/handbook/2/narrowing.html#discriminated-unions) input types. These enable type-safe integration when working with dynamic data (e.g., form inputs, API responses):
547
+
548
+ ```typescript
549
+ import { isCRateInput, cRate } from 'formulab/battery';
550
+
551
+ // Form data from user input (Record<string, unknown>)
552
+ const formData: unknown = { mode: 'currentToRate', capacityAh: 100, currentA: 50 };
553
+
554
+ if (isCRateInput(formData)) {
555
+ const result = cRate(formData); // Type-safe, no 'as any' needed
556
+ }
557
+ ```
558
+
559
+ ### Available Type Guards
560
+
561
+ | Guard | Domain | Discriminant | Variants |
562
+ |-------|--------|-------------|----------|
563
+ | `isCRateInput()` | battery | `mode` | currentToRate, rateToCurrent |
564
+ | `isDilutionInput()` | chemical | `solveFor` | c1, v1, c2, v2 |
565
+ | `isReactorInput()` | chemical | `shape` | cylindrical, spherical |
566
+ | `isHeatTransferInput()` | chemical | `mode` | conduction, convection, radiation |
567
+ | `isMomentOfInertiaInput()` | construction | `shape` | rectangle, circle, hollowRectangle, hollowCircle, iBeam, tSection, cChannel |
568
+ | `isOhmsLawInput()` | electronics | `solveFor` | voltage, current, resistance, power |
569
+ | `isMetalWeightInput()` | metal | `shape` | plate, round, pipe, angle |
570
+ | `isBoltInput()` | metal | `mode` | torqueToPreload, preloadToTorque |
571
+
572
+ ## Error Handling
573
+
574
+ See [ERRORS.md](./ERRORS.md) for the complete error behavior specification. Key points:
575
+
576
+ - **All validation failures** throw `RangeError` with descriptive messages
577
+ - **No silent NaN/Infinity** — every function guarantees finite outputs for valid inputs
578
+ - Every `@throws` condition is documented in each function's JSDoc
579
+
580
+ ```typescript
581
+ import { metalWeight } from 'formulab/metal';
582
+
583
+ try {
584
+ const result = metalWeight({ shape: 'plate', materialName: 'steel', length: 0, width: 100, thickness: 10 });
585
+ } catch (e) {
586
+ if (e instanceof RangeError) {
587
+ console.log(e.message); // "length must be positive"
588
+ }
589
+ }
590
+ ```
591
+
592
+ ## Tree Shaking
593
+
594
+ Import only what you need to minimize bundle size:
595
+
596
+ ```typescript
597
+ // Recommended - domain-specific import
598
+ import { oee } from 'formulab/quality';
599
+ import { metalWeight } from 'formulab/metal';
600
+
601
+ // Also works - main entry point (tree-shakeable)
602
+ import { oee, metalWeight } from 'formulab';
603
+
604
+ // Avoid - imports entire module
605
+ import * as formulab from 'formulab';
606
+ ```
607
+
608
+ ## TypeScript Support
609
+
610
+ Full TypeScript support with detailed type definitions:
611
+
612
+ ```typescript
613
+ import type {
614
+ OeeInput,
615
+ OeeResult,
616
+ CpkInput,
617
+ CpkResult,
618
+ MetalWeightInput,
619
+ MetalWeightResult,
620
+ } from 'formulab';
621
+ ```
622
+
623
+ ## Browser Support
624
+
625
+ formulab works in all modern browsers and Node.js:
626
+
627
+ - Node.js 18+
628
+ - Chrome 80+
629
+ - Firefox 75+
630
+ - Safari 13+
631
+ - Edge 80+
632
+
633
+ ## Contributing
634
+
635
+ Contributions are welcome! Please see our [GitHub repository](https://github.com/iyulab/formulab).
636
+
637
+ ```bash
638
+ # Clone the repository
639
+ git clone https://github.com/iyulab/formulab.git
640
+
641
+ # Install dependencies
642
+ pnpm install
643
+
644
+ # Run tests
645
+ pnpm test
646
+
647
+ # Build
648
+ pnpm build
649
+ ```
650
+
651
+ ## License
652
+
653
+ MIT © [iyulab](https://github.com/iyulab)
654
+
655
+ ---
656
+
657
+ <p align="center">
658
+ Made with engineering precision by <a href="https://github.com/iyulab">iyulab</a>
659
+ </p>