package main import ( "math" "strings" ) func setJobProgress(job *RecordJob, phase string, pct int) { phase = strings.TrimSpace(phase) phaseLower := strings.ToLower(phase) // clamp pct 0..100 if pct < 0 { pct = 0 } if pct > 100 { pct = 100 } // "globale" Zielbereiche pro Phase (dein Pipeline-Modell) // postwork wartet: 70..72 // remuxing: 72..78 // moving: 78..84 // probe: 84..86 // assets: 86..99 type rng struct{ start, end int } rangeFor := func(ph string) rng { switch ph { case "postwork": return rng{0, 5} case "remuxing": return rng{5, 65} case "moving": return rng{65, 75} case "probe": return rng{75, 80} case "assets": return rng{80, 99} default: return rng{0, 100} } } jobsMu.Lock() defer jobsMu.Unlock() // Sobald Postwork läuft oder Aufnahme beendet ist -> Recorder darf NICHTS mehr überschreiben. inPostwork := job.EndedAt != nil || (strings.TrimSpace(job.Phase) != "" && strings.ToLower(strings.TrimSpace(job.Phase)) != "recording") if inPostwork { // harte Blockade: alte recording-Updates dürfen weder Phase noch Progress anfassen if phaseLower == "" || phaseLower == "recording" { return } } // Phase aktualisieren (aber nur wenn nicht leer) if phase != "" { job.Phase = phase } // ✅ Sonderfall: "wartet auf Nachbearbeitung" => Progress bleibt 0% // Erwartung: Caller sendet phase="postwork" und pct=0 solange nur gewartet wird. // Muss vor "niemals rückwärts" passieren, sonst käme man von Recording-Progress nicht mehr auf 0. if phaseLower == "postwork" && pct == 0 { job.Progress = 0 return } // Progress-Logik: // - wenn wir in Postwork sind und jemand phasenlokale 0..100 liefert (z.B. remuxing 25), // mappe das in den globalen Bereich der Phase. // - danach: niemals rückwärts. mapped := pct if inPostwork { r := rangeFor(phaseLower) if r.end >= r.start { // Heuristik: // - Wenn pct bereits im globalen Bereich der Phase liegt => als global interpretieren, clampen. // - Sonst => als lokales 0..100 interpretieren und in [start..end] mappen. if pct >= r.start && pct <= r.end { // schon global mapped = pct } else { // lokal 0..100 -> global width := float64(r.end - r.start) mapped = r.start + int(math.Round((float64(pct)/100.0)*width)) } // clamp in den Bereich if mapped < r.start { mapped = r.start } if mapped > r.end { mapped = r.end } } } // niemals rückwärts if mapped < job.Progress { mapped = job.Progress } job.Progress = mapped }