File size: 1,499 Bytes
e6a1f55 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 | import { type ClassValue, clsx } from "clsx";
import { twMerge } from "tailwind-merge";
export function cn(...inputs: ClassValue[]): string {
return twMerge(clsx(inputs));
}
/** Map a confidence in [0, 1] to a tailwind text color tier. */
export function confidenceColor(
conf: number,
prediction: "real" | "fake" | "uncertain"
): string {
if (prediction === "uncertain") {
return "text-warn";
}
if (prediction === "fake") {
if (conf >= 0.85) return "text-danger";
if (conf >= 0.6) return "text-warn";
return "text-ink-dim";
}
if (conf >= 0.85) return "text-cyber";
if (conf >= 0.6) return "text-warn";
return "text-ink-dim";
}
export function formatMs(ms: number): string {
if (ms < 1) return `${(ms * 1000).toFixed(0)} µs`;
if (ms < 1000) return `${ms.toFixed(0)} ms`;
return `${(ms / 1000).toFixed(2)} s`;
}
export function formatPercent(value: number, digits = 1): string {
return `${(value * 100).toFixed(digits)}%`;
}
export function formatParams(k?: number | null): string {
if (k == null) return "—";
if (k >= 1_000_000) return `${(k / 1_000_000).toFixed(1)}B`;
if (k >= 1_000) return `${(k / 1_000).toFixed(0)}M`;
return `${k}K`;
}
export function classifyStatus(status: string): "live" | "fallback" | "error" | "loading" {
const s = status.toLowerCase();
if (s === "live") return "live";
if (s.startsWith("architecture_only_fallback")) return "fallback";
if (s.startsWith("error")) return "error";
return "loading";
}
|