/*
* niViz -- snow profiles visualization
* Copyright (C) 2015 WSL/SLF - Fluelastrasse 11 - 7260 Davos Dorf - Switzerland.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
(function (niviz) {
'use strict';
// --- Module Dependencies ---
var properties = Object.defineProperties;
var property = Object.defineProperty;
var Value = niviz.Value;
var Common = niviz.Common;
var inherits = niviz.util.inherits;
/** @module niviz.Value */
var EXPONENT = 2.4;
var FACTOR = 1 / EXPONENT;
var COEFFICIENT = 19.3;
/**
* Stores a Hand Hardness Index (HHI) value.
*
* @class Hardness
* @extends Value
*
* @constructor
* @param {Number} [top]
* @param {Number} [value]
* @param {Number} [bottom]
*/
function Hardness(top, val, bottom) {
if (typeof val === 'string' || typeof val === 'number' && val > 6)
val = Hardness.parse(val);
/**
* The HHI value between .666 and 6.0.
*
* @property value
* @type {Number}
*/
var value;
property(this, 'value', {
enumerable: true,
get: function () { return value; },
set: function value$set(to) {
value = this.$newton = undefined;
if (to) {
var v = parseFloat(to);
if (isNaN(v) || v < .666 || v > 6)
throw new Error('HHI index must be between .666 (F-) and 6.0, was: ' + to);
value = v;
}
}
});
// Prepare Newton cache
property(this, '$newton', { writable: true, enumerable: false });
// Call Value constructor
Value.call(this, top, val, bottom);
}
inherits(Hardness, Value);
properties(Hardness, {
/**
* HHI code to numeric index mapping.
*
* @property index
* @type {Object}
*/
index: {
value: {
'F-': 2 / 3,
'F': 1,
'F+': 4 / 3,
'F-4F': 1.5,
'4F-': 5 / 3,
'4F': 2,
'4F+': 7 / 3,
'4F-1F': 2.5,
'1F-': 8 / 3,
'1F': 3,
'1F+': 10 / 3,
'1F-P': 3.5,
'P-': 11 / 3,
'P': 4,
'P+': 13 / 3,
'P-K': 4.5,
'K-': 14 / 3,
'K': 5,
'K+': 16 / 3,
'K-I': 5.5,
'I': 6
}
},
/**
* @property codes
* @type {Array.<String>}
*/
codes: {
value: ['F', '4F', '1F', 'P', 'K', 'I']
},
/**
* @property options
* @type {Array.<String>}
*/
caamlcodes: {
value: [ 'F-', 'F', 'F+', 'F-4F', '4F-', '4F', '4F+', '4F-1F', '1F-', '1F', '1F+',
'1F-P', 'P-', 'P', 'P+', 'P-K', 'K-', 'K', 'K+', 'K-I', 'I' ]
},
allcodes: {
get: function allcodes$get() {
if (Common.defaults.hand_hardness_format === 'International')
return [ 'F', 'F-4F', '4F', '4F-1F', '1F', '1F-P', 'P', 'P-K', 'K', 'K-I', 'I',
'F-', 'F+', '4F-', '4F+', '1F-', '1F+', 'P-', 'P+', 'K-', 'K+' ]
else
return [ 'F-', 'F', 'F+', '4F-', '4F', '4F+', '1F-', '1F', '1F+', 'P-', 'P', 'P+',
'K-', 'K', 'K+', 'I', 'F-4F', '4F-1F', '1F-P', 'P-K', 'K-I']
}
}
});
/**
* Converts a `value` to HHI index. If the value
* is a string, it is interpreted as an HHI code;
* if it is a number it is interpreted as ram
* resistance in Newton.
*
* @method parse
* @static
*
* @param {Number, String} value
*
* @return {Number}
*/
Hardness.parse = function (value) {
if (!value) return null;
switch (typeof value) {
case 'number':
if (value >= 1200) return 6;
if (value <= COEFFICIENT) return 1;
return Math.pow(value / COEFFICIENT, FACTOR);
case 'string':
var idx = Hardness.index[value];
if (!idx)
throw new Error('Unknown HHI code: ' + value);
return idx;
//return [value].reduce(avg, 0);
//return value.split(/\s*-\s*/).reduce(avg, 0);
default:
throw new Error('Cannot convert value to HHI index: ' + value);
}
};
properties(Hardness.prototype, {
/**
* HHI code string.
*
* @property code
* @type {String}
*/
code: {
get: function code$get() {
if (!this.value) return undefined;
var lower = Math.floor(this.value);
if (this.value < 1) return Hardness.codes[0];
if (this.value === lower)
return Hardness.codes[lower - 1];
return [
Hardness.codes[lower - 1],
Hardness.codes[Math.ceil(this.value) - 1]
].join('-');
},
set: function code$set(value) {
this.value = (value != null) ?
Hardness.parse(String(value)) : undefined;
}
},
/**
* HHI CAAML code string.
*
* @property caamlcode
* @type {String}
*/
caamlcode: {
get: function caamlcode$get() {
if (!this.value) return undefined;
var lower = Math.floor(this.value);
if (this.value < 1) return Hardness.caamlcodes[0];
if (this.value > 5.6) return 'I';
if (this.value === lower) // exact value
return Hardness.caamlcodes[(lower - 1) * 4 + 1];
else if (this.value - lower > 0.3 && this.value - lower < 0.4)
return Hardness.caamlcodes[(lower - 1) * 4 + 2];
else if (this.value - lower > 0.6 && this.value - lower < 0.7)
return Hardness.caamlcodes[lower * 4];
return [
Hardness.codes[lower - 1],
Hardness.codes[Math.ceil(this.value) - 1]
].join('-');
},
set: function caamlcode$set(value) {
this.value = (value != null) ?
Hardness.parse(String(value)) : undefined;
}
},
/**
* Ram Resistance in Newton.
*
* @property newton
* @type {Number}
*/
newton: {
get: function newton$get() {
if (!this.value) return undefined;
if (this.$newton == null) {
if ((this.value * 10) % 5 === 0 && this.value <= 6 && this.value >= 1) {
if (this.value === 1) this.$newton = 20;
else if (this.value === 1.5) this.$newton = 50;
else if (this.value === 2) this.$newton = 100;
else if (this.value === 2.5) this.$newton = 175;
else if (this.value === 3) this.$newton = 250;
else if (this.value === 3.5) this.$newton = 390;
else if (this.value === 4) this.$newton = 500;
else if (this.value === 4.5) this.$newton = 715;
else if (this.value === 5) this.$newton = 1000;
else if (this.value === 5.5) this.$newton = 1100;
else if (this.value > 5.5) this.$newton = 1200;
} else {
this.$newton = Math.pow(this.value, EXPONENT) * COEFFICIENT;
}
}
return this.$newton;
},
set: function newton$set(value) {
this.value = (value != null) ?
Hardness.parse(parseFloat(value)) : undefined;
}
}
});
// --- Helpers ---
// Computes the average index value for a list of HHI codes.
function avg(a, b, i, code) {
var idx = Hardness.index[b];
if (!idx)
throw new Error('Unknown HHI code: ' + b);
if (i < code.length - 1)
return a + idx;
return (a + idx) / code.length;
}
// --- Module Exports ---
Value.Hardness = Hardness;
}(niviz));