about summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorBenedikt Peetz <benedikt.peetz@b-peetz.de>2026-02-19 22:39:09 +0100
committerBenedikt Peetz <benedikt.peetz@b-peetz.de>2026-02-19 22:39:09 +0100
commit9c6cb50906b5b504e9a4afd0259d9384562cd43d (patch)
tree6e08052818674d7d7c752bb09cd9768d8fbd1429
parentpkgs/mpdpopmd: Make the {positive,neutral,negative} chances configurable (diff)
downloadnixos-config-9c6cb50906b5b504e9a4afd0259d9384562cd43d.zip
pkgs/mpdpopmd: Also consider the `last_played` sticker when calculating weights
Diffstat (limited to '')
-rw-r--r--pkgs/by-name/mp/mpdpopm/src/dj/algorithms.rs48
1 files changed, 43 insertions, 5 deletions
diff --git a/pkgs/by-name/mp/mpdpopm/src/dj/algorithms.rs b/pkgs/by-name/mp/mpdpopm/src/dj/algorithms.rs
index fcb7a88d..c002f055 100644
--- a/pkgs/by-name/mp/mpdpopm/src/dj/algorithms.rs
+++ b/pkgs/by-name/mp/mpdpopm/src/dj/algorithms.rs
@@ -1,7 +1,10 @@
-use std::collections::HashSet;
+use std::{
+    collections::HashSet,
+    time::{Duration, SystemTime},
+};
 
 use anyhow::{Context, Result};
-use rand::{Rng, distr, seq::SliceRandom};
+use rand::{Rng, distr};
 use tracing::info;
 
 use crate::{clients::Client, storage};
@@ -149,15 +152,50 @@ impl Discovery {
     /// dislikes to a lower number.
     /// Currently, only the rating, skip count and play count are considered. Similarity scores,
     /// fetched from e.g. last.fm should be included in the future.
-    async fn weight_track(client: &mut Client, track: &str) -> Result<i64> {
+    pub async fn weight_track(client: &mut Client, track: &str) -> Result<i64> {
+        let last_played_delta = {
+            let last_played = storage::last_played::get(client, track).await?.unwrap_or(0);
+            let now = SystemTime::now()
+                .duration_since(SystemTime::UNIX_EPOCH)
+                .expect("to be before")
+                .as_secs();
+
+            let played_seconds_ago = now - last_played;
+
+            const HOUR: u64 = Duration::from_hours(1).as_secs();
+            const DAY: u64 = Duration::from_hours(24).as_secs();
+            const MONTH: u64 = Duration::from_hours(24 * 30).as_secs();
+
+            match played_seconds_ago {
+                ..HOUR => {
+                    // it was played in the last hour already
+                    -3
+                }
+                HOUR..DAY => {
+                    // it was not played in the last hour, but in the last day
+                    -2
+                }
+                DAY..MONTH => {
+                    // it was not played in the last day, but in the last month
+                    -1
+                }
+                MONTH.. => {
+                    // it was not played in a month
+                    1
+                }
+            }
+        };
+
         let rating = i32::from(storage::rating::get(client, track).await?.unwrap_or(0));
         let play_count = i32::try_from(storage::play_count::get(client, track).await?.unwrap_or(0))
             .context("`play_count` too big")?;
         let skip_count = i32::try_from(storage::skip_count::get(client, track).await?.unwrap_or(0))
             .context("`skip_count` too big")?;
 
-        let output: f64 =
-            1.0 * f64::from(rating) + 0.3 * f64::from(play_count) + -0.6 * f64::from(skip_count);
+        let output: f64 = 1.0 * f64::from(rating)
+            + 0.3 * f64::from(play_count)
+            + -0.6 * f64::from(skip_count)
+            + 0.65 * f64::from(last_played_delta);
 
         let weight = output.round() as i64;