<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>CPF Calculator</title>
<style>
body {
font-family: Arial, sans-serif;
margin: 20px;
}
.calculator {
max-width: 600px;
margin: auto;
padding: 20px;
border: 1px solid #ccc;
border-radius: 10px;
box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
}
.calculator input {
width: 100%;
padding: 10px;
margin: 10px 0;
border: 1px solid #ccc;
border-radius: 5px;
}
.calculator button {
width: 100%;
padding: 10px;
background-color: #007bff;
color: white;
border: none;
border-radius: 5px;
cursor: pointer;
}
.calculator button:hover {
background-color: #0056b3;
}
table {
width: 100%;
margin-top: 20px;
border-collapse: collapse;
}
table th, table td {
border: 1px solid #ccc;
padding: 10px;
text-align: center;
}
table th {
background-color: #f8f9fa;
}
</style>
</head>
<body>
<div class="calculator">
<h2>CPF Calculator</h2>
<label for="monthlyIncome">Monthly Income ($):</label>
<input type="number" id="monthlyIncome" placeholder="Enter monthly income">
<label for="salaryIncrease">Annual Salary Increase (%):</label>
<input type="number" step="0.01" id="salaryIncrease" placeholder="Enter annual salary increase">
<label for="numYears">Number of Years:</label>
<input type="number" id="numYears" placeholder="Enter number of years">
<label for="startDate">Start Year:</label>
<input type="number" id="startDate" placeholder="Enter start year">
<label for="startAge">Starting Age:</label>
<input type="number" id="startAge" placeholder="Enter starting age">
<button onclick="window.calculateCPF()">Calculate</button>
<div id="outputTable"></div>
</div>
<script>
window.calculateCPF = function() {
// Get user inputs
const monthlyIncome = parseFloat(document.getElementById('monthlyIncome').value);
const salaryIncrease = parseFloat(document.getElementById('salaryIncrease').value) / 100;
const numYears = parseInt(document.getElementById('numYears').value);
const startDate = parseInt(document.getElementById('startDate').value);
const startAge = parseInt(document.getElementById('startAge').value);
if (isNaN(monthlyIncome) || isNaN(salaryIncrease) || isNaN(numYears) || isNaN(startDate) || isNaN(startAge)) {
document.getElementById('outputTable').innerHTML = '<p style="color: red;">Please fill in all fields correctly.</p>';
return;
}
let currentIncome = monthlyIncome; // Start with monthly income
let cpfBalance = { OA: 0, SA: 0, MA: 0 };
let results = [];
let currentAge = startAge;
for (let year = 0; year < numYears; year++) {
const currentYear = startDate + year;
// Determine CPF contribution rates based on age
let cpfRate;
if (currentAge <= 35) {
cpfRate = cpfRates.upTo35;
} else if (currentAge <= 45) {
cpfRate = cpfRates['35to45'];
} else if (currentAge <= 50) {
cpfRate = cpfRates['45to50'];
} else if (currentAge <= 55) {
cpfRate = cpfRates['50to55'];
} else if (currentAge <= 60) {
cpfRate = cpfRates['55to60'];
} else if (currentAge <= 65) {
cpfRate = cpfRates['60to65'];
} else {
cpfRate = cpfRates.above65;
}
// Initialize yearly totals
let yearlyPrincipal = 0;
let yearlyInterest = 0;
// Process each month in the year
for (let month = 0; month < 12; month++) {
// Calculate monthly contributions
const cpfContributions = {
OA: currentIncome * cpfRate.OA,
SA: currentIncome * cpfRate.SA,
MA: currentIncome * cpfRate.MA
};
// Add contributions to balances
cpfBalance.OA += cpfContributions.OA;
cpfBalance.SA += cpfContributions.SA;
cpfBalance.MA += cpfContributions.MA;
// Calculate monthly interest
const interest = {
OA: cpfBalance.OA * (cpfInterestRates.OA / 12),
SA: cpfBalance.SA * (cpfInterestRates.SA / 12),
MA: cpfBalance.MA * (cpfInterestRates.MA / 12)
};
// Add interest to balances
cpfBalance.OA += interest.OA;
cpfBalance.SA += interest.SA;
cpfBalance.MA += interest.MA;
// Update yearly totals
yearlyPrincipal += cpfContributions.OA + cpfContributions.SA + cpfContributions.MA;
yearlyInterest += interest.OA + interest.SA + interest.MA;
}
// Calculate total balance at the end of the year
const totalBalance = cpfBalance.OA + cpfBalance.SA + cpfBalance.MA;
// Store results for the year
results.push({
year: currentYear,
age: currentAge,
principal: yearlyPrincipal.toFixed(2),
interest: yearlyInterest.toFixed(2),
total: totalBalance.toFixed(2)
});
// Update income for next year
currentIncome *= (1 + salaryIncrease);
// Increment age
currentAge++;
}
// Generate the output table
let tableHTML = `
<table>
<thead>
<tr>
<th>Year</th>
<th>Age</th>
<th>CPF Principal Amount ($)</th>
<th>CPF Accrued Interest Amount ($)</th>
<th>Total CPF Amount ($)</th>
</tr>
</thead>
<tbody>
`;
results.forEach(row => {
tableHTML += `
<tr>
<td>${row.year}</td>
<td>${row.age}</td>
<td>${row.principal}</td>
<td>${row.interest}</td>
<td>${row.total}</td>
</tr>
`;
});
tableHTML += '</tbody></table>';
document.getElementById('outputTable').innerHTML = tableHTML;
};
const cpfRates = {
upTo35: { OA: 0.23, SA: 0.06, MA: 0.08 },
35to45: { OA: 0.21, SA: 0.07, MA: 0.09 },
45to50: { OA: 0.19, SA: 0.08, MA: 0.10 },
50to55: { OA: 0.15, SA: 0.115, MA: 0.105 },
55to60: { OA: 0.12, SA: 0.035, MA: 0.08 },
60to65: { OA: 0.035, SA: 0.025, MA: 0.08 },
above65: { OA: 0.01, SA: 0.01, MA: 0.08 }
};
const cpfInterestRates = { OA: 0.025, SA: 0.04, MA: 0.04 };
</script>
</body>
</html>