Popular Picks: fix empty result for deezer (popularity threshold scale mismatch)

The discovery pool synthesizes deezer popularity onto a 0-100 score (base 45 + bonuses, capped at 100), but _get_popularity_thresholds had deezer on the raw-rank scale (500000/100000). So Popular Picks' 'popularity >= 500000' matched nothing — empty for every deezer-primary user — while Hidden Gems' '< 100000' caught the whole pool. Deezer thresholds now sit on the 0-100 scale (60/50, like Spotify's 60/40). Tested.
This commit is contained in:
BoulderBadgeDad 2026-06-25 16:30:52 -07:00
parent 30ff0bde49
commit c033656fdf
2 changed files with 42 additions and 2 deletions

View file

@ -111,7 +111,10 @@ class PersonalizedPlaylistsService:
Either value can be None to skip that filter for that source.
- Spotify: 60 / 40 (the existing 0-100 popularity scale)
- Deezer: 500000 / 100000 (rank values ballpark from real data)
- Deezer: 60 / 50 (ALSO 0-100 the discovery pool SYNTHESIZES deezer popularity to a
0-100 score at scan time, capped at 100; it is NOT Deezer's raw rank. The old
500000/100000 rank thresholds matched nothing, so Popular Picks came back empty for
deezer users while Hidden Gems' < 100000 caught the whole pool.)
- iTunes / others: None / None (no popularity data; fall back to no
threshold filter, just diversity-on-random)
@ -121,7 +124,7 @@ class PersonalizedPlaylistsService:
if normalized == 'spotify':
return 60, 40
if normalized == 'deezer':
return 500_000, 100_000
return 60, 50
# iTunes, hydrabase, anything else — no usable popularity data
return None, None

View file

@ -0,0 +1,37 @@
"""Popular Picks was empty for deezer users — wrong popularity-threshold scale.
The discovery pool synthesizes deezer popularity onto a 0-100 score (base 45 + bonuses, capped
at 100), but _get_popularity_thresholds had deezer on the raw-rank scale (500000/100000). So
`popularity >= 500000` matched nothing (Popular Picks empty) while `< 100000` matched the whole
pool (Hidden Gems caught everything). Thresholds must stay on the 0-100 scale.
"""
from __future__ import annotations
from core.personalized_playlists import PersonalizedPlaylistsService
def _svc():
return PersonalizedPlaylistsService(database=None)
def test_deezer_thresholds_are_on_the_0_100_scale():
popular_min, hidden_max = _svc()._get_popularity_thresholds('deezer')
assert (popular_min, hidden_max) == (60, 50) # was (500000, 100000) — unreachable
assert 0 < popular_min <= 100 and 0 < hidden_max <= 100
assert popular_min > hidden_max # popular tier sits above the hidden tier
def test_spotify_thresholds_unchanged():
assert _svc()._get_popularity_thresholds('spotify') == (60, 40)
def test_case_insensitive():
assert _svc()._get_popularity_thresholds('Deezer') == (60, 50)
assert _svc()._get_popularity_thresholds('SPOTIFY') == (60, 40)
def test_sources_without_popularity_skip_the_filter():
assert _svc()._get_popularity_thresholds('itunes') == (None, None)
assert _svc()._get_popularity_thresholds('musicbrainz') == (None, None)
assert _svc()._get_popularity_thresholds('') == (None, None)