1 /*
  2  * FuelConsumptionUnit.js - Unit conversions for fuel consumption measurements
  3  *
  4  * Copyright © 2014-2015, 2018 JEDLSoft
  5  *
  6  * Licensed under the Apache License, Version 2.0 (the "License");
  7  * you may not use this file except in compliance with the License.
  8  * You may obtain a copy of the License at
  9  *
 10  *     http://www.apache.org/licenses/LICENSE-2.0
 11  *
 12  * Unless required by applicable law or agreed to in writing, software
 13  * distributed under the License is distributed on an "AS IS" BASIS,
 14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 15  *
 16  * See the License for the specific language governing permissions and
 17  * limitations under the License.
 18  */
 19 
 20 /*
 21 !depends
 22 Measurement.js
 23 */
 24 
 25 var Measurement = require("./Measurement.js");
 26 
 27 /**
 28  * @class
 29  * Create a new fuelconsumption measurement instance.
 30  *
 31  * @constructor
 32  * @extends Measurement
 33  * @param options {{unit:string,amount:number|string|undefined}} Options controlling
 34  * the construction of this instance
 35  */
 36 var FuelConsumptionUnit = function(options) {
 37     this.unit = "liter-per-100kilometers";
 38     this.amount = 0;
 39 
 40     this.ratios = FuelConsumptionUnit.ratios;
 41     this.aliases = FuelConsumptionUnit.aliases;
 42     this.aliasesLower = FuelConsumptionUnit.aliasesLower;
 43     this.systems = FuelConsumptionUnit.systems;
 44 
 45     this.parent.call(this, options);
 46 };
 47 
 48 FuelConsumptionUnit.prototype = new Measurement();
 49 FuelConsumptionUnit.prototype.parent = Measurement;
 50 FuelConsumptionUnit.prototype.constructor = FuelConsumptionUnit;
 51 
 52 FuelConsumptionUnit.ratios = {
 53     /*                         index    km/L        L/km        L/100km           mpg         mpgi       inverse? */
 54      "kilometer-per-liter":      [ 1,   1,          1,          100,              2.35215,    2.82481,   false ],
 55      "liter-per-kilometer":      [ 2,   1,          1,          0.01,             2.35215,    2.82481,   true  ],
 56      "liter-per-100kilometers":  [ 3,   100,        0.01,       1,                235.215,    282.481,   true  ],
 57      "mile-per-gallon":          [ 4,   0.425144,   2.35215,    235.215,          1,          1.20095,   false ],
 58      "mile-per-gallon-imperial": [ 5,   0.354006,   2.82481,    282.481,          0.8326741,  1,         false ]
 59 };
 60 
 61 /**
 62  * Return the type of this measurement. Examples are "mass",
 63  * "length", "speed", etc. Measurements can only be converted
 64  * to measurements of the same type.<p>
 65  *
 66  * The type of the units is determined automatically from the
 67  * units. For example, the unit "grams" is type "mass". Use the
 68  * static call {@link Measurement.getAvailableUnits}
 69  * to find out what units this version of ilib supports.
 70  *
 71  * @return {string} the name of the type of this measurement
 72  */
 73 FuelConsumptionUnit.prototype.getMeasure = function() {
 74     return "fuelconsumption";
 75 };
 76 
 77 /**
 78  * Return a new instance of this type of measurement.
 79  *
 80  * @param {Object} params parameters to the constructor
 81  * @return {Measurement} a measurement subclass instance
 82  */
 83 FuelConsumptionUnit.prototype.newUnit = function(params) {
 84     return new FuelConsumptionUnit(params);
 85 };
 86 
 87 FuelConsumptionUnit.aliases = {
 88     "Km/liter": "kilometer-per-liter",
 89     "KM/Liter": "kilometer-per-liter",
 90     "KM/L": "kilometer-per-liter",
 91     "Kilometers Per Liter": "kilometer-per-liter",
 92     "kilometers per liter": "kilometer-per-liter",
 93     "km/l": "kilometer-per-liter",
 94     "Kilometers/Liter": "kilometer-per-liter",
 95     "Kilometer/Liter": "kilometer-per-liter",
 96     "kilometers/liter": "kilometer-per-liter",
 97     "kilometer/liter": "kilometer-per-liter",
 98     "km/liter": "kilometer-per-liter",
 99     "Liter/100km": "liter-per-100kilometers",
100     "Liters/100km": "liter-per-100kilometers",
101     "Liter/100kms": "liter-per-100kilometers",
102     "Liters/100kms": "liter-per-100kilometers",
103     "liter/100km": "liter-per-100kilometers",
104     "liters/100kms": "liter-per-100kilometers",
105     "liters/100km": "liter-per-100kilometers",
106     "liter/100kms": "liter-per-100kilometers",
107     "Liter/100KM": "liter-per-100kilometers",
108     "Liters/100KM": "liter-per-100kilometers",
109     "L/100km": "liter-per-100kilometers",
110     "L/100KM": "liter-per-100kilometers",
111     "l/100KM": "liter-per-100kilometers",
112     "l/100km": "liter-per-100kilometers",
113     "l/100kms": "liter-per-100kilometers",
114     "Liter/km": "liter-per-kilometer",
115     "Liters/km": "liter-per-kilometer",
116     "Liter/kms": "liter-per-kilometer",
117     "Liters/kms": "liter-per-kilometer",
118     "liter/km": "liter-per-kilometer",
119     "liters/kms": "liter-per-kilometer",
120     "liters/km": "liter-per-kilometer",
121     "liter/kms": "liter-per-kilometer",
122     "Liter/KM": "liter-per-kilometer",
123     "Liters/KM": "liter-per-kilometer",
124     "L/km": "liter-per-kilometer",
125     "L/KM": "liter-per-kilometer",
126     "l/KM": "liter-per-kilometer",
127     "l/km": "liter-per-kilometer",
128     "l/kms": "liter-per-kilometer",
129     "MPG(US)": "mile-per-gallon",
130     "USMPG ": "mile-per-gallon",
131     "mpg": "mile-per-gallon",
132     "mpgUS": "mile-per-gallon",
133     "mpg(US)": "mile-per-gallon",
134     "mpg(us)": "mile-per-gallon",
135     "mpg-us": "mile-per-gallon",
136     "mpg Imp": "mile-per-gallon-imperial",
137     "MPG(imp)": "mile-per-gallon-imperial",
138     "mpg(imp)": "mile-per-gallon-imperial",
139     "mpg-imp": "mile-per-gallon-imperial"
140 };
141 
142 (function() {
143     FuelConsumptionUnit.aliasesLower = {};
144     for (var a in FuelConsumptionUnit.aliases) {
145         FuelConsumptionUnit.aliasesLower[a.toLowerCase()] = FuelConsumptionUnit.aliases[a];
146     }
147 })();
148 
149 /**
150  * Return a new measurement instance that is converted to a new
151  * measurement unit. Measurements can only be converted
152  * to measurements of the same type.<p>
153  *
154  * @param {string} to The name of the units to convert to
155  * @return {number|undefined} the converted measurement
156  * or undefined if the requested units are for a different
157  * measurement type
158  */
159 FuelConsumptionUnit.prototype.convert = function(to) {
160     if (!to || typeof(FuelConsumptionUnit.ratios[this.normalizeUnits(to)]) === 'undefined') {
161         return undefined;
162     }
163     return FuelConsumptionUnit.convert(to, this.unit, this.amount);
164 };
165 
166 FuelConsumptionUnit.systems = {
167     "metric": [
168         "liter-per-kilometer",
169         "liter-per-100kilometers",
170         "kilometer-per-liter"
171     ],
172     "uscustomary": [
173         "mile-per-gallon"
174     ],
175     "imperial": [
176         "mile-per-gallon-imperial"
177     ],
178     "conversions": {
179         "metric": {
180             "uscustomary": {
181                 "liter-per-kilometer": "mile-per-gallon",
182                 "kilometer-per-liter": "mile-per-gallon",
183                 "liter-per-100kilometers": "mile-per-gallon"
184             },
185             "imperial": {
186                 "liter-per-kilometer": "mile-per-gallon-imperial",
187                 "kilometer-per-liter": "mile-per-gallon-imperial",
188                 "liter-per-100kilometers": "mile-per-gallon-imperial"
189             }
190         },
191         "uscustomary": {
192             "metric": {
193                 "mile-per-gallon": "liter-per-100kilometers"
194             },
195             "imperial": {
196                 "mile-per-gallon": "mile-per-gallon-imperial"
197             }
198         },
199         "imperial": {
200             "metric": {
201                 "mile-per-gallon-imperial": "liter-per-100kilometers"
202             },
203             "uscustomary": {
204                 "mile-per-gallon-imperial": "mile-per-gallon"
205             }
206         }
207     }
208 };
209 
210 /**
211  * Convert a FuelConsumption to another measure.
212  *
213  * @static
214  * @param to {string} unit to convert to
215  * @param from {string} unit to convert from
216  * @param fuelConsumption {number} amount to be convert
217  * @returns {number|undefined} the converted amount
218  */
219 FuelConsumptionUnit.convert = function(to, from, fuelConsumption) {
220     from = Measurement.getUnitIdCaseInsensitive(FuelConsumptionUnit, from) || from;
221     to = Measurement.getUnitIdCaseInsensitive(FuelConsumptionUnit, to) || to;
222     var fromRow = FuelConsumptionUnit.ratios[from];
223     var toRow = FuelConsumptionUnit.ratios[to];
224     if (typeof(from) === 'undefined' || typeof(to) === 'undefined') {
225         return undefined;
226     }
227 
228     if (fromRow[6] !== toRow[6]) {
229         // inverses of each other. Avoid the divide by 0.
230         return fuelConsumption ? (fromRow[toRow[0]] / fuelConsumption) : 0;
231     }
232 
233     // not inverses, so just multiply by the factor
234     return fuelConsumption * fromRow[toRow[0]];
235 };
236 
237 /**
238  * Scale the measurement unit to an acceptable level. The scaling
239  * happens so that the integer part of the amount is as small as
240  * possible without being below zero. This will result in the
241  * largest units that can represent this measurement without
242  * fractions. Measurements can only be scaled to other measurements
243  * of the same type.
244  *
245  * @param {string=} measurementsystem system to use (uscustomary|imperial|metric),
246  * or undefined if the system can be inferred from the current measure
247  * @param {Object=} units mapping from the measurement system to the units to use
248  * for this scaling. If this is not defined, this measurement type will use the
249  * set of units that it knows about for the given measurement system
250  * @return {Measurement} a new instance that is scaled to the
251  * right level
252  */
253 FuelConsumptionUnit.prototype.scale = function(measurementsystem, units) {
254     return new FuelConsumptionUnit({
255         unit: this.unit,
256         amount: this.amount
257     });
258 };
259 
260 /**
261  * Expand the current measurement such that any fractions of the current unit
262  * are represented in terms of smaller units in the same system instead of fractions
263  * of the current unit. For example, "6.25 feet" may be represented as
264  * "6 feet 4 inches" instead. The return value is an array of measurements which
265  * are progressively smaller until the smallest unit in the system is reached
266  * or until there is a whole number of any unit along the way.
267  *
268  * @param {string=} measurementsystem system to use (uscustomary|imperial|metric),
269  * or undefined if the system can be inferred from the current measure
270  * @param {Object=} units mapping from the measurement system to the units to use
271  * for this scaling. If this is not defined, this measurement type will use the
272  * set of units that it knows about for the given measurement system
273  * @return {Array.<Measurement>} an array of new measurements in order from
274  * the current units to the smallest units in the system which together are the
275  * same measurement as this one
276  */
277 FuelConsumptionUnit.prototype.expand = function(measurementsystem, units) {
278     return [this]; // nothing to expand
279 };
280 
281 /**
282  * @private
283  * @static
284  */
285 FuelConsumptionUnit.getMeasures = function() {
286     return Object.keys(FuelConsumptionUnit.ratios);
287 };
288 
289 //register with the factory method
290 Measurement._constructors["fuelconsumption"] = FuelConsumptionUnit;
291 
292 module.exports = FuelConsumptionUnit;
293