@spg-drycooling/field-services

Convert, calculate and validate fields and values for the SPG Drycooling Asset Database

Usage no npm install needed!

<script type="module">
  import spgDrycoolingFieldServices from 'https://cdn.skypack.dev/@spg-drycooling/field-services';
</script>

README

SPG Drycooling Field Services

This is a collection of utils and tools for use with the SPG Asset Database.

Install

npm install -S @spg-drycooling/field-services

or

yarn add @spg-drycooling/field-services

Usage

The field services packages exposes a collection of tools that can be imported from the main entry point:

import { FieldCalculcator, IUnit } from '@spg-drycooling/field-services';

Core concepts

Supported units

The tools included in this package support a wide range of unit types and units:

UnitType Base unit Imperial Metric (SI) Other
Acceleration g-force m/s2, g-force
Angle deg deg, rad, grad, arcmin, arcsec
ApparentPower VA VA, mVA, kVA, MVA, GVA
Area m2 in2, ft2, ac, mi2, yd2 mm2, cm2, m2, ha, km2
Charge c c, mC, μC, nC, pC
Current A A, mA, kA
Density kg/m3 kg/m3
Each ea / ea, dz
Energy J Wh, mWh, kWh, MWh, GWh, J, kJ
Force N lbf N, kN
Frequency Hz Hz, mHz, kHz, MHz, GHz, THz, rpm, deg/s, rad/s
Generic / / wu, ul, %, kWe, W/m2K, kJ/kg, bar(g)+FV, bool
Illuminance lx ft-cd lx
Length m in, ft-us, ft, mi, yd, nMi mm, cm, m, km fathom
Mass g oz, lb, t mcg, mg, g, kg, mt
MassFlowRate kg/s lb/s kg/s
Pace s/m s/ft, min/mi s/m, min/km
PartsPer ppm / ppm, ppb, ppt, ppq
Power W W, kW, mW, kM, MW, GW
Pressure kPa psi, ksi Pa, hPa, kPa, MPa, bar, mbar torr
ReactiveEnergy VARh VARh, mVARh, kVARh, MVARh, GVARh
ReactivePower VAR VARh, mVARh, kVARh, MVARh, GVARh
Sound db(A) dB(A)
Speed km/h ft/s, knot m/s, km/h, m/h
Temperature C F C, K R
Time s ns, mu, ms, s, min, h, d, week, month, year
Voltage V V, mV, kV
Volume l tsp, Tbs, in3, fl-oz, cup, pnt, qt, gal, ft3, yd3 mm3, cm3, ml, l, kl, m3, km3, cl, dl
VolumeFlowRate l/s tsp/s, Tbs/s, in3/s, in3/min, in3/h, fl-oz/s, fl-oz/min, fl-oz/h, cup/s, pnt/s, pnt/min, pnt/h, qt/s, gal/s, gal/min, gal/h, ft3/s, ft3/min, ft3/h, yd3/s, yd3/min, yd3/h mm3/s, cm3/s, ml/s, cl/s, dl/s, l/s, l/min, l/h, kl/s, kl/min, kl/h, m3/s, m3/min, m3/h, km3/s

Good to know

  • Generic is a special case, this unit type contains all units that cannot be converted and should be used as is.
  • All units displayed in the table can be converted to any other unit within their unit type.
  • New units & unit types can be added, provided the correct conversion rules are implemented.

Formula

Fields are calculated and validation from formulas. A formula consists of 3 parts:

  1. source: the lefthand value in the operation
  2. operator: the operator to use
  3. target: the righthand side in the operation

The source and target can be a new formula as well, allowing the recursive nesting of formulas.

Formula segment

The source and target properties are formula segments. They can contain 1 of 4 things:

  1. a value: concrete value to use in the calculcations/validations
  2. a field ID: a unique key that maps to a field provided in the fields map (see calculcation below)
  3. a formula: a nested formula that results in a value
  4. a datalist: an object containing info to map to a value provided in the datalistItems property

