/** * Prueft die Monitor-Auswertung gegen konstruierte Faelle mit von Hand * ausgerechnetem Sollwert. Die Rechnung landet als Verfuegbarkeitsaussage im * Kundendokument — sie muss stimmen, nicht plausibel aussehen. */ // Laedt die TS-Datei direkt (Node 22.6+ entfernt die Typannotationen selbst). // Vorher stand hier der Pfad einer von Hand erzeugten .mjs-Kopie in einem // Sitzungsverzeichnis unter /tmp — nach dessen Wegfall lief dieser Pruefer // nicht mehr, waehrend im Repo "alle Faelle korrekt" stand. const { buildMonitorMeasurement } = await import('../src/lib/monitor-auswertung.ts'); const T0 = new Date('2026-08-16T09:00:00').getTime(); const min = (m) => T0 + m * 60000; const faelle = [ { name: 'Alles stabil, 60 min, 2 Geraete', s: { startedAt: T0, intervalSec: 30, targets: [{ip:'192.168.1.10',label:'Router'},{ip:'192.168.1.51',label:'Kamera Hof'}], events: [] }, ende: min(60), soll: { verf: 100, aussetzer: 0, status: 0 }, }, { name: 'Kamera 6 min weg (2 Ausfaelle) in 60 min -> 90 %', s: { startedAt: T0, intervalSec: 30, targets: [{ip:'192.168.1.51',label:'Kamera Hof'}], events: [ {ip:'192.168.1.51',ts:min(10),type:'down'}, {ip:'192.168.1.51',ts:min(13),type:'up'}, {ip:'192.168.1.51',ts:min(40),type:'down'}, {ip:'192.168.1.51',ts:min(43),type:'up'}, ]}, ende: min(60), soll: { verf: 90, aussetzer: 2, status: 2 }, // 6 von 60 min weg }, { name: 'DURCHGEHEND TOT (Start-Ereignis) -> 0 %, nicht 100 %', s: { startedAt: T0, intervalSec: 30, targets: [{ip:'192.168.1.51',label:'Kamera Hof'}], events: [{ip:'192.168.1.51',ts:T0,type:'down'}]}, ende: min(60), soll: { verf: 0, aussetzer: 1, status: 2 }, }, { name: 'Beim Beenden NOCH OFFENER Ausfall (letzte 15 von 60 min)', s: { startedAt: T0, intervalSec: 30, targets: [{ip:'192.168.1.51',label:'Kamera Hof'}], events: [{ip:'192.168.1.51',ts:min(45),type:'down'}]}, ende: min(60), soll: { verf: 75, aussetzer: 1, status: 2 }, }, { name: 'Ein totes Geraet unter neun gesunden (schlechtestes zaehlt)', s: { startedAt: T0, intervalSec: 30, targets: [...Array(9)].map((_,i)=>({ip:`192.168.1.${20+i}`,label:`PC ${i+1}`})) .concat([{ip:'192.168.1.51',label:'Kamera Hof'}]), events: [{ip:'192.168.1.51',ts:T0,type:'down'}]}, ende: min(60), soll: { verf: 0, aussetzer: 1, status: 2 }, }, { name: 'Ein kurzer Aussetzer (30 s in 60 min) -> gelb, nicht rot', s: { startedAt: T0, intervalSec: 30, targets: [{ip:'192.168.1.51',label:'Kamera Hof'}], events: [ {ip:'192.168.1.51',ts:min(20),type:'down'}, {ip:'192.168.1.51',ts:min(20.5),type:'up'}, ]}, ende: min(60), soll: { verf: 99.2, aussetzer: 1, status: 1 }, }, ]; let fehler = 0; for (const f of faelle) { const r = buildMonitorMeasurement(f.s, f.ende, false); const verf = r.result.verfuegbarkeitProzent; const aus = r.result.aussetzer; const st = r.measureStatus; const ok = Math.abs(verf - f.soll.verf) < 0.15 && aus === f.soll.aussetzer && st === f.soll.status; if (!ok) fehler++; console.log(`${ok ? 'OK ' : 'FEHL'} ${f.name}`); console.log(` verf=${verf} (soll ${f.soll.verf}) aussetzer=${aus} (soll ${f.soll.aussetzer}) status=${st} (soll ${f.soll.status})`); console.log(` Label: ${r.label}`); if (r.result.geraete.length <= 3) r.result.geraete.forEach(g => console.log(' ', g)); console.log(); } console.log(fehler === 0 ? 'ALLE FAELLE KORREKT' : `${fehler} FEHLER`);