vehicle/running/result.js

/**
 * Works out emissions and costs based on journey miles

 * @module
 * @since 0.1.21
 */

import { isPHEV } from '../classification';
import { getPPM } from './costs/components/fuelandelectric/ppm';
import { getCO2gPerMile } from './emissions/components/fuelandelectric/co2gpm';
import { getMPG, getBatteryRangeMiles, getIsCSMode } from './util';
import {
    totalCostOfAllJourneys,
    numberOfJourneys,
    journeyCostPortion,
    journeyCostTotal,
    journeyEmissionsPortion,
    journeyEmissionsTotal,
    totalEmissionsOfAllJourneys,
    getJourneyMilesForPHEVs,
    getElectricMiles,
    getICEMiles,
    getJourneyFuelRatio,
} from './journey/calculate';

/**
 * Calculate journeys and mileages taken
 * @returns {struct} electric, ice and totals
 */
const getSplit = (skv_config) => {
    const skv_default_config = {
        journey_miles: '',
        mpg: 0,
        battery_range_miles: 0,
    };

    const skv_local_config = Object.assign(skv_default_config, skv_config);

    let journey_miles = 0;

    const is_phev = isPHEV(skv_local_config.mpg, getBatteryRangeMiles(skv_local_config));

    // if its a PHEV then we may need to make adjustments to the journey miles
    // using Charge Sustaining mode (previously called Condition B)
    if (is_phev) {
        journey_miles = getJourneyMilesForPHEVs(skv_local_config);
    } else {
        journey_miles = skv_local_config.journey_miles;
    }

    // calculate the split between ICE and electric
    const electric_miles = getElectricMiles(getBatteryRangeMiles(skv_local_config), getMPG(skv_local_config), journey_miles);

    // what we have left from the total battery range minus the electric range
    const ice_miles = getICEMiles(electric_miles, journey_miles);

    // proportion of journey carried out on electric miles
    const electric_ratio = getJourneyFuelRatio(electric_miles, journey_miles);
    // proportion of journey carried out on ICE miles
    const ice_ratio = getJourneyFuelRatio(ice_miles, journey_miles);

    return {
        electric: {
            miles: electric_miles,
            ratio: electric_ratio,
        },
        ice: {
            miles: ice_miles,
            ratio: ice_ratio,
        },
    };
};

/**
 * get journey miles on electric and ice
 * @param {struct} skv_config
 * @returns {struct}
 */
const getJourney = (skv_config) => {
    const skv_journey_config = {
        mpg: getMPG(skv_config),
        battery_range_miles: getBatteryRangeMiles(skv_config),
    };
    // add journey_miles if it exists in the config
    if (Object.prototype.hasOwnProperty.call(skv_config, 'journey_miles')) {
        skv_journey_config.journey_miles = skv_config.journey_miles;
    }
    return getSplit(skv_journey_config);
};

/* *******************************************
   ***************** COSTS *******************
   *******************************************
*/

/**
 * calculate a single journey cost
 * @param {struct} skv_journey_split miles of journey on electric and ice
 * @param {struct} skv_ppm pence per mile on electric and ice
 * @returns {struct}
 */
const singleJourneyCost = (skv_journey_split, skv_ppm) => {
    // calculate individual electric and ICE portions of the journey
    const skv_return = {
        electric: {
            ppm: skv_ppm.electric,
            distance: skv_journey_split.electric,
            total_pounds: journeyCostPortion(skv_journey_split.electric, skv_ppm.electric),
        },
        ice: {
            ppm: skv_ppm.ice,
            distance: skv_journey_split.ice,
            total_pounds: journeyCostPortion(skv_journey_split.ice, skv_ppm.ice),
        },
    };
    // calculate the total combined cost
    skv_return.combined = journeyCostTotal(skv_return);
    return skv_return;
};

/**
 *
 * @returns {struct}
*/
const getCost = (skv_config) => {
    const skv_return = {
        journey: {},
        total: {
            journeys: {},
            ice: {},
            electric: {},
            combined: {},
        },
    };
    const skv_journey_split = getJourney(skv_config);
    const skv_ppm = getPPM(skv_config);
    // get the costs for a single journey by combined the split and the ppm
    skv_return.journey = singleJourneyCost(skv_journey_split, skv_ppm);
    skv_return.total.journeys.amount = numberOfJourneys(skv_config.journey_miles, skv_config.total_miles);
    // calculate the total cost based on the total mileage passed in
    const result = totalCostOfAllJourneys(skv_return.journey, skv_config.total_miles);
    skv_return.total.electric = result.electric;
    skv_return.total.ice = result.ice;
    skv_return.total.combined = result.combined;
    return skv_return;
};

/* *******************************************
   *************** EMISSIONS *****************
   *******************************************
*/

/**
 * calculate a single journey emissions
 * @param {struct} skv_journey_split miles of journey on electric and ice
 * @param {struct} skv_co2_g_per_mile
 * @returns {struct}
 */
const singleJourneyEmissions = (skv_journey_split, skv_co2_g_per_mile) => {
    // calculate individual electric and ICE portions of the journey
    const skv_return = {
        electric: {
            co2_g_per_mile: skv_co2_g_per_mile.electric,
            distance: skv_journey_split.electric,
            total_co2_g: journeyEmissionsPortion(skv_journey_split.electric, skv_co2_g_per_mile.electric),
        },
        ice: {
            co2_g_per_mile: skv_co2_g_per_mile.ice,
            distance: skv_journey_split.ice,
            total_co2_g: journeyEmissionsPortion(skv_journey_split.ice, skv_co2_g_per_mile.ice),
        },
    };

    // calculate the total combined cost
    skv_return.combined = journeyEmissionsTotal(skv_return);
    return skv_return;
};

/**
 *
 * @returns {struct}
*/
const getEmissions = (skv_config) => {
    const skv_return = {
        journey: {},
        total: {
            journeys: {},
            ice: {},
            electric: {},
            combined: {},
        },
    };
    const skv_journey_split = getJourney(skv_config);
    const skv_co2_g_per_mile = getCO2gPerMile(skv_config);

    // get the costs for a single journey by combined the split and the ppm
    skv_return.journey = singleJourneyEmissions(skv_journey_split, skv_co2_g_per_mile);
    skv_return.total.journeys.amount = numberOfJourneys(skv_config.journey_miles, skv_config.total_miles);
    // // calculate the total cost based on the total mileage passed in
    const result = totalEmissionsOfAllJourneys(skv_return.journey, skv_config.total_miles);
    skv_return.total.electric = result.electric;
    skv_return.total.ice = result.ice;
    skv_return.total.combined = result.combined;
    return skv_return;
};

export {
    getSplit,
    getIsCSMode,
    getJourney,
    // costs
    getCost,
    singleJourneyCost,
    // emissions
    getEmissions,
    singleJourneyEmissions,
};