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";
}