// Die Vorgangs-Leiste (5.6.0, Commander: „Phase 1–4 plus Komprimierung — // irgendwie zu einem machen, der Phasen-Balken gefällt mir") — EIN Weg für // jede Disc, vier Stationen: Titel lesen → Rippen → Komprimieren → Ablegen, // bei Bedarf das Rettungs-Abbild als Zwischenstation vor dem Rippen. Die // Leiste zeigt immer den GANZEN Weg, aber nur an einer Stelle die Details: // in der Laufwerks-Kachel, solange das Laufwerk arbeitet (Stationen 1–2), // in der Kompressions-Karte danach (3–4), im Verlauf als Punkte. // // Hier liegt die REINE Logik (welche Station ist fertig, aktiv, offen, // gescheitert) — testbar ohne React; gezeichnet wird in // fenster/uebersicht/VorgangsLeiste.tsx. import type { KompressionStand, RipStatus, VorgangEintrag } from './nachrichten' export type Station = 'titel' | 'rettung' | 'rip' | 'kompression' | 'ablage' export type LeisteZustand = 'laeuft' | 'wartet' | 'fertig' | 'fehler' | 'abgebrochen' export type StationsZustand = 'fertig' | 'aktiv' | 'offen' | 'fehler' export interface LeisteStand { station: Station zustand: LeisteZustand /** 0–100 in der aktiven Station, -1 = keine Angabe. */ prozent: number /** Das Rettungs-Abbild als Zwischenstation zeigen. */ rettung: boolean /** Kurztext in der aktiven Station („Platz 2", „läuft — Karte unten"). */ hinweis: string } export const STATIONS_NAMEN: Record = { titel: 'Titel lesen', rettung: 'Rettungs-Abbild', rip: 'Rippen', kompression: 'Komprimieren', ablage: 'Ablegen', } export function stationen(rettung: boolean): Station[] { return rettung ? ['titel', 'rettung', 'rip', 'kompression', 'ablage'] : ['titel', 'rip', 'kompression', 'ablage'] } /** Zustand je Station: alles vor der aktiven ist fertig, die aktive läuft * (oder ist gescheitert), alles danach ist offen. `fertig` = alle gold. */ export function stationsZustand(liste: readonly Station[], station: Station, zustand: LeisteZustand): StationsZustand[] { const i = liste.indexOf(station) return liste.map((_, k) => { if (zustand === 'fertig') return 'fertig' if (k < i) return 'fertig' if (k === i) return zustand === 'fehler' || zustand === 'abgebrochen' ? 'fehler' : 'aktiv' return 'offen' }) } function stand(station: Station, zustand: LeisteZustand, prozent = -1, rettung = false, hinweis = ''): LeisteStand { return { station, zustand, prozent, rettung, hinweis } } /** Die Leiste in der Laufwerks-Kachel: aus dem Rip-Stand und — nach dem * Rip — aus dem Vorgang (ohne Prozent: die Details stehen in der * Kompressions-Karte). */ export function leisteAusRip( rip: Pick, vorgang: Pick | undefined, wartePlatz: number, ): LeisteStand { const rettung = rip.phase === 'rettet' || rip.rettung !== undefined switch (rip.phase) { case 'liest-info': return stand('titel', 'laeuft', -1, rettung) case 'rettet': return stand('rettung', 'laeuft', rip.prozent, true) case 'rippt': return stand('rip', 'laeuft', rip.prozent, rettung) case 'komprimiert': return stand('kompression', 'laeuft', rip.prozent, rettung) case 'legt-ab': return stand('ablage', 'laeuft', rip.prozent, rettung) case 'fehler': return stand('rip', 'fehler', -1, rettung) case 'abgebrochen': return stand('rip', 'abgebrochen', -1, rettung) case 'fertig': break } // Der Rip ist durch — wo steht der Vorgang? if (vorgang === undefined) return stand('kompression', 'wartet', -1, rettung, 'eingereiht') switch (vorgang.phase) { case 'rippt': return stand('rip', 'laeuft', -1, rettung) case 'wartet': return stand('kompression', 'wartet', -1, rettung, wartePlatz > 0 ? `Platz ${wartePlatz}` : 'wartet') case 'komprimiert': return stand('kompression', 'laeuft', -1, rettung, 'läuft — Karte unten') case 'legt-ab': return stand('ablage', 'laeuft', -1, rettung, 'läuft — Karte unten') case 'fertig': return stand('ablage', 'fertig', 100, rettung) case 'fehler': return stand('kompression', 'fehler', -1, rettung) case 'abgebrochen': return stand('kompression', 'abgebrochen', -1, rettung) } } /** Die Leiste eines Vorgangs im Verlauf (kompakt). Bei Fehlern ohne * Roh-Bytes scheiterte schon der Rip, sonst die Kompression. */ export function leisteAusVorgang(v: Pick): LeisteStand { switch (v.phase) { case 'rippt': return stand('rip', 'laeuft') case 'wartet': return stand('kompression', 'wartet', -1, false, 'wartet') case 'komprimiert': return stand('kompression', 'laeuft') case 'legt-ab': return stand('ablage', 'laeuft') case 'fertig': return stand('ablage', 'fertig', 100) case 'fehler': return stand(v.rohBytes > 0 ? 'kompression' : 'rip', 'fehler') case 'abgebrochen': return stand(v.rohBytes > 0 ? 'kompression' : 'rip', 'abgebrochen') } } /** Die Leiste in der Kompressions-Karte: Stationen 1–2 sind fertig. */ export function leisteAusKompression(k: Pick): LeisteStand { switch (k.phase) { case 'legt-ab': return stand('ablage', 'laeuft', k.prozent) case 'wartet': return stand('kompression', 'wartet', -1, false, 'wartet') case 'fertig': return stand('ablage', 'fertig', 100) case 'fehler': return stand('kompression', 'fehler') case 'abgebrochen': return stand('kompression', 'abgebrochen') case 'rippt': return stand('rip', 'laeuft', k.prozent) case 'komprimiert': return stand('kompression', 'laeuft', k.prozent) } }