From a32df57496361ffd72c68e1e135439d0ec6ec87f Mon Sep 17 00:00:00 2001
From: Yuchen Pei <id@ypei.org>
Date: Mon, 6 Jan 2025 23:04:35 +1100
Subject: [emacs] Start emms scoring

When a track finishes, score up by 1. When a track is manually chosen,
set the score delta to 2.

Added a function my-emms-wrapped that prints the top 5 scored tracks.
---
 emacs/.emacs.d/lisp/my/my-emms.el | 48 +++++++++++++++++++++++++++++++++++----
 1 file changed, 44 insertions(+), 4 deletions(-)

(limited to 'emacs/.emacs.d/lisp/my')

diff --git a/emacs/.emacs.d/lisp/my/my-emms.el b/emacs/.emacs.d/lisp/my/my-emms.el
index 803ac0a..03392be 100644
--- a/emacs/.emacs.d/lisp/my/my-emms.el
+++ b/emacs/.emacs.d/lisp/my/my-emms.el
@@ -300,10 +300,23 @@ filter extensions from filter-exts."
 (defvar my-emms-i3bar-file (locate-user-emacs-file "emms-i3bar")
   "File to write current playing to which i3bar reads")
 (defun my-emms-get-display-name (track)
+  "Return the display name of a track.
+
+The display name is either the info-title, or the display name of
+the filename."
   (or (alist-get 'info-title track)
       (when-let ((name
                   (alist-get 'name track)))
-        (replace-regexp-in-string "^\\(.*/\\)\\(.*/.*/.*\\)" "\\2" name))))
+        (my-emms-get-display-name-1 name))))
+
+(defun my-emms-get-display-name-1 (name)
+  "Return the display name of a filename NAME.
+
+The display name is the last three components of the filename,
+assuming the filesystem hierarchy is arranged in
+artist/album/track."
+  (replace-regexp-in-string "^\\(.*/\\)\\(.*/.*/.*\\)" "\\2" name))
+
 (defun my-emms-output-current-track-to-i3bar-file ()
   (let ((current-track
          (my-emms-get-display-name (emms-playlist-current-selected-track))))
@@ -473,13 +486,40 @@ Hex-encoded characters in URLs are replaced by the decoded
 character."
   (let ((type (emms-track-type track)))
     (cond ((emms-track-get track 'description)
-	   (emms-track-get track 'description))
-	  ((eq 'file type)
-	   (emms-track-name track))
+	         (emms-track-get track 'description))
+	        ((eq 'file type)
+	         (emms-track-name track))
           ((eq 'url type)
            (emms-format-url-track-name (emms-track-name track)))
           (t (concat (symbol-name type)
                      ": " (emms-track-name track))))))
 
+(defvar my-emms-score-delta 1)
+
+(defun my-emms-score-up-playing ()
+  "Increase score by `my-emms-score-delta', then reset it to 1."
+  (emms-score-change-score
+   my-emms-score-delta
+   (my-emms-get-display-name-1 (emms-score-current-selected-track-filename)))
+  (setq my-emms-score-delta 1))
+
+(defun my-emms-score-up-chosen-bonus ()
+  "Bonus score up if the track is started intentionally.
+
+If the last command is `emms-playlist-mode-play-smart', then set
+`my-emms-score-delta' to 2."
+  (when (eq last-command 'emms-playlist-mode-play-smart)
+    (setq my-emms-score-delta 2)))
+
+(defun my-emms-wrapped ()
+  "Print top 5 scored tracks."
+  (interactive)
+  (let (keys)
+    (maphash (lambda (k _) (push k keys)) emms-score-hash)
+    (sort keys (lambda (k1 k2)
+                 (< (second (gethash k1 emms-score-hash))
+                    (second (gethash k2 emms-score-hash)))))
+    (message "Top 5: %s" (string-join (take 5 keys) "\n"))))
+
 (provide 'my-emms)
 ;;; my-emms.el ends here
-- 
cgit v1.2.3