import type { Ranking, RankingRow } from "@dci/core"; import { DASH, fmtCompact, fmtInt, fmtMw } from "@/lib/format"; import { entityHref } from "@/lib/routes"; export const SCOPE_LABEL: Record = { countries: "Countries", metros: "Markets", operators: "Operators", facilities: "Facilities", }; export const SCOPE_ORDER: Ranking["scope"][] = ["countries", "metros", "operators", "facilities"]; /** Format a ranking value according to the ranking unit. */ export function fmtRankValue(v: number | null | undefined, unit: string): string { if (v === null || v === undefined || !Number.isFinite(v)) return DASH; const u = unit.toLowerCase(); if (u === "mw") return fmtMw(v); if (u.includes("per") || u.includes("kw") || u.includes("$")) return `${fmtCompact(v, 2)} ${unit}`; return fmtInt(v); } /** First sentence of the methodology text (for excerpts). */ export function firstSentence(text: string): string { const m = text.match(/^.*?[.!?](\s|$)/); return (m ? m[0] : text).trim(); } /** "Secondary: known MW." → "Known MW" */ export function secondaryLabel(methodology: string): string { const m = methodology.match(/Secondary:\s*([^.]+)\./i); if (!m) return "Secondary"; const s = m[1]!.trim(); return s.charAt(0).toUpperCase() + s.slice(1); } /** Site href for a ranking row — the API already returns a site path; fall back to entityHref. */ export function rowHref(row: RankingRow, scope: Ranking["scope"]): string { if (row.href && row.href.startsWith("/")) return row.href; const type = scope === "countries" ? "country" : scope === "metros" ? "metro" : scope === "operators" ? "operator" : "facility"; return entityHref(type, row.slug, row.name); }