Spaces:
Runtime error
Runtime error
File size: 3,843 Bytes
7e49c4d | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 | import { calculateAllEmissions } from './carbonCalculator.js';
/**
* Simulation Service
* Projects future emissions based on behavior change scenarios
*/
/**
* Apply a simulation scenario to the original assessment data and calculate new emissions
* @param {Object} assessmentData - original user inputs
* @param {Object} scenarioParams - changes to apply
* @param {string} scenarioName
* @returns {Object} simulation result
*/
export function runSimulation(assessmentData, scenarioParams, scenarioName) {
// Build modified data by applying scenario params
const modifiedData = applyScenario(assessmentData, scenarioParams);
// Calculate original and projected emissions
const original = calculateAllEmissions(assessmentData);
const projected = calculateAllEmissions(modifiedData);
const originalTotal = original.totalEmission;
const projectedTotal = projected.totalEmission;
const savings = originalTotal - projectedTotal;
const reductionPercentage =
originalTotal > 0 ? parseFloat(((savings / originalTotal) * 100).toFixed(1)) : 0;
return {
scenarioName,
scenarioParams,
originalEmission: originalTotal,
projectedEmission: projectedTotal,
reductionPercentage,
annualSavingsKg: Math.round(savings),
categoryBreakdown: {
original: {
transport: original.transportEmission,
energy: original.energyEmission,
food: original.foodEmission,
shopping: original.shoppingEmission,
},
projected: {
transport: projected.transportEmission,
energy: projected.energyEmission,
food: projected.foodEmission,
shopping: projected.shoppingEmission,
},
},
};
}
/**
* Apply scenario parameters to original assessment data
* @param {Object} original
* @param {Object} params
* @returns {Object} modified assessment data
*/
function applyScenario(original, params) {
const modified = { ...original };
// Direct field overrides
if (params.carFuelType !== undefined) modified.carFuelType = params.carFuelType;
if (params.dietType !== undefined) modified.dietType = params.dietType;
if (params.renewablePercentage !== undefined)
modified.renewablePercentage = params.renewablePercentage;
// Reduction factors
if (params.cyclingReductionFactor !== undefined) {
// Reduce daily car km by the cycling reduction factor
modified.dailyCarKm = original.dailyCarKm * (1 - params.cyclingReductionFactor);
modified.cyclingKmPerWeek =
(original.cyclingKmPerWeek || 0) + original.dailyCarKm * params.cyclingReductionFactor * 5;
}
if (params.flightReductionFactor !== undefined) {
modified.shortFlightsPerYear = Math.round(
original.shortFlightsPerYear * (1 - params.flightReductionFactor)
);
modified.longFlightsPerYear = Math.round(
original.longFlightsPerYear * (1 - params.flightReductionFactor)
);
}
if (params.electricityReductionFactor !== undefined) {
modified.monthlyElectricityKwh =
original.monthlyElectricityKwh * (1 - params.electricityReductionFactor);
}
if (params.shoppingReductionFactor !== undefined) {
modified.clothingItemsPerYear = Math.round(
original.clothingItemsPerYear * (1 - params.shoppingReductionFactor)
);
modified.electronicsItemsPerYear = Math.round(
original.electronicsItemsPerYear * (1 - params.shoppingReductionFactor)
);
}
return modified;
}
/**
* Run multiple simulations and return ranked results
* @param {Object} assessmentData
* @param {Array} scenarios
* @returns {Array} sorted simulation results
*/
export function runMultipleSimulations(assessmentData, scenarios) {
const results = scenarios.map(({ name, params }) => runSimulation(assessmentData, params, name));
return results.sort((a, b) => b.annualSavingsKg - a.annualSavingsKg);
}
|