feat(scrobble): add pure Qualifies threshold function
This commit is contained in:
@@ -0,0 +1,15 @@
|
|||||||
|
// Package scrobble owns the outbound-scrobble pipeline: threshold detection,
|
||||||
|
// the queue write path, and the worker goroutine. The HTTP client is in
|
||||||
|
// internal/scrobble/listenbrainz; this package consumes it.
|
||||||
|
package scrobble
|
||||||
|
|
||||||
|
// Qualifies returns true if a closed play_event meets ListenBrainz's
|
||||||
|
// recommended scrobble threshold: ≥240 seconds played OR ≥50% of the
|
||||||
|
// track length played.
|
||||||
|
//
|
||||||
|
// The two thresholds are deliberately separate from M2's skip-detection
|
||||||
|
// thresholds (which serve a different purpose — internal engine signal
|
||||||
|
// for the scoring formula's skip penalty).
|
||||||
|
func Qualifies(durationPlayedMs int, completionRatio float64) bool {
|
||||||
|
return durationPlayedMs >= 240_000 || completionRatio >= 0.5
|
||||||
|
}
|
||||||
@@ -0,0 +1,42 @@
|
|||||||
|
package scrobble
|
||||||
|
|
||||||
|
import "testing"
|
||||||
|
|
||||||
|
func TestQualifies_NeverPlayed(t *testing.T) {
|
||||||
|
if Qualifies(0, 0) {
|
||||||
|
t.Error("0/0 should not qualify")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestQualifies_AtLeast240Seconds(t *testing.T) {
|
||||||
|
if !Qualifies(240_000, 0.0) {
|
||||||
|
t.Error("240_000 ms played should qualify regardless of ratio")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestQualifies_AtLeastHalfRatio(t *testing.T) {
|
||||||
|
if !Qualifies(0, 0.5) {
|
||||||
|
t.Error("ratio=0.5 should qualify regardless of duration")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestQualifies_BelowBoth(t *testing.T) {
|
||||||
|
if Qualifies(120_000, 0.49) {
|
||||||
|
t.Error("120s + 49% should not qualify")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestQualifies_BoundaryJustUnder(t *testing.T) {
|
||||||
|
if Qualifies(239_999, 0.4999) {
|
||||||
|
t.Error("just-under both thresholds should not qualify")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestQualifies_BoundaryExactly(t *testing.T) {
|
||||||
|
if !Qualifies(240_000, 0.4999) {
|
||||||
|
t.Error("exactly 240s should qualify")
|
||||||
|
}
|
||||||
|
if !Qualifies(239_999, 0.5) {
|
||||||
|
t.Error("exactly 50% should qualify")
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user