From 649e5bde9b158c50e88f8489d114419ef3bc4a35 Mon Sep 17 00:00:00 2001 From: Caleb Allen Date: Mon, 30 Mar 2026 03:32:24 -0400 Subject: [PATCH] fix: use 100K reference floor for popularity normalization MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When maxPop=0 (no artist has index/LB popularity data), blendedScore returned raw relevance (0-1), making Score = MB_score directly. Shannon Hale (MB 83, zero listens) scored 92 after tier adjustment and ranked #4 — above Shannon Wright (MB 80, 766K real listens but not in index). Now blendedScore uses max(maxPop, 100K) as the normalization denominator. With zero popularity against a 100K reference, the 60% popularity component contributes near-zero, dropping all zero-pop artists to ~35-40. This ensures unpopular artists can't dominate through MB text relevance alone when the index lacks data. --- backend/explore/explore.go | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/backend/explore/explore.go b/backend/explore/explore.go index 377c38f..4cda340 100644 --- a/backend/explore/explore.go +++ b/backend/explore/explore.go @@ -1372,11 +1372,15 @@ func rerankReleaseGroups(rgs []MBReleaseGroup, pop map[string]int) { // relevance is 0–1. listenCount is raw; maxListenCount is the // maximum in the result set (for normalization). func blendedScore(relevance float64, listenCount, maxListenCount int) float64 { - if maxListenCount <= 0 { - return relevance + // Use a floor for maxListenCount so that zero-popularity artists + // don't get a free pass when no result has popularity data. + // 100K is a reasonable "average popular artist" reference point. + effectiveMax := maxListenCount + if effectiveMax < 100_000 { //nolint:mnd + effectiveMax = 100_000 } - logPop := math.Log10(float64(listenCount)+1) / math.Log10(float64(maxListenCount)+1) + logPop := math.Log10(float64(listenCount)+1) / math.Log10(float64(effectiveMax)+1) return relevanceWeight*relevance + popularityWeight*logPop }