Skip to content

Instantly share code, notes, and snippets.

@francisrstokes
Created April 16, 2018 06:49
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save francisrstokes/9e4546ed52c0ee59a10b22633eeb958d to your computer and use it in GitHub Desktop.
Save francisrstokes/9e4546ed52c0ee59a10b22633eeb958d to your computer and use it in GitHub Desktop.
Fluent API for performing length conversions
const validUnits = ['km', 'm', 'cm', 'mm', 'in', 'ft', 'mile'];
const isLengthObj = (lo) =>
'_val' in lo &&
'_unit' in lo &&
typeof lo._val === 'number' &&
typeof lo._unit === 'string' &&
validUnits.includes(lo._unit);
const formatUnit = (unit, val) => {
switch(unit) {
case 'km':
case 'm':
case 'cm':
case 'mm':
case 'in':
case 'ft': return unit;
case 'mile': return (val !== 1) ? 'miles' : unit;
}
}
const toCm = ({_val, _unit}) => {
switch(_unit) {
case 'km':
return _val * 100000;
case 'm':
return _val * 100;
case 'cm':
return _val;
case 'mm':
return 0.1 * _val;
case 'in':
return _val * 2.54;
case 'ft':
return _val * 30.48;
case 'mile':
return _val * 160934;
default:
throw new Error(`Unit ${_unit} is not valid. Supported units: ${validUnits.join(', ')}`);
}
};
const toUnit = (lo, toUnit) => {
const std = toCm(lo);
switch(toUnit) {
case 'km':
return std / 100000;
case 'm':
return std / 100;
case 'cm':
return std;
case 'mm':
return std * 10;
case 'in':
return std / 2.54;
case 'ft':
return std / 30.48;
case 'mile':
return std / 160934;
default:
throw new Error(`Unit ${lo._unit} is not valid. Supported units: ${validUnits.join(', ')}`);
}
}
const length = (val, unit) => {
if (!validUnits.includes(unit)) {
throw new Error(`Unit ${unit} is not valid. Supported units: ${validUnits.join(', ')}`);
}
if (!(typeof val === 'number')) {
throw new Error(`Non number value provided: ${val}`);
}
return {
_val: val,
_unit: unit,
add: (nVal, nUnit) => {
if (typeof nVal === 'object') {
if (isLengthObj(nVal)) {
return length(val + toUnit(nVal, unit), unit);
} else {
throw new Error(`Invalid legnth object: ${nVal}`);
}
} else {
return length(val + toUnit({_val: nVal, _unit: nUnit}, unit), unit);
}
},
subtract: (nVal, nUnit) => {
if (typeof nVal === 'object') {
if (isLengthObj(nVal)) {
return length(val - toUnit(nVal, unit), unit);
} else {
throw new Error(`Invalid legnth object: ${nVal}`);
}
} else {
return length(val - toUnit({_val: nVal, _unit: nUnit}, unit), unit);
}
},
to: (nUnit) => {
if (!validUnits.includes(nUnit)) {
throw new Error(`Unit ${nUnit} is not valid. Supported units: ${validUnits.join(', ')}`);
}
return length(toUnit({_val: val, _unit: unit}, nUnit), nUnit);
},
toString: () => `${val.toFixed(3)} ${unit}${unit === 'mile' ? 's' : ''}`,
rawValue: () => val,
rawUnit: () => unit
}
};
module.exports = length;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment