/**
* @copyright 2015 Tridium, Inc. All Rights Reserved.
* @author Gareth Johnson
*/
/**
* Defines {@link baja.Dimension}.
* @module baja/obj/Dimension
*/
define([ "bajaScript/sys",
"bajaScript/baja/obj/Simple",
"bajaScript/baja/obj/objUtil" ], function (
baja,
Simple,
objUtil) {
'use strict';
var SYMBOLS = [ 'm', 'kg', 's', 'A', 'K', 'Mol', 'cd', '$' ],
DECODE_STRING_REGEX = /(\(\S+?\))/g,
DECODE_SEGMENT_REGEX = /\(([a-zA-Z$]+)(-?[\d.]*)\)/,
subclass = baja.subclass,
callSuper = baja.callSuper,
cacheDecode = objUtil.cacheDecode,
cacheEncode = objUtil.cacheEncode;
/**
* Convert a number to its exponent string representation.
*
* @inner
* @param {Number} num
* @returns {String}
*/
function toExponent(num) {
switch (num) {
case 1: return '';
case 2: return '²';
case 3: return '³';
default: return num;
}
}
/**
* Represents a `baja:Dimension` in BajaScript.
*
* When creating a `Simple`, always use the `make()` method instead of
* creating a new Object.
*
* @class
* @alias baja.Dimension
* @extends baja.Simple
*/
var Dimension = function Dimension(meter, kilogram, second, ampere,
kelvin, mole, candela, dollar) {
callSuper(Dimension, this, arguments);
this.$m = meter || 0;
this.$kg = kilogram || 0;
this.$s = second || 0;
this.$A = ampere || 0;
this.$K = kelvin || 0;
this.$mol = mole || 0;
this.$cd = candela || 0;
this.$$ = dollar || 0;
};
subclass(Dimension, Simple);
/**
* Default `Dimension` instance.
*
* @type {baja.Dimension}
*/
Dimension.DEFAULT = new Dimension();
/**
* Null `Dimension` instance (same as `DEFAULT`).
*
* @type {baja.Dimension}
*/
Dimension.NULL = Dimension.DEFAULT;
/**
* Used to maintain an internal cache of `Dimension` objects, keyed by value.
*
* @private
* @type {Object}
*/
Dimension.$cache = {};
/**
* Create a new instance of `baja.Dimension`. Each parameter will be an
* exponent for a particular unit of measurement. 0 indicates the absence of
* that unit, 1 indicates linear, 2 for squared, 3 for cubed, etc.
*
* @param {Number} meter=0 exponent for the meter component
* @param {Number} kilogram=0 exponent for the kilogram component
* @param {Number} second=0 exponent for the second component
* @param {Number} ampere=0 exponent for the ampere component
* @param {Number} kelvin=0 exponent for the Kelvin component
* @param {Number} mole=0 exponent for the mole component
* @param {Number} candela=0 exponent for the candela component
* @param {Number} dollar=0 exponent for the dollar component
* @returns {baja.Dimension}
*/
Dimension.make = function (meter, kilogram, second, ampere,
kelvin, mole, candela, dollar) {
if (!meter && !kilogram && !second && !ampere && !kelvin && !mole &&
!candela && !dollar) {
return baja.Dimension.DEFAULT;
}
var dim = new Dimension(meter, kilogram, second, ampere, kelvin, mole,
candela, dollar),
str = dim.encodeToString(),
existing = Dimension.$cache[str];
return existing || (Dimension.$cache[str] = dim);
};
/**
* @see baja.Dimension.make
* @returns {baja.Dimension}
*/
Dimension.prototype.make = function () {
return Dimension.make.apply(this, arguments);
};
/**
* Decode a `Dimension` from a `String`.
* @method
* @param {String} str
* @returns {baja.Dimension}
*/
Dimension.prototype.decodeFromString = cacheDecode(function (str) {
if (!str) {
return Dimension.DEFAULT;
}
var matches = str.match(DECODE_STRING_REGEX),
map = {},
match,
value,
symbol,
i;
if (!matches) {
throw new Error("invalid input '" + str + "'");
}
for (i = 0; i < matches.length; i++) {
match = DECODE_SEGMENT_REGEX.exec(matches[i]);
if (match) {
symbol = match[1];
if (SYMBOLS.indexOf(symbol) < 0) {
throw new Error("invalid symbol '" + symbol + "'");
}
value = parseFloat(match[2]) || 1;
map[symbol] = value;
}
}
return baja.Dimension.make(map.m, map.kg, map.s, map.A, map.K, map.Mol,
map.cd, map.$);
});
/**
* Encode a `Dimension` to a `String`.
*
* @method
* @returns {String}
*/
Dimension.prototype.encodeToString = cacheEncode(function () {
var that = this,
values = [ that.$m, that.$kg, that.$s, that.$A,
that.$K, that.$mol, that.$cd, that.$$ ],
value,
outValues = [],
outStr,
i;
for (i = 0; i < values.length; i++) {
value = values[i];
if (value) {
outValues.push(value === 1 ? SYMBOLS[i] : SYMBOLS[i] + value);
}
}
outStr = outValues.join(')(');
return outStr && '(' + outStr + ')';
});
/**
* Returns a human-readable representation of the dimension.
*
* @returns {String}
*/
Dimension.prototype.toString = function () {
var that = this,
values = [ that.$m, that.$kg, that.$s, that.$A,
that.$K, that.$mol, that.$cd, that.$$ ],
value,
outValues = [],
i;
for (i = 0; i < values.length; i++) {
value = values[i];
if (value) {
outValues.push(SYMBOLS[i] + toExponent(value));
}
}
return outValues.join('·');
};
/**
* Get the meter component of this dimension.
* @returns {Number}
*/
Dimension.prototype.getMeter = function () { return this.$m; };
/**
* Get the kilogram component of this dimension.
* @returns {Number}
*/
Dimension.prototype.getKilogram = function () { return this.$kg; };
/**
* Get the second component of this dimension.
* @returns {Number}
*/
Dimension.prototype.getSecond = function () { return this.$s; };
/**
* Get the ampere component of this dimension.
* @returns {Number}
*/
Dimension.prototype.getAmpere = function () { return this.$A; };
/**
* Get the Kelvin component of this dimension.
* @returns {Number}
*/
Dimension.prototype.getKelvin = function () { return this.$K; };
/**
* Get the mole component of this dimension.
* @returns {Number}
*/
Dimension.prototype.getMole = function () { return this.$mol; };
/**
* Get the candela component of this dimension.
* @returns {Number}
*/
Dimension.prototype.getCandela = function () { return this.$cd; };
/**
* Get the dollar component of this dimension.
* @returns {Number}
*/
Dimension.prototype.getDollar = function () { return this.$$; };
return Dimension;
});