function formatMoney(num) { return parseFloat(num).toFixed(2).replace(/\d(?=(\d{3})+\.)/g, "$&,"); } class Data { constructor(balance, contribution, returnRate, inflationRate, years, money) { this.balance = balance; this.contribution = contribution; this.returnRate = returnRate; this.inflationRate = inflationRate; this.years = years; this.money = money; } summary() { const summaryRow = " $ " + formatMoney(this.balance) + " $ " + formatMoney(this.contribution) + " " + (this.returnRate).toFixed(2) + " % " + (this.inflationRate).toFixed(2) + " % "; return summaryRow; } adjustedRate() { const adjustedRate = ((1 + (this.returnRate / 100)) / (1 + (this.inflationRate / 100)) - 1); return adjustedRate; } graphData(monthsArr, balanceArr, interestArr) { let matched = window.matchMedia('(prefers-color-scheme: dark)').matches; if(matched) { var bgColor = "#202020"; var fgColor = "#ffffff"; var gridColor = "#3b3b3b"; var lineColor = "#5b5b5b"; } else { var bgColor = "#ffffff"; var fgColor = "#222222"; var gridColor = "#c8c8c8"; var lineColor = "#555555"; } const balanceTrace = { x: monthsArr, y: balanceArr, type: "scatter", line: { color: "#24ab48", width: 2 } }; const interestTrace = { x: monthsArr, y: interestArr, type: "scatter", line: { color: "#0062ff", width: 2 } }; const balanceTitle = { title: { text: "Total Balance", color: fgColor }, paper_bgcolor: bgColor, plot_bgcolor: bgColor, font: { color: fgColor }, yaxis: { title: "Total Balance", gridcolor: gridColor, zerolinecolor: gridColor, linecolor: lineColor }, xaxis: { title: "Months", gridcolor: gridColor, zerolinecolor: gridColor, linecolor: lineColor } }; const interestTitle = { title: { text: "Accrued Interest", color: fgColor }, paper_bgcolor: bgColor, plot_bgcolor: bgColor, font: { color: fgColor }, yaxis: { title: "Accrued Interest", gridcolor: gridColor, zerolinecolor: gridColor, linecolor: lineColor }, xaxis: { title: "Months", gridcolor: gridColor, zerolinecolor: gridColor, linecolor: lineColor } }; return [balanceTrace, interestTrace, balanceTitle, interestTitle]; } } function retirementYears() { $("tbody").empty(); const myData = new Data(parseFloat($("#begBalance").val()), parseFloat($("#monthlyContr").val()), parseFloat($("#returnRate").val()), parseFloat($("#inflationRate").val()), parseFloat($("#years").val()), null); const summary = myData.summary(); $(".infoTable tbody").append(summary); $(".infoTable, .resultsTable, #infoTableHeading, #resultsTableHeading").show(); var interestArr = [], balanceArr = [], monthsArr = []; const adjustedRate = myData.adjustedRate(); const monthlyContr = myData.contribution; let pVal = myData.balance; for (var i = 0; i < (myData.years * 12); i++) { var interest = (pVal * (adjustedRate / 12)).toFixed(2); var newBalance = (parseFloat(pVal) + parseFloat(interest) + monthlyContr).toFixed(2); $(".resultsTable tbody").append(" " + (i + 1) + " $ " + formatMoney(interest) + " $ " + formatMoney(monthlyContr) + " $ " + formatMoney(newBalance) + " "); if ((i + 1) === 1 || (i + 1) % 12 === 0 || i === (myData.years * 12)) { interestArr.push(parseInt(interest * 100) / 100); balanceArr.push(parseInt(newBalance * 100) / 100); monthsArr.push(i + 1); } pVal = newBalance; } $(".graphCard").css("display", "block"); const graphData = myData.graphData(monthsArr, balanceArr, interestArr); Plotly.newPlot("balChartContainer", [graphData[0]], graphData[2], { responsive: true }); Plotly.newPlot("intChartContainer", [graphData[1]], graphData[3], { responsive: true }); } function retirementMoney() { $("tbody").empty(); const myData = new Data(parseFloat($("#begBalance").val()), parseFloat($("#monthlyContr").val()), parseFloat($("#returnRate").val()), parseFloat($("#inflationRate").val()), null, parseFloat($("#money").val())); const summary = myData.summary(); $(".infoTable tbody").append(summary); $(".infoTable, .resultsTable, #infoTableHeading, #resultsTableHeading").show(); var interestArr = [], balanceArr = [], monthsArr = []; const adjustedRate = myData.adjustedRate(); const monthlyContr = myData.contribution; let pVal = myData.balance; let money = myData.money; for (var i = 0; pVal < money; i++) { var months = i + 1; var newBalance = (pVal + (pVal * (adjustedRate / 12)) + monthlyContr); $(".resultsTable tbody").append(" " + months + " $ " + formatMoney((pVal * (adjustedRate / 12))) + " $ " + formatMoney(monthlyContr) + " $ " + formatMoney(newBalance) + " "); var roundedInterest = parseInt((pVal * (adjustedRate / 12)) * 100) / 100; var roundedBalance = parseInt(newBalance * 100) / 100; if (months === 1 || months % 12 === 0 || pVal > money) { interestArr.push(roundedInterest); balanceArr.push(roundedBalance); monthsArr.push(months); } pVal = newBalance; } $(".graphCard").css("display", "block"); const graphData = myData.graphData(monthsArr, balanceArr, interestArr); Plotly.newPlot("balChartContainer", [graphData[0]], graphData[2], { responsive: true }); Plotly.newPlot("intChartContainer", [graphData[1]], graphData[3], { responsive: true }); }