← back to StudentLoanTracker
src/lib/calculators/comparison.ts
77 lines
/**
* Plan Comparison Engine
*
* Runs all IDR calculators and produces a unified comparison
* with recommendations for lowest monthly, lowest total cost,
* and fastest payoff.
*/
import { LoanInputs, PlanResult, ComparisonResult } from './types';
import { calculateSAVE } from './save-calculator';
import { calculateIBR } from './ibr-calculator';
import { calculatePAYE } from './paye-calculator';
import { calculateICR } from './icr-calculator';
/**
* Calculate the 10-year Standard repayment plan for baseline comparison.
*/
function calculateStandard(inputs: LoanInputs): PlanResult {
const { totalBalance, weightedRate } = inputs;
const monthlyRate = weightedRate / 12;
const months = 120;
const monthlyPayment =
monthlyRate > 0
? (totalBalance * monthlyRate) / (1 - Math.pow(1 + monthlyRate, -months))
: totalBalance / months;
const totalPaid = monthlyPayment * months;
return {
planName: 'Standard (10-Year)',
monthlyPayment: Math.round(monthlyPayment * 100) / 100,
totalPaid: Math.round(totalPaid * 100) / 100,
totalInterest: Math.round((totalPaid - totalBalance) * 100) / 100,
forgivenessAmount: 0,
forgivenessMonths: 0,
repaymentMonths: months,
discretionaryIncome: 0,
povertyGuideline: 0,
};
}
/**
* Compare all available repayment plans.
*/
export function compareAllPlans(inputs: LoanInputs): ComparisonResult {
const plans: PlanResult[] = [
calculateStandard(inputs),
calculateSAVE(inputs),
calculateIBR(inputs, true), // New IBR
calculateIBR(inputs, false), // Old IBR
calculatePAYE(inputs),
calculateICR(inputs),
];
// Find recommendations
const lowestMonthly = plans.reduce((min, p) =>
p.monthlyPayment < min.monthlyPayment ? p : min
);
const lowestTotal = plans.reduce((min, p) =>
p.totalPaid < min.totalPaid ? p : min
);
const fastestPayoff = plans.reduce((min, p) =>
p.repaymentMonths < min.repaymentMonths ? p : min
);
return {
inputs,
plans,
recommended: lowestTotal.planName,
lowestMonthly: lowestMonthly.planName,
fastestPayoff: fastestPayoff.planName,
};
}