(runs: MaintainRun[], nowMs: number, weeks = 8)
| 82 | |
| 83 | /** Opened-cleanups per week over the last `weeks` (oldest→newest) — a sparkline series. PURE. */ |
| 84 | export function trendByWeek(runs: MaintainRun[], nowMs: number, weeks = 8): number[] { |
| 85 | const DAY = 86_400_000; |
| 86 | const buckets = new Array(weeks).fill(0); |
| 87 | for (const r of runs) { |
| 88 | if (r.status !== 'opened' || !r.at) continue; |
| 89 | const t = Date.parse(r.at); |
| 90 | if (!Number.isFinite(t)) continue; |
| 91 | const weeksAgo = Math.floor((nowMs - t) / (7 * DAY)); |
| 92 | if (weeksAgo >= 0 && weeksAgo < weeks) buckets[weeks - 1 - weeksAgo]++; // newest at the end |
| 93 | } |
| 94 | return buckets; |
| 95 | } |
| 96 | |
| 97 | /** Project the going rate forward: cleanups + minutes saved per month, from the last 28 days. PURE. */ |
| 98 | export function projectMonthly(runs: MaintainRun[], nowMs: number): { cleanupsPerMonth: number; minutesPerMonth: number } { |
no outgoing calls
no test coverage detected