// Reine Anzeige-Logik der Cockpit-Seiten — getrennt von den Komponenten, damit sie ohne // DOM testbar bleibt und Vites Hot-Reload die Komponenten-Dateien sauber tauschen kann. import type { UpdateDetails } from "./abfragen" import type { Modell, Start } from "./typen" // --- Rundinstrument ----------------------------------------------------------------- // 240°-Bogen wie ein Zeigerinstrument, Mittelpunkt (100|95) in einer 200×150-Zeichnung. const MX = 100 const MY = 95 const START = 210 // Grad, links unten const SPANNE = 240 function punkt(grad: number, r: number): [number, number] { const rad = (grad * Math.PI) / 180 return [MX + r * Math.cos(rad), MY - r * Math.sin(rad)] } const r2 = (n: number) => Math.round(n * 100) / 100 /** SVG-Pfad eines Bogens von Anteil `von` bis `bis` (0…1) auf Radius `r`. */ export function bogenPfad(von: number, bis: number, r: number): string { const a = Math.max(0, Math.min(1, von)) const b = Math.max(a, Math.min(1, bis)) const [x0, y0] = punkt(START - SPANNE * a, r) const [x1, y1] = punkt(START - SPANNE * b, r) const gross = (b - a) * SPANNE > 180 ? 1 : 0 return `M ${r2(x0)} ${r2(y0)} A ${r} ${r} 0 ${gross} 1 ${r2(x1)} ${r2(y1)}` } /** Farbe der Temperatur: grün bis 70 °C, dann Bernstein, ab 85 °C rot. */ export function temperaturFarbe(grad: number | null | undefined) { if (grad == null) return "var(--text-3)" if (grad >= 85) return "var(--rot)" if (grad >= 70) return "var(--bernstein)" return "var(--gruen)" } // --- Hauptwarnleuchte --------------------------------------------------------------- /** Was die Hauptwarnleuchte sagt. Der schweigende Wächter geht allem anderen vor. */ export function hauptleuchte(z: Start["zustand"]) { if (!z.waechter_wach) { return { art: "stumm" as const, oben: "Wächter", mitte: "SCHWEIGT", unten: "Seit über 5 Minuten kein Prüflauf" } } if (z.update_laeuft) { return { art: "info" as const, oben: "Wartung", mitte: "UPDATE LÄUFT", unten: "Hinweise ruhen bis zum Ende" } } if (z.anzahl === 0) { return { art: "ok" as const, oben: "Alles", mitte: "IN ORDNUNG", unten: "Keine offenen Hinweise" } } const mitte = `${z.anzahl} HINWEIS${z.anzahl === 1 ? "" : "E"}` return z.stufe === "rot" ? { art: "rot" as const, oben: "Störung", mitte, unten: "Drücken zum Ansehen" } : { art: "gelb" as const, oben: "Achtung", mitte, unten: "Drücken zum Ansehen" } } // --- Updates ------------------------------------------------------------------------ /** „Läuft“ und „Neu“ aus den Update-Details lesbar machen. */ export function versionen(id: string, d: UpdateDetails | undefined): { laeuft: string; neu: string | null } { if (!d) return { laeuft: "…", neu: null } if (id === "os") return { laeuft: "Ubuntu", neu: d.count ? `${d.count} Pakete` : null } // Hermes kommt aus git: „Neu“ ist die Zahl der Änderungen seit dem eingespielten Stand. if (id === "hermes") { return { laeuft: d.installed_version ? `v${d.installed_version}` : "–", neu: d.behind ? `+${d.behind.toLocaleString("de-DE")} Änderungen` : null, } } const pre = id === "engine" ? "b" : "v" const laeuft = d.installed_build != null ? `${pre}${d.installed_build}` : "–" const neuer = d.latest_build != null && d.installed_build != null && d.latest_build > d.installed_build return { laeuft, neu: neuer ? `${pre}${d.latest_build}` : null } } // --- Modelle ------------------------------------------------------------------------ /** Rolle eines Modells aus seinen llama-swap-Aliasen. */ export function rolleVon(m: Modell): "hirn" | "coder" | null { const a = m.aliases.map((x) => x.toLowerCase()) if (a.includes("hermes") || a.includes("fast")) return "hirn" if (a.includes("coder")) return "coder" return null } // --- Modell-Radar --------------------------------------------------------------------- /** Status eines Radar-Kandidaten in Worten fürs Cockpit. */ export const RADAR_STATUS_TEXT: Record = { neu: "Neu", wartet: "Wartet", getestet: "Gemessen", bestanden: "Bestanden", durchgefallen: "Durchgefallen", uebernommen: "Übernommen", verworfen: "Verworfen", } /** Messwert des Radar-Vergleichs lesbar machen (Zahlen deutsch, eine Nachkommastelle). */ export function messwert(wert: unknown, einheit = ""): string { if (wert == null || wert === "") return "–" const text = typeof wert === "number" ? wert.toLocaleString("de-DE", { maximumFractionDigits: wert < 10 ? 1 : 0 }) : String(wert) return einheit ? `${text} ${einheit}` : text }