GreenPlusbyGXS / web /src /utils /carbonFootprintTracker.js
gaialive's picture
Upload 106 files
759768a verified
/**
* Carbon Footprint Tracker
* Comprehensive carbon footprint calculation and tracking system
*/
export class CarbonFootprintTracker {
constructor() {
// Emission factors (kg CO2e per unit)
this.emissionFactors = {
transportation: {
car_gasoline: 0.404, // per mile
car_diesel: 0.411,
car_hybrid: 0.200,
car_electric: 0.100, // varies by grid
bus: 0.089,
train: 0.045,
subway: 0.040,
bicycle: 0.000,
walking: 0.000,
motorcycle: 0.280,
airplane_domestic: 0.255, // per mile
airplane_international: 0.195,
taxi: 0.450,
rideshare: 0.350
},
energy: {
electricity_grid: 0.707, // per kWh (US average)
electricity_renewable: 0.050,
natural_gas: 5.300, // per therm
heating_oil: 10.180, // per gallon
propane: 5.750, // per gallon
coal: 2.230, // per kg
wood: 0.000 // considered carbon neutral
},
food: {
beef: 27.0, // per kg
lamb: 24.5,
pork: 7.6,
chicken: 4.6,
fish: 3.0,
dairy: 3.2,
eggs: 1.9,
rice: 2.3,
vegetables: 0.4,
fruits: 0.3,
grains: 0.8,
legumes: 0.4,
nuts: 0.3
},
waste: {
landfill: 0.57, // per kg
recycling: -0.30, // negative = avoided emissions
composting: -0.20,
incineration: 0.40
},
water: {
tap_water: 0.0004, // per liter
bottled_water: 0.24, // per liter
shower: 0.006, // per minute
bath: 0.024, // per bath
dishwasher: 0.012, // per load
washing_machine: 0.018 // per load
}
};
// Activity categories and their typical ranges
this.activityRanges = {
transportation: { min: 0, max: 50, unit: 'kg CO2e/day' },
energy: { min: 0, max: 30, unit: 'kg CO2e/day' },
food: { min: 1, max: 15, unit: 'kg CO2e/day' },
waste: { min: 0, max: 5, unit: 'kg CO2e/day' },
water: { min: 0, max: 3, unit: 'kg CO2e/day' }
};
// Global averages for comparison
this.globalAverages = {
daily: 16.4, // kg CO2e per person per day (global average)
annual: 6000, // kg CO2e per person per year
sustainable: 2300 // kg CO2e per person per year (1.5°C target)
};
}
/**
* Calculate carbon footprint from activities
*/
async calculateCarbonFootprint(activities, timeframe = 'daily') {
try {
console.log('🌱 Calculating carbon footprint...');
const footprint = {
timestamp: new Date().toISOString(),
timeframe: timeframe,
activities: activities,
breakdown: {},
total: 0,
comparison: {},
recommendations: [],
trends: {},
confidence: 90
};
// Calculate emissions by category
Object.keys(this.emissionFactors).forEach(category => {
footprint.breakdown[category] = this.calculateCategoryEmissions(category, activities[category] || {});
footprint.total += footprint.breakdown[category].total;
});
// Scale to requested timeframe
footprint.total = this.scaleToTimeframe(footprint.total, 'daily', timeframe);
Object.keys(footprint.breakdown).forEach(category => {
footprint.breakdown[category].total = this.scaleToTimeframe(
footprint.breakdown[category].total, 'daily', timeframe
);
});
// Generate comparisons
footprint.comparison = this.generateComparisons(footprint.total, timeframe);
// Generate recommendations
footprint.recommendations = this.generateRecommendations(footprint.breakdown, footprint.total);
// Calculate trends (mock for now)
footprint.trends = this.calculateTrends(footprint);
// Assess confidence
footprint.confidence = this.assessConfidence(activities);
console.log('✅ Carbon footprint calculation completed');
return footprint;
} catch (error) {
console.error('Carbon footprint calculation failed:', error);
throw new Error(`Carbon footprint calculation failed: ${error.message}`);
}
}
/**
* Calculate emissions for a specific category
*/
calculateCategoryEmissions(category, activities) {
const categoryData = {
total: 0,
activities: {},
percentage: 0
};
const factors = this.emissionFactors[category];
if (!factors) return categoryData;
Object.keys(activities).forEach(activity => {
const amount = activities[activity];
const factor = factors[activity];
if (factor && amount > 0) {
const emissions = amount * factor;
categoryData.activities[activity] = {
amount: amount,
factor: factor,
emissions: Math.round(emissions * 1000) / 1000,
unit: this.getActivityUnit(category, activity)
};
categoryData.total += emissions;
}
});
categoryData.total = Math.round(categoryData.total * 1000) / 1000;
return categoryData;
}
/**
* Get unit for activity
*/
getActivityUnit(category, activity) {
const units = {
transportation: 'miles',
energy: category === 'energy' && activity.includes('electricity') ? 'kWh' :
activity.includes('gas') ? 'therms' : 'gallons',
food: 'kg',
waste: 'kg',
water: activity.includes('shower') ? 'minutes' :
activity.includes('load') ? 'loads' : 'liters'
};
return units[category] || 'units';
}
/**
* Scale emissions to different timeframes
*/
scaleToTimeframe(dailyEmissions, fromTimeframe, toTimeframe) {
const scales = {
daily: 1,
weekly: 7,
monthly: 30.44, // average days per month
annual: 365.25
};
const fromScale = scales[fromTimeframe] || 1;
const toScale = scales[toTimeframe] || 1;
return (dailyEmissions / fromScale) * toScale;
}
/**
* Generate comparisons with averages and targets
*/
generateComparisons(totalEmissions, timeframe) {
const dailyEmissions = this.scaleToTimeframe(totalEmissions, timeframe, 'daily');
const annualEmissions = this.scaleToTimeframe(totalEmissions, timeframe, 'annual');
return {
vsGlobalAverage: {
value: Math.round((dailyEmissions / this.globalAverages.daily) * 100),
message: dailyEmissions > this.globalAverages.daily ? 'above' : 'below'
},
vsSustainableTarget: {
value: Math.round((annualEmissions / this.globalAverages.sustainable) * 100),
message: annualEmissions > this.globalAverages.sustainable ? 'above' : 'below'
},
annualProjection: Math.round(annualEmissions),
dailyAverage: Math.round(dailyEmissions * 100) / 100,
category: this.getCarbonFootprintCategory(annualEmissions)
};
}
/**
* Get carbon footprint category
*/
getCarbonFootprintCategory(annualEmissions) {
if (annualEmissions <= 2300) return 'Excellent';
if (annualEmissions <= 4000) return 'Good';
if (annualEmissions <= 6000) return 'Average';
if (annualEmissions <= 10000) return 'High';
return 'Very High';
}
/**
* Generate personalized recommendations
*/
generateRecommendations(breakdown, totalEmissions) {
const recommendations = [];
// Find highest emission categories
const sortedCategories = Object.keys(breakdown)
.sort((a, b) => breakdown[b].total - breakdown[a].total)
.slice(0, 3);
sortedCategories.forEach(category => {
const categoryEmissions = breakdown[category];
if (categoryEmissions.total > 0) {
const categoryRecs = this.getCategoryRecommendations(category, categoryEmissions);
recommendations.push(...categoryRecs);
}
});
// Add general recommendations based on total emissions
const annualProjection = this.scaleToTimeframe(totalEmissions, 'daily', 'annual');
if (annualProjection > this.globalAverages.sustainable) {
recommendations.push({
category: 'general',
priority: 'high',
action: 'Reduce overall carbon footprint',
impact: `Target reduction: ${Math.round(annualProjection - this.globalAverages.sustainable)} kg CO2e/year`,
difficulty: 'medium'
});
}
return recommendations.slice(0, 8); // Limit to top 8 recommendations
}
/**
* Get category-specific recommendations
*/
getCategoryRecommendations(category, categoryData) {
const recommendations = [];
switch (category) {
case 'transportation':
if (categoryData.activities.car_gasoline?.emissions > 5) {
recommendations.push({
category: 'transportation',
priority: 'high',
action: 'Switch to hybrid or electric vehicle',
impact: 'Reduce emissions by 50-75%',
difficulty: 'high'
});
}
if (categoryData.activities.airplane_domestic?.emissions > 10) {
recommendations.push({
category: 'transportation',
priority: 'medium',
action: 'Reduce air travel or offset flights',
impact: 'Significant emission reduction',
difficulty: 'medium'
});
}
recommendations.push({
category: 'transportation',
priority: 'low',
action: 'Use public transport, bike, or walk more',
impact: 'Reduce daily transport emissions',
difficulty: 'low'
});
break;
case 'energy':
if (categoryData.activities.electricity_grid?.emissions > 8) {
recommendations.push({
category: 'energy',
priority: 'high',
action: 'Switch to renewable energy provider',
impact: 'Reduce home emissions by 80%+',
difficulty: 'low'
});
}
recommendations.push({
category: 'energy',
priority: 'medium',
action: 'Improve home insulation and efficiency',
impact: 'Reduce energy consumption by 20-30%',
difficulty: 'medium'
});
break;
case 'food':
if (categoryData.activities.beef?.emissions > 3) {
recommendations.push({
category: 'food',
priority: 'high',
action: 'Reduce red meat consumption',
impact: 'Major dietary emission reduction',
difficulty: 'medium'
});
}
recommendations.push({
category: 'food',
priority: 'low',
action: 'Eat more plant-based meals',
impact: 'Reduce food emissions by 30-50%',
difficulty: 'low'
});
break;
case 'waste':
recommendations.push({
category: 'waste',
priority: 'low',
action: 'Increase recycling and composting',
impact: 'Reduce waste emissions and create negative emissions',
difficulty: 'low'
});
break;
}
return recommendations;
}
/**
* Calculate trends (mock implementation)
*/
calculateTrends(footprint) {
// In a real implementation, this would use historical data
return {
weekly: this.generateWeeklyTrend(),
monthly: this.generateMonthlyTrend(),
category: this.generateCategoryTrends(footprint.breakdown),
projection: this.generateProjection(footprint.total)
};
}
generateWeeklyTrend() {
const trend = [];
const baseEmission = 15 + Math.random() * 10;
for (let i = 6; i >= 0; i--) {
const date = new Date();
date.setDate(date.getDate() - i);
const variation = (Math.random() - 0.5) * 6;
trend.push({
date: date.toISOString().split('T')[0],
emissions: Math.round((baseEmission + variation) * 100) / 100,
day: date.toLocaleDateString('en-US', { weekday: 'short' })
});
}
return trend;
}
generateMonthlyTrend() {
const trend = [];
const baseEmission = 450 + Math.random() * 200;
for (let i = 11; i >= 0; i--) {
const date = new Date();
date.setMonth(date.getMonth() - i);
const variation = (Math.random() - 0.5) * 100;
trend.push({
month: date.toLocaleDateString('en-US', { month: 'short', year: 'numeric' }),
emissions: Math.round(baseEmission + variation),
change: i === 11 ? 0 : Math.round((Math.random() - 0.5) * 20)
});
}
return trend;
}
generateCategoryTrends(breakdown) {
const trends = {};
Object.keys(breakdown).forEach(category => {
trends[category] = {
current: breakdown[category].total,
trend: Math.random() > 0.5 ? 'increasing' : 'decreasing',
change: Math.round((Math.random() - 0.5) * 20 * 100) / 100
};
});
return trends;
}
generateProjection(currentDaily) {
const annual = this.scaleToTimeframe(currentDaily, 'daily', 'annual');
return {
currentAnnual: Math.round(annual),
projectedReduction: Math.round(annual * 0.15), // 15% reduction potential
targetAnnual: this.globalAverages.sustainable,
yearsToTarget: Math.max(1, Math.ceil((annual - this.globalAverages.sustainable) / (annual * 0.15)))
};
}
/**
* Assess confidence in calculation
*/
assessConfidence(activities) {
let confidence = 90;
// Reduce confidence for missing data
const totalCategories = Object.keys(this.emissionFactors).length;
const providedCategories = Object.keys(activities).length;
if (providedCategories < totalCategories) {
confidence -= (totalCategories - providedCategories) * 5;
}
// Check data completeness within categories
Object.keys(activities).forEach(category => {
const categoryActivities = activities[category];
if (Object.keys(categoryActivities).length < 2) {
confidence -= 5;
}
});
return Math.max(60, Math.min(98, confidence));
}
/**
* Generate sample activities for testing
*/
generateSampleActivities() {
return {
transportation: {
car_gasoline: 25, // miles per day
bus: 5,
walking: 2
},
energy: {
electricity_grid: 30, // kWh per day
natural_gas: 2 // therms per day
},
food: {
chicken: 0.2, // kg per day
vegetables: 0.5,
dairy: 0.3,
grains: 0.4
},
waste: {
landfill: 1.5, // kg per day
recycling: 0.8
},
water: {
shower: 10, // minutes per day
tap_water: 8 // liters per day
}
};
}
/**
* Calculate offset recommendations
*/
calculateOffsetRecommendations(annualEmissions) {
const offsetOptions = [
{
type: 'Forest Conservation',
costPerTon: 15,
description: 'Protect existing forests from deforestation',
certification: 'VCS, REDD+'
},
{
type: 'Renewable Energy',
costPerTon: 25,
description: 'Support wind and solar energy projects',
certification: 'Gold Standard, VCS'
},
{
type: 'Reforestation',
costPerTon: 20,
description: 'Plant new trees and restore forests',
certification: 'VCS, CDM'
},
{
type: 'Direct Air Capture',
costPerTon: 150,
description: 'Remove CO2 directly from atmosphere',
certification: 'Emerging technology'
}
];
const emissionsToOffset = Math.round(annualEmissions);
return offsetOptions.map(option => ({
...option,
annualCost: Math.round(emissionsToOffset * option.costPerTon),
monthlyCost: Math.round((emissionsToOffset * option.costPerTon) / 12),
tonsToOffset: emissionsToOffset
}));
}
}
// Create singleton instance
export const carbonFootprintTracker = new CarbonFootprintTracker();
// Export main calculation function
export const calculateCarbonFootprint = async (activities, timeframe = 'daily') => {
try {
return await carbonFootprintTracker.calculateCarbonFootprint(activities, timeframe);
} catch (error) {
console.error('Carbon footprint calculation error:', error);
throw error;
}
};
// Export sample data generator
export const generateSampleCarbonData = () => {
return carbonFootprintTracker.generateSampleActivities();
};
export default carbonFootprintTracker;