You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
cvm/src/make-units.js

94 lines
2.3 KiB
JavaScript

"use strict";
/* TODO:
toDisplay
conversion between unit scales (eg. IEC -> metric bytes)
*/
const util = require("util");
const chalk = require("chalk");
function capitalize(string) {
return string[0].toUpperCase() + string.slice(1);
}
module.exports = function makeUnits(unitSpecs) {
let resultObject = {};
unitSpecs.forEach((spec, i) => {
let proto = {
[util.inspect.custom]: function (_depth, options) {
let inspectString = `<Unit> ${this.amount} ${this.unit}`;
if (options.colors === true) {
return chalk.cyan(inspectString);
} else {
return inspectString;
}
},
toString: function () {
return `${this.amount} ${this.unit}`;
},
toDisplay: function (decimals) {
let roundingFactor = Math.pow(10, decimals);
let unitMagnitude = i;
let amount = this.amount;
let unitsLeft = (i < unitSpecs.length - 1);
function createOfCurrentMagnitude() {
let roundedValue = Math.round(amount * roundingFactor) / roundingFactor;
return resultObject[unitSpecs[unitMagnitude].unit](roundedValue);
}
while (unitsLeft === true) {
let currentUnit = unitSpecs[unitMagnitude];
if (amount < currentUnit.toNext) {
return createOfCurrentMagnitude();
} else {
amount = amount / currentUnit.toNext;
unitMagnitude += 1;
unitsLeft = (unitMagnitude < unitSpecs.length - 1);
}
}
return createOfCurrentMagnitude;
}
};
unitSpecs.forEach((otherSpec, otherI) => {
let factor = 1;
if (otherI < i) {
/* Convert downwards, to smaller units (== larger numbers) */
unitSpecs.slice(otherI, i).reverse().forEach((specStep) => {
factor = factor * specStep.toNext;
});
} else if (otherI > i) {
/* Convert upwards, to larger units (== smaller numbers) */
unitSpecs.slice(i, otherI).forEach((specStep) => {
factor = factor / specStep.toNext;
});
}
proto[`to${capitalize(otherSpec.unit)}`] = function () {
return resultObject[otherSpec.unit](this.amount * factor);
};
});
resultObject[spec.unit] = function createUnit(value) {
if (typeof value !== "number") {
throw new Error("Value must be numeric");
} else {
return Object.assign(Object.create(proto), {
unit: spec.unit,
amount: value
});
}
};
});
return resultObject;
};