/**
* Calculate journey, fuel and electric ppm, total mileages
*
* @module
* @since 0.1.21
*/
import { requiredKeys } from '../../../../../keys/required';
import { getMPG, getBatteryRangeMiles } from '../../../util';
import { roundToDP } from '../../../../../maths/util';
import { removeVAT } from '../../../../../calculations/vat';
import { hydrogenKgToLitres, kmToMiles } from '../../../../../maths/conversions';
import {
ratio,
litresUsedPerMile,
costForFullCharge,
costForFullChargePPM,
applyRatio,
costForICEPPM,
} from './calculate';
/**
*
* @returns {struct}
*/
const checkRequiredKeys = (skv_config, required_keys) => {
const rst_required_keys = requiredKeys(skv_config, required_keys);
// check to see if any keys missing
if (
!rst_required_keys.success
|| rst_required_keys.data.length > 0
) {
let missing_keys_msg = '';
if (rst_required_keys.data.length > 0) {
missing_keys_msg = ` // Missing required keys: ${rst_required_keys.data}`;
}
throw new Error(` ${rst_required_keys.msg}${missing_keys_msg} for running.vehicle.journey`);
}
};
/**
* petrol/diesel or hydrogen can be used in calculation so switch here
* @param {struct} skv_config including ice_pp_litre or hydrogen_pp_kg
* @returns {number}
*/
const getICEPPLitre = (skv_config) => {
let num_return;
// if ice_pp_litre (petrol/diesel) is provided then use that
if (
Object.prototype.hasOwnProperty.call(skv_config, 'ice_pp_litre')
&& skv_config.ice_pp_litre > 0
) {
return skv_config.ice_pp_litre;
}
// if hydrogen_pp_kg (hydrogen) is provided then use that and convert to litres
if (
Object.prototype.hasOwnProperty.call(skv_config, 'hydrogen_pp_kg')
&& skv_config.hydrogen_pp_kg > 0
) {
// 1 kg of hydrogen is 14.128 litres
num_return = hydrogenKgToLitres(skv_config.hydrogen_pp_kg);
}
return num_return;
};
/**
* calculate vehicle ICE cost
* @param {struct} skv_config ice_pp_litre, mpg, vat_percentage
* @returns {struct}
*/
const getICEPPM = (skv_config) => {
const required_keys = ['mpg', 'ice_pp_litre|hydrogen_pp_kg', 'vat_percentage'];
checkRequiredKeys(skv_config, required_keys);
const skv_return = {
exc_vat: 0,
inc_vat: 0,
};
// if mpg_user is provided then use that, otherwise use mpg which is the official figure
const mpg = Object.prototype.hasOwnProperty.call(skv_config, 'mpg_user')
? skv_config.mpg_user : skv_config.mpg;
const ltr_used_per_mile = litresUsedPerMile(mpg, 1);
// handle petrol/diesel or hydrogen pp litre
const ice_pp_litre = getICEPPLitre(skv_config);
// calculate cost per mile
const cost_ppm = costForICEPPM(ice_pp_litre, ltr_used_per_mile);
// apply VAT
skv_return.inc_vat = roundToDP(cost_ppm, 2);
skv_return.exc_vat = removeVAT(skv_return.inc_vat, skv_config.vat_percentage);
skv_return.exc_vat = roundToDP(skv_return.exc_vat, 2);
return skv_return;
};
/**
* calculate Battery Range Cost PPM
* @param {struct} skv_config battery_range_miles_user, battery_range_miles, battery_total_capacity_kwh, elec_pp_kwh
* @returns {number}
*/
const getBatteryRangeCostPPM = (skv_config) => {
// ensure we have a user provided battery range defaulting to the official battery range
const battery_range_miles_user = Object.prototype.hasOwnProperty.call(skv_config, 'battery_range_miles_user')
? skv_config.battery_range_miles_user : skv_config.battery_range_miles;
// calculate the user provided battery range as a ratio of the official battery range
const battery_range_ratio = ratio(skv_config.battery_range_miles, battery_range_miles_user);
// cost for full charge
const cost_for_full_charge = costForFullCharge(skv_config.battery_total_capacity_kwh, skv_config.elec_pp_kwh);
// cost per mile
let cost_ppm = costForFullChargePPM(cost_for_full_charge, skv_config.battery_range_miles);
cost_ppm = applyRatio(cost_ppm, battery_range_ratio);
return cost_ppm;
};
/**
* calculate Battery Efficiency Cost PPM
* @param {struct} skv_config electric_energy_consumption, elec_pp_kwh
* @returns {number}
*/
const getEfficiencyCostPPM = (skv_config) => {
// Set to per km instead of per 100km
const elec_energy_consumption_kwh_per_km = skv_config.electric_energy_consumption / 100;
// convert to miles. convert using equivalance flag on kmToMiles function
const elec_energy_consumption_kwh_per_mile = kmToMiles(elec_energy_consumption_kwh_per_km, true);
// cost per mile
const cost_ppm = applyRatio(elec_energy_consumption_kwh_per_mile, skv_config.elec_pp_kwh);
return cost_ppm;
};
/**
* calculate vehicle electric cost
* @param {struct} skv_config elec_pp_kwh, battery_range_miles, battery_total_capacity_kwh, vat_percentage
* @returns {struct}
*/
const getElectricPPM = (skv_config) => {
let required_keys = ['battery_range_miles', 'battery_total_capacity_kwh', 'elec_pp_kwh', 'vat_percentage'];
if (skv_config.method === 'efficiency') {
required_keys = ['electric_energy_consumption', 'elec_pp_kwh', 'vat_percentage'];
}
checkRequiredKeys(skv_config, required_keys);
const skv_return = {
exc_vat: 0,
inc_vat: 0,
};
// apply the ratio to factor in a user provided value if provided
let cost_ppm = '';
// If we're expanding this in future change to switch
// however only 2 cases currently, range and efficiency
if (skv_config.method !== 'efficiency') {
cost_ppm = getBatteryRangeCostPPM(skv_config);
} else {
cost_ppm = getEfficiencyCostPPM(skv_config);
}
// electric is gross
skv_return.inc_vat = roundToDP(cost_ppm, 2);
// remove vat to get net amount. Large outlets pay full vat (20%), smaller ones pay reduced (5%)
// the vat could be an average of multiple vat rates if different tariffs are used
skv_return.exc_vat = removeVAT(skv_return.inc_vat, skv_config.vat_percentage);
skv_return.exc_vat = roundToDP(skv_return.exc_vat, 2);
return skv_return;
};
/**
* get PPM on electric and ice
* @param {struct} skv_config
* @returns {struct}
*/
const getPPM = (skv_config) => {
let skv_ice_result = {
exc_vat: 0,
inc_vat: 0,
};
let skv_electric_result = {
exc_vat: 0,
inc_vat: 0,
};
if (getMPG(skv_config) > 0) {
const skv_ice_config = {
ice_pp_litre: getICEPPLitre(skv_config),
mpg: getMPG(skv_config),
vat_percentage: skv_config.ice_vat_percentage,
};
skv_ice_result = getICEPPM(skv_ice_config);
}
if (getBatteryRangeMiles(skv_config) > 0) {
const skv_electric_config = {
elec_pp_kwh: skv_config.elec_pp_kwh,
battery_range_miles: getBatteryRangeMiles(skv_config),
battery_total_capacity_kwh: skv_config.battery_total_capacity_kwh,
vat_percentage: skv_config.elec_vat_percentage,
electric_energy_consumption: skv_config.electric_energy_consumption,
method: skv_config.method,
};
skv_electric_result = getElectricPPM(skv_electric_config);
}
return {
electric: skv_electric_result,
ice: skv_ice_result,
};
};
export {
getElectricPPM,
getICEPPM,
getPPM,
getICEPPLitre,
getEfficiencyCostPPM,
getBatteryRangeCostPPM,
};