Available operators

Operations are always converted to a formula with a left- and righthand side.

E.g.:

10^3

will be seen as

10 POW 3

These operators are available:

  • ABS: calculcate absolute value
  • ADD: add the target to the source
  • DIVIDE: divide the source by the target
  • MAX: return the highest value between the source and the target
  • MIN: return the lowest value between the source and the target
  • MODULUS: return the remainder after dividing the source by the target
  • MULTIPLY: multiply the source with the target
  • NOPE: ignore this operation, return the source
  • POW: exponentiate the source with the target
  • ROUND: round the source to the number of decimal places as defined by the target (negative values get rounded to the left of the decimal point)
  • SUBTRACT: subtract the target from the source

Examples

Simple division:

{
  "source": {
    "value": 10
  },
  "operator": "DIVIDE",
  "target": {
    "value": 5
  }
}

Would translate to:

10 / 5

Power:

Formula:

{
  "source": {
    "value": 15
  },
  "operator": "POW",
  "target": {
    "value": 2
  }
}

Would translate to:

15^2

Nested formula:

{
  "source": [
    {
      "source": {
        "value": 15
      },
      "operator": "POW",
      "target": {
        "value": 2
      }
    }
  ],
  "operator": "SUBTRACT",
  "target": [
    {
      "source": [
        {
          "source": {
            "value": 3
          },
          "operator": "MULTIPLY",
          "target": {
            "value": 0.9
          }
        }
      ],
      "operator": "ROUND",
      "target": {
        "value": 2
      }
    }
  ]
}

Would translate to:

15^2 - ROUND(3 * 0.9, 2)

Validation rules

Validation rules follow the same syntax and rules as the calculation formulas. Instead of an operator, they use a comparator.

E.g.:

{
  "source": {
    "value": 25
  },
  "comparator": "LTE",
  "target": {
    "value": 99
  }
}

Available comparators

  • EQ: resolve if source is equal to target
  • GT: resolve if source is greater than target
  • GTE: resolve if source is greater than or equal to target
  • IN: resolve if source is included in target (list)
  • LT: resolve if source is less than target
  • LTE: resolve if source is less than or equal to target
  • NE: resolve if source is not equal to target
  • NIN: resolve if source is not included in target (list)

Field Calculator

The FieldCalculator is used to calculcate a field value from a provided formula and values map.

It exposes 3 methods:

mapOperation

Provided an operator, return a function to run the operation on a source and target. Used internally to map operators to operation methods.

const operator = FieldCalculator.mapOperation("SUBTRACT");

return operator(2, 5); // return value: 7

mapValue

Provided a field, formula segment (e.g. source) and fields map, return the resulting value. Used internally in the calculcate method to allow recursive calculcation.

const field = { code: "FIELD", nominalValue: 2.4 };
const segment = {
  source: {
    value: 4
  },
  operator: "MULTIPLY",
  target: {
    fieldId: "TARGET_FIELD"
  }
};
const fields: {
  TARGET_FIELD: {
    currentValue: 0.3
  }
};

const value = FieldCalculator.mapValue(field, segment, fields); // return value: 1.2

calculcate

Provided a field, formula and fields map, return the calculcated value.

const field = { code: "FIELD", nominalValue: 2.4 };
const formula = {
  source: [{
    source: {
      value: 4
    },
    operator: "MULTIPLY",
    target: {
      fieldId: "TARGET_FIELD"
    }
  }],
  operator: ROUND,
  target: {
    value: 2
  }
};
const fields: {
  TARGET_FIELD: {
    currentValue: 0.3
  }
};

const value = FieldCalculator.calculate(field, formula, fields); // return value: 1.20

Field Validator

The FieldValidator is used to validate a field value from a provided validation rule and values map.

It exposes 3 methods:

mapComparator

Provided an comparator, return a function to run the comparison on a source and target. Used internally to map comparators to comparison methods.

