import Link from 'next/link'; import { Bars, StackedBars } from '@/components/charts/charts'; import { fmtInt, num } from '@/lib/format'; import { routes } from '@/lib/site'; import type { StatsSnapshot } from '@/lib/types'; import { ChartBlock, Derived, Note, TwoCol } from './shared'; /** Full-history charts (since 1957) + derived growth-rate table. */ export function StatsHistory({ snapshot }: { snapshot: StatsSnapshot }) { const launches = [...snapshot.launches_by_year].sort((a, b) => a.year - b.year); const payloads = [...snapshot.payloads_by_launch_year].sort((a, b) => a.year - b.year); const decays = [...snapshot.decays_by_year].sort((a, b) => a.year - b.year); const first = launches[0]?.year; const last = launches[launches.length - 1]?.year; const span = first && last ? `${first}–${last}` : undefined; const launchSeries = launches.map((r) => ({ x: r.year, y: num(r.launches) ?? 0 })); const payloadStack = payloads.map((r) => { const p = num(r.payloads) ?? 0; const a = num(r.still_active) ?? 0; return { x: r.year, still_active: a, retired: Math.max(0, p - a) }; }); const decaySeries = decays.map((r) => ({ x: r.year, y: num(r.decayed) ?? 0 })); // Derived: year-over-year change of payloads launched (last 10 complete + current year). const growth = payloads .map((r, i) => { const cur = num(r.payloads) ?? 0; const prev = i > 0 ? (num(payloads[i - 1]?.payloads) ?? 0) : null; const pct = prev && prev > 0 ? ((cur - prev) / prev) * 100 : null; return { year: r.year, payloads: cur, prev, pct, active: num(r.still_active) ?? 0 }; }) .slice(-10) .reverse(); const currentYear = new Date().getUTCFullYear(); return (
Launches with at least one catalogued object (CelesTrak SATCAT, grouped by COSPAR launch id). The last bar is the current, incomplete year. Retired = payloads catalogued for that launch year − payloads still active today (derived from the two snapshot series). Objects with a published decay date in the SATCAT. Debris-only breakdown on /debris; recent reentries on{' '} /reentries. {growth.map((g) => ( ))}
Year Payloads launched Previous year YoY change Still active
{g.year} {g.year === currentYear && year to date} {fmtInt(g.payloads)} {g.prev === null ? '—' : fmtInt(g.prev)} {g.pct === null ? — : = 0 ? 'text-active' : 'text-danger'}>{g.pct >= 0 ? '+' : ''}{g.pct.toFixed(1)}%} {fmtInt(g.active)}
YoY change = (payloads launched in year − payloads launched the previous year) ÷ previous year, computed from the snapshot series. The current year is partial, so its change is not comparable.
); }