refactor(discover): both affinities weigh a watch by one rule

The YouTube channel affinity and the Plex one each had the recency decay, the undated-watch rule and
the scale to the strongest; app.draw now holds them. Tests hold that another user's history leans
neither draw, the rail's blind slot, and that a show leans on show recommendations.
This commit is contained in:
2026-11-07 21:48:38 +01:00
parent e7e8d8236e
commit bb91d0a22d
4 changed files with 99 additions and 27 deletions
+5 -9
View File
@@ -77,7 +77,8 @@ _FEED_BASE: dict = {
def _seeded(col, seed: int):
"""The feed's deterministic shuffle expression, reused for Plex so one seed moves both halves."""
"""The Home surprise's seeded order (md5 of the key and the seed), the same for Plex so one
seed moves both halves."""
return func.md5(func.concat(col, str(seed)))
@@ -188,14 +189,9 @@ def _channel_affinity(db: Session, user: User) -> dict[str, float]:
now = datetime.now(timezone.utc)
scores: dict[str, float] = {}
for channel_id, watched_at in rows:
age = (
(now - watched_at).total_seconds() / 86400 if watched_at else 2 * WATCHED_HALF_LIFE_DAYS
)
scores[channel_id] = scores.get(channel_id, 0.0) + 0.5 ** (
max(0.0, age) / WATCHED_HALF_LIFE_DAYS
)
top = max(scores.values(), default=0.0)
return {k: v / top for k, v in scores.items()} if top else {}
r = draw.recency(watched_at, now, WATCHED_HALF_LIFE_DAYS)
scores[channel_id] = scores.get(channel_id, 0.0) + r
return draw.scaled(scores)
def yt_video_row(db: Session, user: User, video_id: str) -> dict | None: