// Constants for carbon calculations const EMISSION_FACTOR = 3.206; // tons of CO₂ per ton of fuel const FUEL_DENSITY = 0.85; // tons per m³ (or metric tons per kiloliter) const GALLONS_TO_LITERS = 3.78541; // 1 US gallon = 3.78541 liters const LITERS_TO_CUBIC_METERS = 0.001; // 1 liter = 0.001 m³ // Available currencies const currencies = { USD: { code: 'USD', symbol: '$', rate: 1 }, EUR: { code: 'EUR', symbol: '€', rate: 0.92 }, GBP: { code: 'GBP', symbol: '£', rate: 0.79 }, CHF: { code: 'CHF', symbol: 'CHF', rate: 0.88 }, }; // Format currency function formatCurrency(amountUSD, currency) { if (!currency) { currency = currencies.USD; } // Convert USD amount to target currency const convertedAmount = amountUSD * currency.rate; return `${currency.symbol}${convertedAmount.toLocaleString(undefined, { minimumFractionDigits: 0, maximumFractionDigits: 0, })}`; } // Get currency by code function getCurrencyByCode(code) { return currencies[code] || currencies.USD; } // Calculate trip carbon function calculateTripCarbon(vesselData, distance, speed, fuelRateLitersPerHour) { const tripHours = distance / speed; // Calculate total fuel consumption in liters const fuelConsumptionLiters = fuelRateLitersPerHour * tripHours; // Convert liters to tons for CO₂ calculation const fuelConsumptionTons = (fuelConsumptionLiters * LITERS_TO_CUBIC_METERS) * FUEL_DENSITY; // Calculate CO₂ emissions const fuelRateTonsPerHour = (fuelRateLitersPerHour * LITERS_TO_CUBIC_METERS) * FUEL_DENSITY; const emissionsPerNM = (fuelRateTonsPerHour * EMISSION_FACTOR) / speed; const totalEmissions = emissionsPerNM * distance; return { distance, duration: tripHours, fuelConsumption: Math.round(fuelConsumptionLiters), co2Emissions: Number(totalEmissions.toFixed(2)) }; } // Calculate carbon from fuel function calculateCarbonFromFuel(fuelAmount, isGallons = false) { // Convert to liters if input is in gallons const liters = isGallons ? fuelAmount * GALLONS_TO_LITERS : fuelAmount; // Convert liters to cubic meters (m³) const cubicMeters = liters * LITERS_TO_CUBIC_METERS; // Convert volume to mass (tons) const fuelTons = cubicMeters * FUEL_DENSITY; // Calculate CO₂ emissions const co2Emissions = fuelTons * EMISSION_FACTOR; return Number(co2Emissions.toFixed(2)); } // Sample vessel data const sampleVessel = { imo: '1234567', vesselName: 'Sample Yacht', type: 'Yacht', length: 50, width: 9, estimatedEnginePower: 2250 }; // Default portfolio for fallback const DEFAULT_PORTFOLIO = { id: 1, name: "Puffin Maritime Portfolio", description: "A curated selection of high-impact carbon removal projects focused on maritime sustainability.", projects: [ { id: "dac-1", name: "Direct Air Capture", description: "Permanent carbon removal through direct air capture technology", shortDescription: "Direct air capture in Iceland", imageUrl: "https://images.unsplash.com/photo-1553547274-0df401ae03c9", pricePerTon: 200, location: "Iceland", type: "Direct Air Capture", verificationStandard: "Verified Carbon Standard", impactMetrics: { co2Reduced: 1000 } }, { id: "ocean-1", name: "Ocean Carbon Removal", description: "Enhanced ocean carbon capture through marine permaculture", shortDescription: "Marine carbon capture", imageUrl: "https://images.unsplash.com/photo-1498623116890-37e912163d5d", pricePerTon: 200, location: "Global Oceans", type: "Ocean-Based", verificationStandard: "Gold Standard", impactMetrics: { co2Reduced: 5000 } } ], pricePerTon: 200, currency: 'USD' }; // Simplified analytics const analytics = { pageView: function(path) { console.log(`Analytics pageView: ${path}`); }, event: function(category, action, label) { console.log(`Analytics event: ${category} - ${action} - ${label}`); }, error: function(error, message) { console.error(`Analytics error: ${message}`, error); } }; // Create portfolio API call (with fallback to default) async function getPortfolios() { try { // In a real implementation, this would be an API call // For demo purposes, we'll just return the default portfolio after a small delay return new Promise((resolve) => { setTimeout(() => resolve([DEFAULT_PORTFOLIO]), 1000); }); } catch (error) { console.warn('Failed to fetch portfolios from API, using fallback'); return [DEFAULT_PORTFOLIO]; } } // Create offset order API call (simulated) async function createOffsetOrder(portfolioId, tons, dryRun = false) { try { // Simulate API call return new Promise((resolve) => { setTimeout(() => { resolve({ id: `order-${Math.floor(Math.random() * 1000000)}`, amountCharged: tons * 200 * 100, // in cents currency: 'USD', tons: tons, portfolio: DEFAULT_PORTFOLIO, status: 'completed', createdAt: new Date().toISOString(), dryRun: dryRun }); }, 1500); }); } catch (error) { console.error('Failed to create offset order', error); throw new Error('Failed to create offset order. Please try again.'); } } // Email validation function validateEmail(email) { const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/; return emailRegex.test(email); } // Send form submission (simulated) async function sendFormSubmission(data) { return new Promise((resolve) => { setTimeout(() => resolve({ success: true }), 1000); }); }