const comparator = FieldValidator.mapComparator("EQ");

return comparator(2, 5); // return value: false

mapValue

Provided a formula segment (e.g. source) and fields map, return the resulting value. Used internally in the validate method to allow recursive validation.

const segment = {
  fieldId: "TARGET_FIELD"
};
const fields: {
  TARGET_FIELD: {
    currentValue: 9
  }
};

const value = FieldCalculator.mapValue(segment, fields); // return value: 9

validate

Provided a field, validation rule and fields map, return the resulting valid state.

const field = { code: "FIELD", nominalValue: 2.4 };
const validation = {
  source: {
    value: 4
  },
  comparator: "GTE",
  target: {
    fieldId: "TARGET_FIELD"
  }
};
const fields: {
  TARGET_FIELD: {
    currentValue: 0.3
  }
};

const value = FieldValidator.validate(field, validation, fields); // return value: true

Unit Converter

The unitConverter is capable of converting a value between the known units of a unit type, as well as returning available unit types and units based on a provided unit.

Definitions

Each unit type (measure) has defined a conversion rule for each of its units. Based on these conversion rules, values can be converted from one unit to another.

A unit conversion definition can define units for multiple systems (e.g.: SI, US). For each system, a base unit is defined, providing a ratio to be used for conversion between systems.

E.g.:

const length: IUnitConversionDefinition = {
  metric: {
    mm: {
      name: {
        singular: 'Millimeter',
        plural: 'Millimeters',
      },
      baseUnitFactor: 1 / 1000,
    },
    m: {
        name: {
        singular: 'Meter',
        plural: 'Meters',
        },
        baseUnitFactor: 1,
    }
  },
  imperial: {
    ft: {
      name: {
        singular: 'Foot',
        plural: 'Feet',
      },
      baseUnitFactor: 1,
    },
  }
  baseUnits: {
    metric: {
      unit: 'm',
      ratio: 3.2808399,
  },
  imperial: {
      unit: 'ft',
      ratio: 0.3048,
    },
  }
};

Convert units within a measure

const result = unitConverter.convert(10, { from: 'mm', to: 'ft' });

// return value: 10000g

Get a list of all available units

const result = unitConverter.getUnits();

/**
 *
 * result = [{
 *  unitSymbol: 'kg',
 *  measure: 'mass',
 *  system: 'metric',
 *  unit: {
 *    name: {
 *      singular: 'Kilogram';
        plural: 'Kilograms';
 *    },
 *    baseUnitFactor: 1000
 *  }
 * }]
 */

Get a list of all available units from a measure

const result = unitConverter.getUnitsByMeasure(UnitType.Mass, MeasurementSystems.Metric);

/**
 *
 * result = [{
 *   unitSymbol: 'kg',
 *  measure: 'mass',
 *  system: 'metric',
 *  unit: {
 *    name: {
 *      singular: 'Kilogram';
        plural: 'Kilograms';
 *    },
 *    baseUnitFactor: 1000
 *  }
 * }, ...]
 */

Get a unit

const result = unitConverter.getUnit(Units.kg);

/**
 *
 * result = {
 *  unitSymbol: 'kg',
 *  measure: 'mass',
 *  system: 'metric',
 *  unit: {
 *    name: {
 *      singular: 'Kilogram';
        plural: 'Kilograms';
 *    },
 *    baseUnitFactor: 1000
 *  }
 * }
 */

Get the base unit

const result = unitConverter.getBaseUnit(Units.kg);

/**
 *
 * result = {
 *  unitSymbol: 'g',
 *  measure: 'mass',
 *  system: 'metric',
 *  unit: {
 *    name: {
 *       singular: 'Gram';
         plural: 'Grams';
 *    },
 *    baseUnitFactor: 1
 *  }
 * }
 */

Get the unit type for a unit

const result = unitConverter.getMeasure(Units.kg);

/**
 *
 * result = 'Mass'
 */