diff --git a/backend/rating.go b/backend/rating.go index 012d95d..315b062 100644 --- a/backend/rating.go +++ b/backend/rating.go @@ -423,69 +423,7 @@ func ratingSignalSetHasInterestingContent(set ratingSignalSet) bool { func contextualSegmentSeverityWeight(label string) float64 { set := ratingSignalSetFromLabel(label) - - if !ratingSignalSetHasInterestingContent(set) { - return 0 - } - - var score float64 - - if set.HasPosition { - // Priorität: Position > Kleidung > Objekte (Kombination erhöht den Score). - score = - 0.66*set.Position + - 0.15*set.Body + - 0.12*set.Clothing + - 0.05*set.Object + - 0.02*set.Person - - if set.HasBody { - score += 0.055 - } - if set.HasClothing { - score += 0.030 - } - if set.HasObject { - score += 0.020 - } - if set.HasPerson { - score += 0.015 - } - - // Standing ohne Kontext bleibt schwach. - if set.Position < 0.60 && !set.HasBody && !set.HasObject && !set.HasClothing { - score = math.Min(score, 0.42) - } - - return ratingClamp01(score) - } - - score = - 0.54*set.Body + - 0.28*set.Clothing + - 0.16*set.Object + - 0.02*set.Person - - if set.HasBody && set.HasClothing { - score += 0.05 - } - if set.HasBody && set.HasObject { - score += 0.04 - } - if set.HasClothing && set.HasObject { - score += 0.03 - } - if set.HasPerson && (set.HasBody || set.HasObject || set.HasClothing) { - score += 0.015 - } - - if set.HasClothing && !set.HasBody && !set.HasObject { - score = math.Min(score, 0.38) - } - - score = math.Min(score, 0.72) - - return ratingClamp01(score) + return contextualSegmentSeverityWeightFromSet(set) } func comboSegmentSeverityWeight(label string) float64 { @@ -521,28 +459,31 @@ func contextualSegmentSeverityWeightFromSet(set ratingSignalSet) float64 { var score float64 if set.HasPosition { + // Position soll das Hauptkriterium sein. + // Kleidung/Objekte dürfen unterstützen, aber nicht das Rating tragen. score = - 0.66*set.Position + - 0.15*set.Body + - 0.12*set.Clothing + - 0.05*set.Object + + 0.82*set.Position + + 0.08*set.Body + + 0.05*set.Clothing + + 0.03*set.Object + 0.02*set.Person if set.HasBody { - score += 0.055 - } - if set.HasClothing { - score += 0.030 - } - if set.HasObject { score += 0.020 } - if set.HasPerson { + if set.HasClothing { score += 0.015 } + if set.HasObject { + score += 0.010 + } + if set.HasPerson { + score += 0.005 + } + // Standing ohne echten Kontext klar schwächer halten. if set.Position < 0.60 && !set.HasBody && !set.HasObject && !set.HasClothing { - score = math.Min(score, 0.42) + score = math.Min(score, 0.32) } return ratingClamp01(score) @@ -1071,19 +1012,27 @@ func mergeRatingActivitySegments( sev := ratingSegmentSeverity(label) start := b.start + end := b.end - // Wenn der finale Block eine Position trägt, soll die Anzeige/der Klick - // beim ersten echten Auftreten dieser Position starten — nicht schon bei - // früheren Body-/Object-Signalen aus demselben Aktivitätsblock. + // Wenn der finale Block eine Position trägt, soll der Block + // wirklich auf die echte Positions-Zeit gekürzt werden — + // nicht nur am Anfang, sondern auch am Ende. if bestPosition != "" { if bounds, ok := b.positionBounds[bestPosition]; ok && bounds.ok { if bounds.start > start { start = bounds.start } + if bounds.end < end { + end = bounds.end + } } } - dur = b.end - start + if end < start { + end = start + } + + dur = end - start if dur <= 0 { return aiSegmentMeta{}, false } @@ -1101,17 +1050,22 @@ func mergeRatingActivitySegments( score = 0.50 } + marker := b.marker + if marker < start || marker > end { + marker = (start + end) / 2 + } + return aiSegmentMeta{ Label: label, Score: ratingClamp01(score), StartSeconds: start, - EndSeconds: b.end, + EndSeconds: end, DurationSeconds: dur, AutoSelected: true, Position: segmentPositionFromAnalyzeLabel(label), Tags: segmentTagsFromAnalyzeLabel(label), - MarkerSeconds: b.marker, - PreviewSeconds: b.marker, + MarkerSeconds: marker, + PreviewSeconds: marker, }, true } @@ -1283,13 +1237,13 @@ func ratingExcellenceBonus( func starsFromHighlightScore(score float64) int { switch { - case score < 18: + case score < 24: return 1 - case score < 38: + case score < 48: return 2 - case score < 60: + case score < 72: return 3 - case score < 80: + case score < 90: return 4 default: return 5 @@ -1386,15 +1340,16 @@ func computeHighlightRatingWithUsername(segments []aiSegmentMeta, durationSec fl weightedDur := segDur * quality effectiveWeightedDur := effectiveDur * quality + set := ratingSignalSetFromLabel(s.Label) + if !set.HasPosition { + // Nur echte Positions-Segmente fließen ins Rating ein. + // Nicht-Positions-Segmente dürfen weder Coverage noch Flagged-Zeit erhöhen. + continue + } + totalFlagged += segDur totalWeighted += weightedDur - set := ratingSignalSetFromLabel(s.Label) - if !set.HasPosition { - // Nur Positions-Segmente fließen ins Rating ein. - // Kleidung und Objekte wirken über Combo-Segmente (position+clothing etc.). - continue - } positionEffectiveWeighted += effectiveWeightedDur positionFlagged += segDur