No analysis results available. Please enter project details and click "Calculate Profitability".
`;
return;
}
const isProfitable = results.npv > 0;
const npvColorClass = isProfitable ? 'text-green-700' : 'text-red-700';
let tableHtml = `
Summary of Financial & Environmental Impact
Project Type: ${projectTypeSelect.value}
Initial Investment: $${results.initialInvestment.toLocaleString(undefined, { minimumFractionDigits: 2, maximumFractionDigits: 2 })}
Project Lifespan: ${results.projectLifespan} Years
Discount Rate: ${results.discountRate * 100}%
Annual Inflation Rate: ${results.inflationRate * 100}%
| Metric |
Value |
| Total Project Revenue: |
$${results.totalRevenue.toLocaleString(undefined, { minimumFractionDigits: 2, maximumFractionDigits: 2 })} |
| Total Project Costs (incl. investment): |
$${results.totalCosts.toLocaleString(undefined, { minimumFractionDigits: 2, maximumFractionDigits: 2 })} |
| Net Profit (Total Revenue - Total Costs): |
$${results.netProfit.toLocaleString(undefined, { minimumFractionDigits: 2, maximumFractionDigits: 2 })} |
| Net Present Value (NPV): |
$${results.npv.toLocaleString(undefined, { minimumFractionDigits: 2, maximumFractionDigits: 2 })}
${isProfitable ? '' : ''}
|
| Payback Period: |
${results.paybackPeriod === Infinity ? 'Never' : results.paybackPeriod.toFixed(2) + ' Years'}
|
| Total Carbon Abated (Estimated): |
${results.totalCarbonAbated.toFixed(2)} tonnes COâ‚‚e |
NPV (Net Present Value): A positive NPV indicates that the project is expected to generate more value than it costs, after accounting for the time value of money.
Payback Period: The time it takes for the cumulative cash flows to equal the initial investment. A shorter payback period is generally preferred.
Disclaimer: This tool provides *simulated* profitability calculations for educational and illustrative purposes only. It should not be used for real financial decisions. Real-world projects involve numerous additional factors, risks, and complexities not captured here.
`;
resultsOutput.innerHTML = tableHtml;
}
/**
* Renders the cumulative cash flow chart.
* @param {Object} results - Results from calculateProfitability.
*/
function renderCashFlowChart(results) {
if (!results || !results.cumulativeCashFlows || results.cumulativeCashFlows.length === 0) {
chartPlaceholder.classList.remove('hidden');
if (cashFlowChartInstance) {
cashFlowChartInstance.destroy();
cashFlowChartInstance = null;
}
return;
}
chartPlaceholder.classList.add('hidden'); // Hide placeholder if chart can be rendered
const ctx = document.getElementById('cashFlowChart').getContext('2d');
// Destroy existing chart instance if it exists to prevent overlap
if (cashFlowChartInstance) {
cashFlowChartInstance.destroy();
}
const years = Array.from({ length: results.projectLifespan + 1 }, (_, i) => `Year ${i}`);
years[0] = 'Year 0 (Investment)'; // Label for initial investment
cashFlowChartInstance = new Chart(ctx, {
type: 'line',
data: {
labels: years,
datasets: [
{
label: 'Cumulative Cash Flow ($)',
data: results.cumulativeCashFlows,
borderColor: '#3B82F6', // Blue 500
backgroundColor: 'rgba(59, 130, 246, 0.2)', // Light blue fill
borderWidth: 2,
tension: 0.3, // Smooth curve
pointRadius: 3,
fill: false,
}
]
},
options: {
responsive: true,
maintainAspectRatio: false,
plugins: {
legend: {
display: true,
position: 'top',
labels: {
font: {
size: 14,
family: 'Inter',
},
color: '#333'
}
},
title: {
display: true,
text: 'Cumulative Cash Flow Over Project Lifespan',
font: {
size: 18,
family: 'Inter',
weight: 'bold'
},
color: '#1F2937'
},
tooltip: {
mode: 'index',
intersect: false,
callbacks: {
label: function(context) {
let label = context.dataset.label || '';
if (label) {
label += ': ';
}
if (context.parsed.y !== null) {
label += `$${parseFloat(context.parsed.y).toLocaleString(undefined, { minimumFractionDigits: 2, maximumFractionDigits: 2 })}`;
}
return label;
}
}
}
},
scales: {
y: {
beginAtZero: false,
title: {
display: true,
text: 'Cumulative Cash Flow ($)',
font: {
size: 14,
family: 'Inter'
},
color: '#333'
},
ticks: {
callback: function(value) {
return '$' + value.toLocaleString();
},
font: { family: 'Inter' }
}
},
x: {
title: {
display: true,
text: 'Year',
font: {
size: 14,
family: 'Inter'
},
color: '#333'
},
ticks: { font: { family: 'Inter' } }
}
}
}
});
}
/**
* Handles the PDF download functionality.
* Captures the results output and chart canvases to generate a PDF report.
*/
window.downloadPdf = async function() {
if (typeof html2canvas === 'undefined' || typeof jspdf === 'undefined' || typeof jspdf.jsPDF === 'undefined') {
displayMessage('PDF generation libraries not loaded. Please try again or refresh.');
return;
}
hideMessage();
const { jsPDF } = jspdf;
const doc = new jsPDF('p', 'pt', 'a4');
const elementsToCapture = [
document.getElementById('resultsOutput'),
document.getElementById('cashFlowChart')
];
let yPos = 40;
doc.setFontSize(22);
doc.setTextColor(51, 51, 51);
doc.text('Renewable Energy Investment Profitability Report', doc.internal.pageSize.getWidth() / 2, yPos, { align: 'center' });
yPos += 30;
doc.setFontSize(12);
doc.setTextColor(100, 100, 100);
doc.text(`Generated on: ${new Date().toLocaleDateString()}`, doc.internal.pageSize.getWidth() / 2, yPos, { align: 'center' });
yPos += 40;
for (const element of elementsToCapture) {
try {
const wasHidden = element.classList.contains('hidden');
if (wasHidden) {
element.classList.remove('hidden');
}
// For charts, ensure they are rendered before capturing
if (element.id === 'cashFlowChart' && cashFlowChartInstance === null) {
console.warn("Chart not yet rendered for PDF capture. Skipping chart section.");
if (wasHidden) { element.classList.add('hidden'); }
continue;
}
const canvas = await html2canvas(element, {
scale: 2,
useCORS: true,
backgroundColor: '#ffffff'
});
if (wasHidden) {
element.classList.add('hidden');
}
const imgData = canvas.toDataURL('image/png');
const imgWidth = 550; // Desired width for image in PDF
const imgHeight = (canvas.height * imgWidth) / canvas.width;
if (yPos + imgHeight > doc.internal.pageSize.getHeight() - 40) {
doc.addPage();
yPos = 40;
}
doc.addImage(imgData, 'PNG', (doc.internal.pageSize.getWidth() - imgWidth) / 2, yPos, imgWidth, imgHeight);
yPos += imgHeight + 30;
} catch (error) {
console.error('Error capturing element for PDF:', error);
displayMessage('Failed to generate part of the PDF. Please ensure all data is loaded and visible before downloading.');
}
}
doc.save('Renewable_Energy_Profitability_Report.pdf');
};
// Initial setup: Load default values for the first project type and show the input tab
loadDefaultValues();
showTab('input');
});