How the Decision tools debt payoff planner calculator is verified
Inputs
| Input | Field | Type |
|---|---|---|
| Your debts | debts | array |
| Total you can pay each month | monthlyBudget | number |
| Which debt gets the extra money | strategy | string |
The formula
Each derived value below is computed by the Valem engine from the expression shown, in this order. Nothing else runs — there is no hidden code path.
| Derived value | Field | Formula (JSONata) |
|---|---|---|
| Total owed today | totalBalance | $round($sum($map(debts, function($d) { $d.balance })), 2) |
| Total Minimums | totalMinimums | $round($sum($map(debts, function($d) { $d.minPayment })), 2) |
| Avalanche | avalanche | $simulate($sort(debts, function($x, $y) { $x.aprPct < $y.aprPct }), monthlyBudget, $const.maxMonths) |
| Snowball | snowball | $simulate($sort(debts, function($x, $y) { $x.balance > $y.balance }), monthlyBudget, $const.maxMonths) |
| Months to debt free | monthsToFree | ( $s := strategy = "snowball" ? snowball : avalanche; $s.months ) |
| Interest you pay | totalInterest | ( $s := strategy = "snowball" ? snowball : avalanche; $s.interest ) |
| Payoff Order | payoffOrder | ( $s := strategy = "snowball" ? snowball : avalanche; $join($s.order, " → ") ) |
| Avalanche saves | interestSaved | ( $s := snowball; $a := avalanche; $round($s.interest - $a.interest, 2) ) |
| Clears In Horizon | clearsInHorizon | ( $s := strategy = "snowball" ? snowball : avalanche; $s.cleared ) |
| What you still owe, month by month | schedule | ( $s := strategy = "snowball" ? snowball : avalanche; [$s.history] ) |
Rates and thresholds
The expressions above read these as $const. They are the figures the annual refresh replaces, so they live as data rather than being written into the formulas — which is what makes a year-on-year change a one-line diff instead of an edit to arithmetic.
| Constant | Value |
|---|---|
maxMonths | 120 |
Test vectors (3)
Every case is executed against this model on each build, by the Java engine and independently by a JavaScript one. A mismatch of a single cent fails the build, so the page cannot ship advertising a figure the model no longer produces.
Case 1 — three debts totalling 11,500 on a 600 budget, avalanche — highest rate first
given monthlyBudget | 600 |
|---|---|
given strategy | avalanche |
expect totalBalance | 11500 |
expect totalMinimums | 265 |
expect monthsToFree | 23 |
expect totalInterest | 1509.23 |
expect clearsInHorizon | true |
expect interestSaved | 112.56 |
expect schedule[0].interest | 142.5 |
expect schedule[0].balance | 11042.5 |
expect schedule[22].balance | 0 |
Case 2 — the same debts on snowball — clears in the same 23 months but costs 112.56 more in interest
given monthlyBudget | 600 |
|---|---|
given strategy | snowball |
expect monthsToFree | 23 |
expect totalInterest | 1621.79 |
expect interestSaved | 112.56 |
Case 3 — paying only the minimums stretches it to 66 months and nearly quadruples the interest
given monthlyBudget | 265 |
|---|---|
given strategy | avalanche |
expect monthsToFree | 66 |
expect totalInterest | 5876.6 |
expect interestSaved | 30.42 |
expect clearsInHorizon | true |
Sources
Check it yourself — and reuse it
The whole model as JSON — inputs, outputs, formulas, vectors and sources in one re-runnable document.
This model is published under CC BY 4.0: use it, adapt it, build on it, with attribution. The licence covers the model — the expression of each rule and the arrangement of the catalog. The rates and thresholds are law, and nobody licenses those; the sources above are where they come from.
← Back to the Decision tools debt payoff planner calculator
Built with Valem — a live, verifiable calculator you can fork and embed.