Value comparison chart will appear here.
';
return;
}
const i = edirevs_results.inputs;
const p = edirevs_results.projections;
const valueChangeClass = p.valueChangeAbsolute >= 0 ? 'edirevs_highlight_positive' : 'edirevs_highlight_negative';
resultsArea.innerHTML = `
Valuation Impact Summary
Original Market Value: ${edirevs_formatCurrency(i.currentValue)}
Original NOI: ${edirevs_formatCurrency(i.currentNOI)}
Original Cap Rate: ${edirevs_formatPercent(i.currentCapRate)}
Projected Downturn NOI: ${edirevs_formatCurrency(p.projectedNOI)}
Projected Downturn Market Cap Rate: ${edirevs_formatPercent(p.projectedCapRate)}
Projected New Market Value: ${edirevs_formatCurrency(p.projectedValue)}
Change in Value (Absolute): ${edirevs_formatCurrency(p.valueChangeAbsolute)}
Change in Value (Percentage): ${edirevs_formatPercent(p.valueChangePercent)}
`;
// Simple Bar Chart for Value Comparison
const originalValue = i.currentValue;
const projectedValue = p.projectedValue;
const maxVal = Math.max(originalValue, projectedValue, 0);
const barHeight = 150; //px
const originalBarHeight = maxVal > 0 ? (originalValue / maxVal) * barHeight : 0;
const projectedBarHeight = maxVal > 0 ? (projectedValue / maxVal) * barHeight : 0;
chartContainer.innerHTML = `
Value Comparison
Original Value: ${edirevs_formatCurrency(originalValue)}
Original
Projected Value: ${edirevs_formatCurrency(projectedValue)}
Projected
{/* Y-axis line */}
${edirevs_formatCurrency(maxVal,0)}
$0
`;
const pdfBtn = document.getElementById('edirevs_downloadPdfButton');
if(pdfBtn) pdfBtn.style.display = 'block';
}
// --- PDF Generation ---
function edirevs_downloadPDF() {
if (!edirevs_results) { alert("Please calculate results first."); return; }
if (typeof window.jspdf === 'undefined' || typeof window.jspdf.jsPDF === 'undefined') {
alert('Core PDF library (jsPDF) is not loaded.'); console.error('jsPDF library not found.'); return;
}
const { jsPDF: JSPDF } = window.jspdf;
const doc = new JSPDF();
if (typeof doc.autoTable !== 'function') {
alert('PDF Table plugin (jsPDF-AutoTable) not loaded. Tables may be missing.');
console.error('doc.autoTable is not a function.');
}
let y = 15; const m = 15; const cw = doc.internal.pageSize.getWidth() - (2 * m);
const i = edirevs_results.inputs;
const p = edirevs_results.projections;
function addLine(text, size, style = 'normal', indent = 0, spacing = 2.5) {
if (y > 275) { doc.addPage(); y = m; }
doc.setFontSize(size); doc.setFont(undefined, style);
const lines = doc.splitTextToSize(text, cw - indent); doc.text(lines, m + indent, y);
y += (lines.length * (size * 0.35)) + spacing;
}
addLine(`Economic Downturn Impact - Real Estate Valuation`, 16, 'bold', 0, 5);
addLine(`Property Type: ${i.propertyType}`, 10);
y += 3;
addLine("Baseline Data:", 12, 'bold', 0, 3);
let baselineData = [
["Current Market Value:", edirevs_formatCurrency(i.currentValue)],
["Current Annual NOI:", edirevs_formatCurrency(i.currentNOI)],
["Implied Current Cap Rate:", edirevs_formatPercent(i.currentCapRate)],
];
if (typeof doc.autoTable === 'function') doc.autoTable({ startY: y, body: baselineData, theme: 'plain', styles: {fontSize: 9, cellPadding: 1}, columnStyles: {0:{fontStyle:'bold'}}});
else baselineData.forEach(row => addLine(`${row[0]} ${row[1]}`, 9));
y = typeof doc.autoTable === 'function' ? doc.lastAutoTable.finalY + 6 : y + baselineData.length * 5;
addLine("Downturn Scenario Assumptions:", 12, 'bold', 0, 3);
let scenarioData = [
["Change in Gross Rental Income:", edirevs_formatPercent(i.rentChangePercent)],
["Change in Vacancy Rate:", `${i.vacancyChangePoints > 0 ? '+' : ''}${i.vacancyChangePoints.toFixed(1)} pp`],
["Change in Operating Expenses:", edirevs_formatPercent(i.opExChangePercent)],
["Change in Market Cap Rate:", `${i.capRateChangePoints > 0 ? '+' : ''}${i.capRateChangePoints.toFixed(2)} pp`],
];
if (typeof doc.autoTable === 'function') doc.autoTable({ startY: y, body: scenarioData, theme: 'plain', styles: {fontSize: 9, cellPadding: 1}, columnStyles: {0:{fontStyle:'bold'}}});
else scenarioData.forEach(row => addLine(`${row[0]} ${row[1]}`, 9));
y = typeof doc.autoTable === 'function' ? doc.lastAutoTable.finalY + 6 : y + scenarioData.length * 5;
addLine("Projected Impact:", 14, 'bold', 0, 4);
let impactData = [
["Projected Downturn NOI:", edirevs_formatCurrency(p.projectedNOI)],
["Projected Downturn Market Cap Rate:", edirevs_formatPercent(p.projectedCapRate)],
[{content: "Projected New Market Value:", styles:{fontStyle:'bold'}}, {content: edirevs_formatCurrency(p.projectedValue), styles:{fontStyle:'bold'}}],
["Change in Value (Absolute):", edirevs_formatCurrency(p.valueChangeAbsolute)],
["Change in Value (Percentage):", edirevs_formatPercent(p.valueChangePercent)],
];
if (typeof doc.autoTable === 'function') doc.autoTable({ startY: y, body: impactData, theme: 'grid', headStyles:{fillColor:[217,83,79]}, styles: {fontSize: 9, cellPadding: 2}, columnStyles: {0:{fontStyle:'bold'}}});
else impactData.forEach(row => addLine(`${row[0]} ${row[1]}`, 9));
y = typeof doc.autoTable === 'function' ? doc.lastAutoTable.finalY + 7 : y + impactData.length * 5;
addLine("Disclaimer: This is a conceptual simulator based on user-defined assumptions for informational purposes only and not financial advice.", 7, 'italic');
doc.save(`RealEstate_DownturnImpact_${i.propertyType.replace(/\s+/g, '_')}.pdf`);
}