GreenPlusbyGXS / web /src /utils /advancedAnalytics.js
gaialive's picture
Upload 106 files
759768a verified
// Advanced Analytics System for EcoSpire
class AdvancedAnalytics {
constructor() {
this.cache = new Map();
this.cacheTimeout = 10 * 60 * 1000; // 10 minutes
}
// Environmental Impact Analysis
async calculateEnvironmentalImpact(userData) {
try {
const impact = {
carbonFootprint: this.calculateCarbonFootprint(userData),
waterUsage: this.calculateWaterUsage(userData),
wasteGeneration: this.calculateWasteGeneration(userData),
energyConsumption: this.calculateEnergyConsumption(userData),
biodiversityImpact: this.calculateBiodiversityImpact(userData),
overallScore: 0
};
// Calculate overall environmental score (0-100)
impact.overallScore = this.calculateOverallScore(impact);
// Generate recommendations
impact.recommendations = this.generateRecommendations(impact);
// Calculate trends
impact.trends = await this.calculateTrends(userData);
return impact;
} catch (error) {
console.error('Failed to calculate environmental impact:', error);
return this.getDefaultImpact();
}
}
calculateCarbonFootprint(userData) {
const activities = userData.activities || [];
let totalCarbon = 0;
const breakdown = {
transportation: 0,
energy: 0,
food: 0,
waste: 0,
other: 0
};
activities.forEach(activity => {
const carbon = this.getActivityCarbon(activity);
totalCarbon += carbon.amount;
breakdown[carbon.category] += carbon.amount;
});
return {
total: Math.round(totalCarbon * 100) / 100,
breakdown: breakdown,
comparison: {
globalAverage: 4800, // kg CO2/year
countryAverage: 16000, // kg CO2/year (US)
target: 2300 // kg CO2/year (Paris Agreement target)
},
trend: this.calculateCarbonTrend(activities)
};
}
getActivityCarbon(activity) {
const carbonFactors = {
// Transportation (kg CO2 per unit)
'car_gasoline': { factor: 0.404, unit: 'km', category: 'transportation' },
'car_electric': { factor: 0.053, unit: 'km', category: 'transportation' },
'bus': { factor: 0.089, unit: 'km', category: 'transportation' },
'train': { factor: 0.041, unit: 'km', category: 'transportation' },
'flight_domestic': { factor: 0.255, unit: 'km', category: 'transportation' },
'flight_international': { factor: 0.195, unit: 'km', category: 'transportation' },
// Energy (kg CO2 per kWh)
'electricity_grid': { factor: 0.475, unit: 'kWh', category: 'energy' },
'electricity_renewable': { factor: 0.024, unit: 'kWh', category: 'energy' },
'natural_gas': { factor: 0.202, unit: 'kWh', category: 'energy' },
'heating_oil': { factor: 0.264, unit: 'kWh', category: 'energy' },
// Food (kg CO2 per kg)
'beef': { factor: 60.0, unit: 'kg', category: 'food' },
'lamb': { factor: 24.0, unit: 'kg', category: 'food' },
'pork': { factor: 7.0, unit: 'kg', category: 'food' },
'chicken': { factor: 6.0, unit: 'kg', category: 'food' },
'fish': { factor: 5.0, unit: 'kg', category: 'food' },
'dairy': { factor: 3.2, unit: 'kg', category: 'food' },
'vegetables': { factor: 2.0, unit: 'kg', category: 'food' },
'fruits': { factor: 1.1, unit: 'kg', category: 'food' },
// Waste (kg CO2 per kg)
'landfill_waste': { factor: 0.57, unit: 'kg', category: 'waste' },
'recycled_waste': { factor: -0.3, unit: 'kg', category: 'waste' },
'composted_waste': { factor: -0.1, unit: 'kg', category: 'waste' }
};
const factor = carbonFactors[activity.type] || { factor: 0, category: 'other' };
return {
amount: (activity.amount || 0) * factor.factor,
category: factor.category
};
}
calculateWaterUsage(userData) {
const activities = userData.activities || [];
let totalWater = 0;
const breakdown = {
domestic: 0,
food: 0,
energy: 0,
transportation: 0,
other: 0
};
// Water footprint calculations (liters per unit)
const waterFactors = {
'shower': { factor: 65, unit: 'minute', category: 'domestic' },
'bath': { factor: 150, unit: 'bath', category: 'domestic' },
'dishwasher': { factor: 15, unit: 'cycle', category: 'domestic' },
'washing_machine': { factor: 50, unit: 'cycle', category: 'domestic' },
'beef': { factor: 15400, unit: 'kg', category: 'food' },
'pork': { factor: 6000, unit: 'kg', category: 'food' },
'chicken': { factor: 4300, unit: 'kg', category: 'food' },
'vegetables': { factor: 322, unit: 'kg', category: 'food' },
'electricity': { factor: 1.4, unit: 'kWh', category: 'energy' }
};
activities.forEach(activity => {
const factor = waterFactors[activity.type];
if (factor) {
const water = (activity.amount || 0) * factor.factor;
totalWater += water;
breakdown[factor.category] += water;
}
});
return {
total: Math.round(totalWater),
breakdown: breakdown,
comparison: {
globalAverage: 1385000, // liters/year
countryAverage: 2842000, // liters/year (US)
target: 1000000 // liters/year (sustainable target)
}
};
}
calculateWasteGeneration(userData) {
const activities = userData.activities || [];
let totalWaste = 0;
const breakdown = {
landfill: 0,
recycled: 0,
composted: 0,
hazardous: 0
};
activities.forEach(activity => {
if (activity.type.includes('waste')) {
const amount = activity.amount || 0;
totalWaste += amount;
if (activity.type.includes('recycled')) {
breakdown.recycled += amount;
} else if (activity.type.includes('composted')) {
breakdown.composted += amount;
} else if (activity.type.includes('hazardous')) {
breakdown.hazardous += amount;
} else {
breakdown.landfill += amount;
}
}
});
const recyclingRate = totalWaste > 0 ? (breakdown.recycled + breakdown.composted) / totalWaste * 100 : 0;
return {
total: Math.round(totalWaste * 100) / 100,
breakdown: breakdown,
recyclingRate: Math.round(recyclingRate * 100) / 100,
comparison: {
globalAverage: 740, // kg/year
countryAverage: 811, // kg/year (US)
target: 400 // kg/year (sustainable target)
}
};
}
calculateEnergyConsumption(userData) {
const activities = userData.activities || [];
let totalEnergy = 0;
const breakdown = {
heating: 0,
cooling: 0,
appliances: 0,
lighting: 0,
transportation: 0,
other: 0
};
// Energy consumption factors (kWh per unit)
const energyFactors = {
'heating': { factor: 15, unit: 'day', category: 'heating' },
'cooling': { factor: 12, unit: 'day', category: 'cooling' },
'refrigerator': { factor: 1.5, unit: 'day', category: 'appliances' },
'washing_machine': { factor: 2.3, unit: 'cycle', category: 'appliances' },
'dishwasher': { factor: 1.8, unit: 'cycle', category: 'appliances' },
'led_lighting': { factor: 0.01, unit: 'hour', category: 'lighting' },
'incandescent_lighting': { factor: 0.06, unit: 'hour', category: 'lighting' },
'car_electric': { factor: 0.2, unit: 'km', category: 'transportation' }
};
activities.forEach(activity => {
const factor = energyFactors[activity.type];
if (factor) {
const energy = (activity.amount || 0) * factor.factor;
totalEnergy += energy;
breakdown[factor.category] += energy;
}
});
const renewablePercentage = this.calculateRenewablePercentage(userData);
return {
total: Math.round(totalEnergy * 100) / 100,
breakdown: breakdown,
renewablePercentage: renewablePercentage,
comparison: {
globalAverage: 3500, // kWh/year
countryAverage: 10500, // kWh/year (US)
target: 2000 // kWh/year (sustainable target)
}
};
}
calculateBiodiversityImpact(userData) {
const activities = userData.activities || [];
let positiveImpact = 0;
let negativeImpact = 0;
// Biodiversity impact factors
const biodiversityFactors = {
'tree_planting': { factor: 10, type: 'positive' },
'native_gardening': { factor: 5, type: 'positive' },
'habitat_restoration': { factor: 15, type: 'positive' },
'pesticide_use': { factor: -8, type: 'negative' },
'land_clearing': { factor: -20, type: 'negative' },
'invasive_species_removal': { factor: 8, type: 'positive' },
'wildlife_feeding': { factor: 3, type: 'positive' },
'composting': { factor: 2, type: 'positive' }
};
activities.forEach(activity => {
const factor = biodiversityFactors[activity.type];
if (factor) {
const impact = (activity.amount || 0) * factor.factor;
if (factor.type === 'positive') {
positiveImpact += impact;
} else {
negativeImpact += Math.abs(impact);
}
}
});
const netImpact = positiveImpact - negativeImpact;
return {
positive: Math.round(positiveImpact * 100) / 100,
negative: Math.round(negativeImpact * 100) / 100,
net: Math.round(netImpact * 100) / 100,
score: Math.max(0, Math.min(100, 50 + netImpact * 2)) // Scale to 0-100
};
}
calculateOverallScore(impact) {
// Weighted scoring system (0-100)
const weights = {
carbon: 0.3,
water: 0.2,
waste: 0.2,
energy: 0.2,
biodiversity: 0.1
};
let score = 0;
// Carbon score (lower is better)
const carbonScore = Math.max(0, 100 - (impact.carbonFootprint.total / impact.carbonFootprint.comparison.target * 100));
score += carbonScore * weights.carbon;
// Water score (lower is better)
const waterScore = Math.max(0, 100 - (impact.waterUsage.total / impact.waterUsage.comparison.target * 100));
score += waterScore * weights.water;
// Waste score (higher recycling rate is better)
const wasteScore = impact.wasteGeneration.recyclingRate;
score += wasteScore * weights.waste;
// Energy score (lower consumption + higher renewable percentage is better)
const energyScore = Math.max(0, 100 - (impact.energyConsumption.total / impact.energyConsumption.comparison.target * 100)) * 0.7 +
impact.energyConsumption.renewablePercentage * 0.3;
score += energyScore * weights.energy;
// Biodiversity score
score += impact.biodiversityImpact.score * weights.biodiversity;
return Math.round(Math.max(0, Math.min(100, score)));
}
generateRecommendations(impact) {
const recommendations = [];
// Carbon recommendations
if (impact.carbonFootprint.total > impact.carbonFootprint.comparison.target) {
if (impact.carbonFootprint.breakdown.transportation > impact.carbonFootprint.total * 0.4) {
recommendations.push({
category: 'Transportation',
priority: 'high',
action: 'Switch to electric vehicle or use public transport',
potential: `Save ${Math.round((impact.carbonFootprint.breakdown.transportation * 0.6))} kg CO₂/year`,
difficulty: 'medium'
});
}
if (impact.carbonFootprint.breakdown.energy > impact.carbonFootprint.total * 0.3) {
recommendations.push({
category: 'Energy',
priority: 'high',
action: 'Switch to renewable energy provider',
potential: `Save ${Math.round((impact.carbonFootprint.breakdown.energy * 0.8))} kg CO₂/year`,
difficulty: 'easy'
});
}
}
// Water recommendations
if (impact.waterUsage.total > impact.waterUsage.comparison.target) {
recommendations.push({
category: 'Water',
priority: 'medium',
action: 'Install low-flow fixtures and fix leaks',
potential: `Save ${Math.round((impact.waterUsage.total * 0.2))} liters/year`,
difficulty: 'easy'
});
}
// Waste recommendations
if (impact.wasteGeneration.recyclingRate < 50) {
recommendations.push({
category: 'Waste',
priority: 'medium',
action: 'Increase recycling and composting',
potential: `Divert ${Math.round((impact.wasteGeneration.breakdown.landfill * 0.6))} kg from landfill`,
difficulty: 'easy'
});
}
// Biodiversity recommendations
if (impact.biodiversityImpact.net < 10) {
recommendations.push({
category: 'Biodiversity',
priority: 'low',
action: 'Plant native species or create wildlife habitat',
potential: 'Improve local ecosystem health',
difficulty: 'medium'
});
}
return recommendations.sort((a, b) => {
const priorityOrder = { high: 3, medium: 2, low: 1 };
return priorityOrder[b.priority] - priorityOrder[a.priority];
});
}
async calculateTrends(userData) {
// Calculate trends over time
const activities = userData.activities || [];
const monthlyData = this.groupActivitiesByMonth(activities);
return {
carbon: this.calculateTrendDirection(monthlyData, 'carbon'),
water: this.calculateTrendDirection(monthlyData, 'water'),
waste: this.calculateTrendDirection(monthlyData, 'waste'),
energy: this.calculateTrendDirection(monthlyData, 'energy')
};
}
groupActivitiesByMonth(activities) {
const grouped = {};
activities.forEach(activity => {
const date = new Date(activity.timestamp || Date.now());
const monthKey = `${date.getFullYear()}-${date.getMonth()}`;
if (!grouped[monthKey]) {
grouped[monthKey] = [];
}
grouped[monthKey].push(activity);
});
return grouped;
}
calculateTrendDirection(monthlyData, category) {
const months = Object.keys(monthlyData).sort();
if (months.length < 2) return 'insufficient_data';
const values = months.map(month => {
const activities = monthlyData[month];
return this.calculateCategoryTotal(activities, category);
});
const firstHalf = values.slice(0, Math.floor(values.length / 2));
const secondHalf = values.slice(Math.floor(values.length / 2));
const firstAvg = firstHalf.reduce((a, b) => a + b, 0) / firstHalf.length;
const secondAvg = secondHalf.reduce((a, b) => a + b, 0) / secondHalf.length;
const change = ((secondAvg - firstAvg) / firstAvg) * 100;
if (Math.abs(change) < 5) return 'stable';
return change > 0 ? 'increasing' : 'decreasing';
}
calculateCategoryTotal(activities, category) {
return activities.reduce((total, activity) => {
const carbon = this.getActivityCarbon(activity);
if (carbon.category === category) {
return total + carbon.amount;
}
return total;
}, 0);
}
calculateRenewablePercentage(userData) {
// Calculate percentage of energy from renewable sources
const energyActivities = userData.activities?.filter(a => a.type.includes('electricity')) || [];
const renewableActivities = energyActivities.filter(a => a.type.includes('renewable'));
if (energyActivities.length === 0) return 0;
const totalEnergy = energyActivities.reduce((sum, a) => sum + (a.amount || 0), 0);
const renewableEnergy = renewableActivities.reduce((sum, a) => sum + (a.amount || 0), 0);
return totalEnergy > 0 ? Math.round((renewableEnergy / totalEnergy) * 100) : 0;
}
calculateCarbonTrend(activities) {
// Simple trend calculation
const recentActivities = activities.slice(-30); // Last 30 activities
const olderActivities = activities.slice(-60, -30); // Previous 30 activities
if (recentActivities.length === 0 || olderActivities.length === 0) {
return 'insufficient_data';
}
const recentCarbon = recentActivities.reduce((sum, a) => sum + this.getActivityCarbon(a).amount, 0);
const olderCarbon = olderActivities.reduce((sum, a) => sum + this.getActivityCarbon(a).amount, 0);
const change = ((recentCarbon - olderCarbon) / olderCarbon) * 100;
if (Math.abs(change) < 5) return 'stable';
return change > 0 ? 'increasing' : 'decreasing';
}
getDefaultImpact() {
return {
carbonFootprint: { total: 0, breakdown: {}, comparison: {}, trend: 'unknown' },
waterUsage: { total: 0, breakdown: {}, comparison: {} },
wasteGeneration: { total: 0, breakdown: {}, recyclingRate: 0, comparison: {} },
energyConsumption: { total: 0, breakdown: {}, renewablePercentage: 0, comparison: {} },
biodiversityImpact: { positive: 0, negative: 0, net: 0, score: 50 },
overallScore: 0,
recommendations: [],
trends: {}
};
}
// Predictive Analytics
async predictFutureImpact(userData, timeframe = 12) {
const currentImpact = await this.calculateEnvironmentalImpact(userData);
const trends = currentImpact.trends;
const predictions = {
carbon: this.predictValue(currentImpact.carbonFootprint.total, trends.carbon, timeframe),
water: this.predictValue(currentImpact.waterUsage.total, trends.water, timeframe),
waste: this.predictValue(currentImpact.wasteGeneration.total, trends.waste, timeframe),
energy: this.predictValue(currentImpact.energyConsumption.total, trends.energy, timeframe)
};
return {
timeframe: `${timeframe} months`,
predictions: predictions,
confidence: this.calculatePredictionConfidence(userData),
recommendations: this.generatePredictiveRecommendations(predictions, currentImpact)
};
}
predictValue(currentValue, trend, months) {
const trendMultipliers = {
'increasing': 1.05, // 5% increase per month
'decreasing': 0.95, // 5% decrease per month
'stable': 1.0,
'insufficient_data': 1.0,
'unknown': 1.0
};
const multiplier = trendMultipliers[trend] || 1.0;
return Math.round(currentValue * Math.pow(multiplier, months) * 100) / 100;
}
calculatePredictionConfidence(userData) {
const activities = userData.activities || [];
const dataPoints = activities.length;
const timeSpan = this.calculateTimeSpan(activities);
if (dataPoints < 10) return 'low';
if (dataPoints < 50 || timeSpan < 30) return 'medium';
return 'high';
}
calculateTimeSpan(activities) {
if (activities.length === 0) return 0;
const timestamps = activities.map(a => new Date(a.timestamp || Date.now()).getTime());
const earliest = Math.min(...timestamps);
const latest = Math.max(...timestamps);
return Math.floor((latest - earliest) / (1000 * 60 * 60 * 24)); // Days
}
generatePredictiveRecommendations(predictions, currentImpact) {
const recommendations = [];
// Check if predictions exceed targets
if (predictions.carbon > currentImpact.carbonFootprint.comparison.target) {
recommendations.push({
category: 'Carbon',
urgency: 'high',
action: 'Implement carbon reduction strategies now to avoid exceeding targets',
timeline: 'immediate'
});
}
if (predictions.water > currentImpact.waterUsage.comparison.target) {
recommendations.push({
category: 'Water',
urgency: 'medium',
action: 'Implement water conservation measures',
timeline: '3 months'
});
}
return recommendations;
}
}
export const advancedAnalytics = new AdvancedAnalytics();
export default advancedAnalytics;