main.js
'use strict';
const { isCorrect, unitsFormat } = require('./lib/helpers');
const BaseFeels = require('./lib/base');
function apparentTemp(tempConvert, func) {
if (!isCorrect(this.temp) || (!isCorrect(this.humidity) && !isCorrect(this.dewPoint))) {
throw new Error('One of the required arguments are not specified');
}
const { temp } = this.units;
const t = tempConvert(this.temp, temp, 'c');
const index = (isCorrect(this.dewPoint) && !isCorrect(this.humidity)) ?
func(t, tempConvert(this.dewPoint, temp, 'c'), { dewPoint: true }) :
func(t, this.humidity);
return tempConvert(index, 'c', this._units.temp, this.round);
}
class Feels extends BaseFeels {
constructor(opts) {
super();
this.setOptions(opts);
this._methods = {
HI: 'heatIndex',
AWBGT: 'AWBGT',
HI_CA: 'humidex',
AAT: 'AAT',
WCI: 'windChill'
};
}
setOptions(opts = {}) {
this.units = unitsFormat(opts.units);
this.temp = opts.temp;
this.speed = opts.speed || 0;
this.humidity = opts.humidity;
this.dewPoint = opts.dewPoint;
this.wvp = opts.wvp;
this.round = opts.round;
this._units = {
temp: this.units.temp,
speed: this.units.speed
};
return this;
}
registerMethod(method) {
if (this[method]) {
this._methods[method.toUpperCase()] = method;
return this;
}
throw new Error(`${method} doesn't exists`);
}
registerMethods(methods) {
if (Array.isArray(methods)) {
for (const method of methods) {
this.registerMethod(method);
}
return this;
}
throw new TypeError('Methods must be an array');
}
addMethod(method, func) {
if (typeof func === 'function') {
this[method] = func.bind(this);
this.registerMethod(method);
return this;
}
throw new TypeError(`${method} must be a function`);
}
toCelsius() {
this._units.temp = 'c';
return this;
}
toFahrenheit() {
this._units.temp = 'f';
return this;
}
toKelvin() {
this._units.temp = 'k';
return this;
}
like(methods = ['HI', 'HI_CA', 'AAT', 'WCI']) {
if (typeof methods === 'string') {
const method = this._methods[methods.toUpperCase()];
if (method) {
return this[method]();
}
throw new RangeError(`Methods must be one of: ${Object.keys(this._methods).join(', ')}`);
}
if (Array.isArray(methods)) {
let like = 0;
let count = methods.length;
for (const m of methods) {
const method = this._methods[m.toUpperCase()];
if (method) {
try {
like += this[method]();
} catch (e) {
// eslint-disable-next-line no-plusplus
count--;
}
} else {
// eslint-disable-next-line max-len
throw new RangeError(`Methods must be one of: ${Object.keys(this._methods).join(', ')}`);
}
}
if (!count) {
throw new Error('No valid methods for these values');
}
return Feels.tempConvert(like / count, '', '', this.round);
}
return this.like(['HI', 'HI_CA', 'AAT', 'WCI']);
}
heatIndex() { // HI
return apparentTemp.call(this, Feels.tempConvert, Feels.heatIndex);
}
AWBGT() { // AWBGT
return apparentTemp.call(this, Feels.tempConvert, Feels.AWBGT);
}
humidex() { // HI_CA
return apparentTemp.call(this, Feels.tempConvert, Feels.humidex);
}
AAT() { // AAT
// eslint-disable-next-line max-len
if (!isCorrect(this.temp, this.speed) || (!isCorrect(this.humidity) && !isCorrect(this.dewPoint))) {
throw new Error('One of the required arguments are not specified');
}
const { temp, speed } = this.units;
const u = this._units.temp;
const t = Feels.tempConvert(this.temp, temp, 'c');
const s = Feels.speedConvert(this.speed, speed, 'mps');
const index = (isCorrect(this.dewPoint) && !isCorrect(this.humidity)) ?
Feels.AAT(t, s, Feels.tempConvert(this.dewPoint, temp, 'c'), { dewPoint: true }) :
Feels.AAT(t, s, this.humidity);
return Feels.tempConvert(index, 'c', u, this.round);
}
windChill() { // WCI
if (!isCorrect(this.temp, this.speed)) {
throw new Error('One of the required arguments are not specified');
}
const { temp, speed } = this.units;
const u = this._units.temp;
const t = Feels.tempConvert(this.temp, temp, 'c');
const s = Feels.speedConvert(this.speed, speed, 'mps');
return Feels.tempConvert(Feels.windChill(t, s), 'c', u, this.round);
}
getWaterVapourPressure() {
if (isCorrect(this.wvp)) {
return this.wvp;
} else if (isCorrect(this.humidity, this.temp)) {
const temp = Feels.tempConvert(this.temp, this.units.temp, 'c');
return Feels.getWVP(temp, this.humidity, this.round);
}
throw new Error('One of the required arguments are not specified');
}
getWaterVapourPressureByDewPoint() {
if (isCorrect(this.wvp)) {
return this.wvp;
} else if (isCorrect(this.dewPoint)) {
const dewPoint = Feels.tempConvert(this.dewPoint, this.units.temp, 'c');
return Feels.getWVPbyDP(dewPoint, this.round);
}
throw new Error('Dew point is not specified');
}
getAproximateRelativeHumidity() {
if (isCorrect(this.humidity)) {
return this.humidity;
} else if (isCorrect(this.temp, this.dewPoint)) {
const { temp } = this.units;
const t = Feels.tempConvert(this.temp, temp, 'c');
const dewPoint = Feels.tempConvert(this.dewPoint, temp, 'c');
return Feels.getARH(t, dewPoint, this.round);
}
throw new Error('One of the required arguments are not specified');
}
getRelativeHumidity() {
if (isCorrect(this.humidity)) {
return this.humidity;
} else if (isCorrect(this.temp) && (isCorrect(this.wvp) || isCorrect(this.dewPoint))) {
const { temp } = this.units;
const t = Feels.tempConvert(this.temp, temp, 'c');
return (isCorrect(this.dewPoint) && !isCorrect(this.wvp)) ?
Feels.getRH(t, Feels.tempConvert(this.dewPoint, temp, 'c'), { dewPoint: true, round: this.round }) :
Feels.getRH(t, this.wvp, this.round);
}
throw new Error('One of the required arguments are not specified');
}
getAproximateDewPoint() {
if (isCorrect(this.dewPoint)) {
return this.dewPoint;
} else if (isCorrect(this.temp, this.humidity)) {
const temp = Feels.tempConvert(this.temp, this.units.temp, 'c');
return Feels.tempConvert(Feels.getADP(temp, this.humidity), 'c', this._units.temp, this.round);
}
throw new Error('One of the required arguments are not specified');
}
getDewPoint() { // dew point for [-40, 50], humidity must be in (0, 100]
if (isCorrect(this.dewPoint)) {
return this.dewPoint;
} else if (isCorrect(this.temp, this.humidity)) {
const temp = Feels.tempConvert(this.temp, this.units.temp, 'c');
return Feels.tempConvert(Feels.getDP(temp, this.humidity), 'c', this._units.temp, this.round);
}
throw new Error('One of the required arguments are not specified');
}
getFrostPoint() { // frost point for [-80, 0], humidity must be in (0, 100]
if (!isCorrect(this.temp, this.humidity)) {
throw new Error('One of the required arguments are not specified');
}
const temp = Feels.tempConvert(this.temp, this.units.temp, 'c');
return Feels.tempConvert(Feels.getFP(temp, this.humidity), 'c', this._units.temp, this.round);
}
}
Feels.prototype.toC = Feels.prototype.toCelsius;
Feels.prototype.toF = Feels.prototype.toFahrenheit;
Feels.prototype.toK = Feels.prototype.toKelvin;
Feels.prototype.getWVP = Feels.prototype.getWaterVapourPressure;
Feels.prototype.getWVPbyDP = Feels.prototype.getWaterVapourPressureByDewPoint;
Feels.prototype.getARH = Feels.prototype.getAproximateRelativeHumidity;
Feels.prototype.getRH = Feels.prototype.getRelativeHumidity;
Feels.prototype.getADP = Feels.prototype.getAproximateDewPoint;
Feels.prototype.getDP = Feels.prototype.getDewPoint;
Feels.prototype.getFP = Feels.prototype.getFrostPoint;
module.exports = Feels;