Annual Savings Rate Optimizer
Current Monthly Income
No income sources added yet.
Current Monthly Expenses
No expense categories added yet.
Current Savings Status
Monthly Savings: $0.00
Annual Savings: $0.00
Current Savings Rate: 0.00%
Optimize Your Savings Rate
Adjust your monthly income and expense amounts below to see the impact on your savings rate. Original amounts are shown for reference.
Add income and expenses in previous tabs to start optimizing.
Optimized Savings Status
New Total Monthly Income: $0.00
New Total Monthly Expenses: $0.00
New Monthly Savings: $0.00
New Annual Savings: $0.00
Optimized Savings Rate: 0.00%
Change in Monthly Savings: $0.00
Optimization Summary & Export
Your optimization summary will appear here.
Monthly Savings: $${monthlySavings.toFixed(2)}
Annual Savings: $${annualSavings.toFixed(2)}
Current Savings Rate: ${savingsRate.toFixed(2)}%
`; return { monthlySavings, annualSavings, savingsRate, totalMonthlyIncome, totalMonthlyExpenses }; } // --- Optimization (Tab 3) --- function asro_populateOptimizationArea() { const area = document.getElementById('asroOptimizationArea'); area.innerHTML = ''; let contentHTML = ''; if (asro_incomeSources.length > 0) { contentHTML += `Adjust Income Sources:
| Source | Current Monthly ($) | Adjusted Monthly ($) |
|---|---|---|
| ${src.name} | ${src.amount.toFixed(2)} |
Adjust Expense Categories:
| Category | Current Monthly ($) | Adjusted Monthly ($) |
|---|---|---|
| ${cat.name} | ${cat.amount.toFixed(2)} |
Add income and expenses in previous tabs to start optimizing.
'; } else { area.innerHTML = contentHTML; } asro_recalculateOptimizedScenario(); // Initial calculation for this tab } function asro_updateAdjustedValue(type, id, value) { const list = type === 'income' ? asro_incomeSources : asro_expenseCategories; const item = list.find(i => i.id === id); if (item) { item.adjustedAmount = parseFloat(value) >= 0 ? parseFloat(value) : 0; // Ensure original input field reflects this if it was an invalid entry (e.g. negative) event.target.value = item.adjustedAmount.toFixed(2); } asro_recalculateOptimizedScenario(); } function asro_recalculateOptimizedScenario() { const totalAdjustedMonthlyIncome = asro_incomeSources.reduce((sum, src) => sum + src.adjustedAmount, 0); const totalAdjustedMonthlyExpenses = asro_expenseCategories.reduce((sum, cat) => sum + cat.adjustedAmount, 0); const newMonthlySavings = totalAdjustedMonthlyIncome - totalAdjustedMonthlyExpenses; const newAnnualSavings = newMonthlySavings * 12; const newSavingsRate = totalAdjustedMonthlyIncome > 0 ? (newMonthlySavings / totalAdjustedMonthlyIncome * 100) : 0; const currentSavingsData = asro_calculateAndDisplayCurrentSavings(); // to get original monthly savings const changeInMonthlySavings = newMonthlySavings - currentSavingsData.monthlySavings; const displayDiv = document.getElementById('asroOptimizedSavingsDisplay'); if(displayDiv) { displayDiv.innerHTML = `Optimized Savings Status
New Total Monthly Income: $${totalAdjustedMonthlyIncome.toFixed(2)}
New Total Monthly Expenses: $${totalAdjustedMonthlyExpenses.toFixed(2)}
New Monthly Savings: $${newMonthlySavings.toFixed(2)}
New Annual Savings: $${newAnnualSavings.toFixed(2)}
Optimized Savings Rate: ${newSavingsRate.toFixed(2)}%
Change in Monthly Savings: ${changeInMonthlySavings >=0 ? '+' : ''}$${changeInMonthlySavings.toFixed(2)}
`; } return { totalAdjustedMonthlyIncome, totalAdjustedMonthlyExpenses, newMonthlySavings, newAnnualSavings, newSavingsRate, changeInMonthlySavings }; } // --- Summary & Export (Tab 4) --- function asro_displayOptimizationSummary() { const previewDiv = document.getElementById('asroReportPreview'); const current = asro_calculateAndDisplayCurrentSavings(); // Get current figures const optimized = asro_recalculateOptimizedScenario(); // Get optimized figures let changesMadeHTML = "Summary of Changes Made:
- ";
let hasChanges = false;
asro_incomeSources.forEach(src => {
if (src.amount !== src.adjustedAmount) {
changesMadeHTML += `
- Income '${src.name}': $${src.amount.toFixed(2)} -> $${src.adjustedAmount.toFixed(2)} (Change: $${(src.adjustedAmount - src.amount).toFixed(2)}) `; hasChanges = true; } }); asro_expenseCategories.forEach(cat => { if (cat.amount !== cat.adjustedAmount) { changesMadeHTML += `
- Expense '${cat.name}': $${cat.amount.toFixed(2)} -> $${cat.adjustedAmount.toFixed(2)} (Change: $${(cat.adjustedAmount - cat.amount).toFixed(2)}) `; hasChanges = true; } }); if (!hasChanges) changesMadeHTML += "
- No changes modeled for optimization. "; changesMadeHTML += "
Current vs. Optimized Scenario
Current Annual Savings: $${current.annualSavings.toFixed(2)} (Rate: ${current.savingsRate.toFixed(2)}%)
Optimized Annual Savings: $${optimized.newAnnualSavings.toFixed(2)} (Rate: ${optimized.newSavingsRate.toFixed(2)}%)
Total Annual Improvement: $${(optimized.newAnnualSavings - current.annualSavings).toFixed(2)}
${changesMadeHTML} `; asro_renderSavingsRateChart(current.savingsRate, optimized.newSavingsRate); } function asro_renderSavingsRateChart(currentRate, optimizedRate) { const chartContainer = document.getElementById('asroSavingsRateChartContainer'); const canvas = document.getElementById('asroSavingsRateChart'); if (!currentRate && !optimizedRate && currentRate !==0 && optimizedRate !==0) { // if both are undefined or null (but not zero) chartContainer.style.display = 'none'; return; } chartContainer.style.display = 'block'; if (asro_savingsRateChartInstance) { asro_savingsRateChartInstance.destroy(); } asro_savingsRateChartInstance = new Chart(canvas, { type: 'bar', data: { labels: ['Current Savings Rate', 'Optimized Savings Rate'], datasets: [{ label: 'Savings Rate (%)', data: [currentRate > 0 ? currentRate : 0, optimizedRate > 0 ? optimizedRate : 0], // Ensure non-negative for chart backgroundColor: [ 'rgba(255, 193, 7, 0.6)', // warning-color somewhat 'rgba(76, 175, 80, 0.6)' // accent-color ], borderColor: [ 'rgba(255, 193, 7, 1)', 'rgba(76, 175, 80, 1)' ], borderWidth: 1 }] }, options: { responsive: true, maintainAspectRatio: true, scales: { y: { beginAtZero: true, ticks: { callback: function(value) { return value + "%" } } } }, plugins: { legend: { display: false }, title: { display: true, text: 'Savings Rate Comparison' } } } }); } function asro_generatePdf() { const current = asro_calculateAndDisplayCurrentSavings(); const optimized = asro_recalculateOptimizedScenario(); if (!current || !optimized) { alert("Please ensure data is entered and calculations are complete."); return; } const { jsPDF } = window.jspdf; const doc = new jsPDF(); let yPos = 20; const primaryColor = getComputedStyle(document.documentElement).getPropertyValue('--primary-color').trim(); const accentColor = getComputedStyle(document.documentElement).getPropertyValue('--accent-color').trim(); const textColor = getComputedStyle(document.documentElement).getPropertyValue('--text-color').trim(); const toCurrency = (num) => `$${num.toFixed(2)}`; doc.setFontSize(20); doc.setTextColor(primaryColor); doc.text("Annual Savings Rate Optimization Plan", doc.internal.pageSize.getWidth() / 2, yPos, { align: 'center' }); yPos += 15; function addSectionTitle(title) { if (yPos > 260) { doc.addPage(); yPos = 20; } doc.setFontSize(14); doc.setTextColor(primaryColor); doc.text(title, 14, yPos); yPos += 8; doc.setFontSize(10); doc.setTextColor(textColor); } function addDataRow(label, valueStr) { if (yPos > 275) { doc.addPage(); yPos = 20; } doc.text(`${label}:`, 14, yPos); doc.text(valueStr, 80, yPos); yPos += 6; } // Current Financials addSectionTitle("Current Financial Summary (Monthly)"); addDataRow("Total Income", toCurrency(current.totalMonthlyIncome)); addDataRow("Total Expenses", toCurrency(current.totalMonthlyExpenses)); addDataRow("Monthly Savings", toCurrency(current.monthlySavings)); addDataRow("Annual Savings", toCurrency(current.annualSavings)); addDataRow("Savings Rate", `${current.savingsRate.toFixed(2)}%`); yPos += 4; // Optimized Financials addSectionTitle("Optimized Financial Summary (Monthly)"); addDataRow("New Total Income", toCurrency(optimized.totalAdjustedMonthlyIncome)); addDataRow("New Total Expenses", toCurrency(optimized.totalAdjustedMonthlyExpenses)); addDataRow("New Monthly Savings", toCurrency(optimized.newMonthlySavings)); doc.setTextColor(accentColor); addDataRow("New Annual Savings", toCurrency(optimized.newAnnualSavings)); addDataRow("New Savings Rate", `${optimized.newSavingsRate.toFixed(2)}%`); doc.setTextColor(textColor); addDataRow("Improvement in Annual Savings", toCurrency(optimized.newAnnualSavings - current.annualSavings)); yPos += 4; // Table of Changes let changes = []; asro_incomeSources.forEach(src => { if (src.amount !== src.adjustedAmount) changes.push([src.name (Income), toCurrency(src.amount), toCurrency(src.adjustedAmount), toCurrency(src.adjustedAmount - src.amount)]) }); asro_expenseCategories.forEach(cat => { if (cat.amount !== cat.adjustedAmount) changes.push([cat.name (Expense), toCurrency(cat.amount), toCurrency(cat.adjustedAmount), toCurrency(cat.adjustedAmount - cat.amount)]) }); if (changes.length > 0) { if (yPos > 240) { doc.addPage(); yPos = 20; } addSectionTitle("Summary of Changes Made (Monthly)"); doc.autoTable({ startY: yPos, head: [['Item (Type)', 'Original Amt ($)', 'Adjusted Amt ($)', 'Change ($)']], body: changes, theme: 'grid', headStyles: { fillColor: primaryColor, textColor: '#ffffff' }, styles: { fontSize: 9, cellPadding: 1.5 }, didDrawPage: (d) => { yPos = d.cursor.y; } }); } else { doc.text("No specific changes were modeled in the optimization step.", 14, yPos); } doc.save('savings_rate_optimization_plan.pdf'); } // Initialize document.addEventListener('DOMContentLoaded', () => { asro_showTab(0); asro_renderIncomeSources(); asro_updateTotalIncomeDisplay(); asro_renderExpenseCategories(); asro_updateTotalExpensesDisplay(); asro_calculateAndDisplayCurrentSavings(); // Initial call // Demo Data asro_incomeSources.push({id:'inc_001', name:'Salary', amount: 4000, adjustedAmount: 4000}); asro_incomeSources.push({id:'inc_002', name:'Freelance Work', amount: 500, adjustedAmount: 600}); asro_expenseCategories.push({id:'exp_001', name:'Rent/Mortgage', amount:1500, adjustedAmount:1500}); asro_expenseCategories.push({id:'exp_002', name:'Groceries', amount:400, adjustedAmount:350}); asro_expenseCategories.push({id:'exp_003', name:'Dining Out', amount:200, adjustedAmount:100}); asro_renderIncomeSources(); asro_updateTotalIncomeDisplay(); asro_renderExpenseCategories(); asro_updateTotalExpensesDisplay(); asro_calculateAndDisplayCurrentSavings(); });
