Please fill in details on all tabs and click 'Compare Results' or 'Recalculate'.
";
return;
}
const ltr = strltr_results.ltr;
const str = strltr_results.str;
const useFinancing = strltr_results.inputs.useFinancing;
const annualMortgage = strltr_results.inputs.monthlyMortgagePayment * 12;
// Function to add 'better' class
const betterClass = (val1, val2) => val1 > val2 ? 'strltr_better_value' : (val2 > val1 ? '' : ''); // val1 is LTR, val2 is STR
const worseClass = (val1, val2) => val1 < val2 ? 'strltr_better_value' : (val2 < val1 ? '' : ''); // For expenses
let tableHTML = `
Comparison Summary (Annual - Year 1)
| Metric |
Long-Term Rental (LTR) |
Short-Term Rental (STR) |
| Initial Cash Invested | ${strltr_formatCurrency(ltr.initialCashInvested)} | ${strltr_formatCurrency(str.initialCashInvested)} |
| Income |
| Gross Scheduled/Potential Annual Income | ${strltr_formatCurrency(ltr.annualGrossScheduledRent)} | ${strltr_formatCurrency(str.grossPotentialRevenue)} |
| Effective Gross Annual Income (after vacancy/occupancy) | ${strltr_formatCurrency(ltr.effectiveGrossIncome)} | ${strltr_formatCurrency(str.grossActualRevenue)} |
| Expenses |
| Total Annual Operating Expenses | ${strltr_formatCurrency(ltr.totalOperatingExpenses)} | ${strltr_formatCurrency(str.totalOperatingExpenses)} |
| Profitability & Cash Flow |
| Net Operating Income (NOI) | ${strltr_formatCurrency(ltr.noi)} | ${strltr_formatCurrency(str.noi)} |
`;
if(useFinancing) {
tableHTML += `| Annual Mortgage Payment (P&I) | ${strltr_formatCurrency(annualMortgage)} | ${strltr_formatCurrency(annualMortgage)} |
`;
} else {
tableHTML += `| Annual Mortgage Payment (P&I) | N/A (Cash Purchase) | N/A (Cash Purchase) |
`;
}
tableHTML += `| Annual Pre-Tax Cash Flow | ${strltr_formatCurrency(ltr.preTaxCashFlow)} | ${strltr_formatCurrency(str.preTaxCashFlow)} |
| Returns & Yields |
| Gross Rental Yield | ${strltr_formatPercent(ltr.grossYield)} | ${strltr_formatPercent(str.grossYield)} |
| Net Rental Yield (NOI / Total Cost) | ${strltr_formatPercent(ltr.netYield)} | ${strltr_formatPercent(str.netYield)} |
| Cash on Cash Return (Pre-Tax) | ${strltr_formatPercent(ltr.cashOnCashReturn)} | ${strltr_formatPercent(str.cashOnCashReturn)} |
`;
container.innerHTML = tableHTML;
const pdfBtn = document.getElementById('strltr_downloadPdfButton');
if(pdfBtn) pdfBtn.style.display = 'block';
}
// --- PDF Generation ---
function strltr_downloadPDF() {
if (!strltr_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.');
// Fallback or simply return: For now, we proceed assuming it might just affect tables
}
let y = 15; const m = 15;
const i = strltr_results.inputs;
const ltr = strltr_results.ltr;
const str = strltr_results.str;
const annualMortgage = i.monthlyMortgagePayment * 12;
doc.setFontSize(16); doc.text("LTR vs. STR Comparison Report", m, y); y += 10;
doc.setFontSize(10);
doc.text(`Property Purchase Price: ${strltr_formatCurrency(i.propertyPrice)}`, m, y); y+=5;
doc.text(`Acquisition Costs: ${strltr_formatCurrency(i.acquisitionCosts)}`, m, y); y+=5;
if (i.useFinancing) {
doc.text(`Financing: Yes, Down Payment: ${i.downPaymentPercent}% (${strltr_formatCurrency(i.propertyPrice * i.downPaymentPercent/100)})`, m, y); y+=5;
doc.text(`Loan: ${strltr_formatCurrency(i.propertyPrice * (1-i.downPaymentPercent/100))} @ ${i.interestRateAnnual}% for ${i.loanTermYears} years. Monthly P&I: ${strltr_formatCurrency(i.monthlyMortgagePayment)}`, m, y); y+=5;
} else {
doc.text("Financing: No (Cash Purchase)", m, y); y+=5;
}
y += 5;
const head = [['Metric', 'Long-Term Rental (LTR)', 'Short-Term Rental (STR)']];
const body = [
['Initial Setup/Furnishing Costs', strltr_formatCurrency(i.initialSetupLTR), strltr_formatCurrency(i.initialSetupSTR)],
['Initial Cash Invested', strltr_formatCurrency(ltr.initialCashInvested), strltr_formatCurrency(str.initialCashInvested)],
[{content: 'Income', colSpan: 3, styles: {fontStyle: 'bold', fillColor: [230,230,230]}}],
['Gross Potential Annual Income', strltr_formatCurrency(ltr.annualGrossScheduledRent), strltr_formatCurrency(str.grossPotentialRevenue)],
['Effective Gross Annual Income', strltr_formatCurrency(ltr.effectiveGrossIncome), strltr_formatCurrency(str.grossActualRevenue)],
[{content: 'Expenses', colSpan: 3, styles: {fontStyle: 'bold', fillColor: [230,230,230]}}],
['Total Annual Operating Expenses', strltr_formatCurrency(ltr.totalOperatingExpenses), strltr_formatCurrency(str.totalOperatingExpenses)],
[{content: 'Profitability & Cash Flow', colSpan: 3, styles: {fontStyle: 'bold', fillColor: [230,230,230]}}],
['Net Operating Income (NOI)', strltr_formatCurrency(ltr.noi), strltr_formatCurrency(str.noi)],
['Annual Mortgage (P&I)', i.useFinancing ? strltr_formatCurrency(annualMortgage) : 'N/A', i.useFinancing ? strltr_formatCurrency(annualMortgage) : 'N/A'],
['Annual Pre-Tax Cash Flow', strltr_formatCurrency(ltr.preTaxCashFlow), strltr_formatCurrency(str.preTaxCashFlow)],
[{content: 'Returns & Yields', colSpan: 3, styles: {fontStyle: 'bold', fillColor: [230,230,230]}}],
['Gross Rental Yield', strltr_formatPercent(ltr.grossYield), strltr_formatPercent(str.grossYield)],
['Net Rental Yield (NOI/Total Cost)', strltr_formatPercent(ltr.netYield), strltr_formatPercent(str.netYield)],
['Cash on Cash Return (Pre-Tax)', strltr_formatPercent(ltr.cashOnCashReturn), strltr_formatPercent(str.cashOnCashReturn)],
];
if (typeof doc.autoTable === 'function') {
doc.autoTable({
startY: y, head: head, body: body, theme: 'grid',
headStyles: { fillColor: [29, 78, 216], textColor: 255, fontSize: 10 }, // Blue header
styles: { fontSize: 9, cellPadding: 2 },
columnStyles: { 0: {fontStyle:'bold', cellWidth: 65}, 1:{halign:'right'}, 2:{halign:'right'} }
});
} else { // Fallback if autoTable is not available
y += 5;
doc.setFontSize(8);
body.forEach(row => {
if (row[0].colSpan) { // Handle merged header rows simply
doc.text(row[0].content, m, y); y += 5;
} else {
doc.text(`${row[0]}: LTR ${row[1]}, STR ${row[2]}`, m, y); y += 4;
}
if (y > 270) { doc.addPage(); y = m; }
});
y += 5;
doc.setFontSize(10);
doc.text("Note: Table formatting limited due to a PDF plugin issue.", m, y, {textColor: 'red'});
}
doc.save("Rental_Yield_Comparison.pdf");
}