import { fmtInt, num } from '@/lib/format'; import type { EntitySummary } from '@/lib/types'; /* Hardware helpers shared by /hardware, /hardware/frontier and /hardware/[slug]. Attributes are read as published; nothing is inferred. */ export const HW_KINDS = ['gpu', 'accelerator', 'npu', 'cpu', 'soc', 'system', 'server', 'workstation', 'cloud-instance'] as const; export const HW_KIND_LABELS: Record = { gpu: 'GPU', accelerator: 'Accelerator', npu: 'NPU', cpu: 'CPU', soc: 'SoC', system: 'System', server: 'Server', workstation: 'Workstation', 'cloud-instance': 'Cloud instance', computer: 'Computer' }; /** memory_gb may be a number or a list of configurations → [min, max] or null. */ export function memoryRange(v: unknown): [number, number] | null { if (Array.isArray(v)) { const xs = v.map(num).filter((x): x is number => x !== null); return xs.length ? [Math.min(...xs), Math.max(...xs)] : null; } const n = num(v); return n === null ? null : [n, n]; } export function memoryOptions(v: unknown): number[] { if (Array.isArray(v)) return v.map(num).filter((x): x is number => x !== null).sort((a, b) => a - b); const n = num(v); return n === null ? [] : [n]; } export function fmtMemory(v: unknown): string { const r = memoryRange(v); if (!r) return '—'; return r[0] === r[1] ? `${fmtInt(r[0])} GB` : `${fmtInt(r[0])}–${fmtInt(r[1])} GB`; } export function str(v: unknown): string | null { return typeof v === 'string' && v.trim() ? v : null; } export function list(v: unknown): string[] { return Array.isArray(v) ? v.filter((x) => x !== null && x !== undefined).map(String) : []; } /** Precision support as published (`precision_support`, `precisions`, `supported_precisions`, `dtypes`). */ export function precisions(a: Record): string[] { for (const k of ['precision_support', 'precisions', 'supported_precisions', 'dtypes']) { const l = list(a[k]); if (l.length) return l; } return []; } export function interconnect(a: Record): string | null { for (const k of ['interconnect', 'interconnect_bandwidth_gbs', 'nvlink_bandwidth_gbs', 'fabric']) { const v = a[k]; if (typeof v === 'string' && v.trim()) return v; if (num(v) !== null) return `${fmtInt(v)} GB/s`; } return null; } export function releaseOf(e: EntitySummary): string | null { return str(e.attributes?.release_date) ?? str(e.attributes?.announced_at) ?? null; } /** Sort key for a release: "2024", "2024-10" or full date → ms; null when absent. */ export function releaseMs(r: string | null): number | null { if (!r) return null; const t = new Date(r.length === 4 ? `${r}-07-01T00:00:00Z` : r.length === 7 ? `${r}-15T00:00:00Z` : r.length === 10 ? `${r}T00:00:00Z` : r).getTime(); return Number.isNaN(t) ? null : t; }