From a58a34e2191698d436180f0503c82ca7b3df44f7 Mon Sep 17 00:00:00 2001 From: Pixirora Date: Wed, 6 Nov 2024 18:28:39 -0500 Subject: [PATCH] Send scrobble events at 66% listen time instead of when the track ends --- .../kit_tunes/api/event/TrackMiddleEvent.java | 15 ++++++++++ .../api/listener/MusicEventListener.java | 4 +++ .../kitten_heart/impl/Constants.java | 3 ++ .../kitten_heart/impl/EventHandling.java | 13 +++++++++ .../impl/event/TrackEventImpl.java | 3 +- .../listener/ScrobblingMusicListener.java | 29 ++++++++----------- .../impl/music/progress/PlayingSong.java | 19 ++++++++++++ 7 files changed, 68 insertions(+), 18 deletions(-) create mode 100644 projects/kit-tunes-api/src/main/java/net/pixaurora/kit_tunes/api/event/TrackMiddleEvent.java diff --git a/projects/kit-tunes-api/src/main/java/net/pixaurora/kit_tunes/api/event/TrackMiddleEvent.java b/projects/kit-tunes-api/src/main/java/net/pixaurora/kit_tunes/api/event/TrackMiddleEvent.java new file mode 100644 index 00000000..d21ac9f2 --- /dev/null +++ b/projects/kit-tunes-api/src/main/java/net/pixaurora/kit_tunes/api/event/TrackMiddleEvent.java @@ -0,0 +1,15 @@ +package net.pixaurora.kit_tunes.api.event; + +import java.util.Optional; + +import net.pixaurora.kit_tunes.api.music.ListeningProgress; +import net.pixaurora.kit_tunes.api.music.Track; +import net.pixaurora.kit_tunes.api.resource.ResourcePath; + +public interface TrackMiddleEvent { + public Optional track(); + + public ResourcePath searchPath(); + + public ListeningProgress progress(); +} diff --git a/projects/kit-tunes-api/src/main/java/net/pixaurora/kit_tunes/api/listener/MusicEventListener.java b/projects/kit-tunes-api/src/main/java/net/pixaurora/kit_tunes/api/listener/MusicEventListener.java index ae8a895d..348610b6 100644 --- a/projects/kit-tunes-api/src/main/java/net/pixaurora/kit_tunes/api/listener/MusicEventListener.java +++ b/projects/kit-tunes-api/src/main/java/net/pixaurora/kit_tunes/api/listener/MusicEventListener.java @@ -1,12 +1,16 @@ package net.pixaurora.kit_tunes.api.listener; import net.pixaurora.kit_tunes.api.event.TrackEndEvent; +import net.pixaurora.kit_tunes.api.event.TrackMiddleEvent; import net.pixaurora.kit_tunes.api.event.TrackStartEvent; public interface MusicEventListener { public default void onTrackStart(TrackStartEvent event) { } + public default void onTrackMiddleReached(TrackMiddleEvent event) { + } + public default void onTrackEnd(TrackEndEvent event) { } diff --git a/projects/kitten-heart/src/main/java/net/pixaurora/kitten_heart/impl/Constants.java b/projects/kitten-heart/src/main/java/net/pixaurora/kitten_heart/impl/Constants.java index 1868849e..ead9ebe6 100644 --- a/projects/kitten-heart/src/main/java/net/pixaurora/kitten_heart/impl/Constants.java +++ b/projects/kitten-heart/src/main/java/net/pixaurora/kitten_heart/impl/Constants.java @@ -1,6 +1,7 @@ package net.pixaurora.kitten_heart.impl; import java.nio.file.Path; +import java.time.Duration; import org.quiltmc.loader.api.ModContainer; import org.quiltmc.loader.api.ModMetadata; @@ -15,6 +16,8 @@ public abstract class Constants { public static final Path SCROBBLER_CACHE_PATH = CACHE_PATH.resolve("scrobblers.json"); public static final Path LISTEN_HISTORY_PATH = CACHE_PATH.resolve("history.json"); + public static final Duration MINIMUM_TIME_TO_SCROBBLE = Duration.ofMinutes(1); + static { ModContainer mod = QuiltLoader.getModContainer(MOD_ID).get(); // Should never be null, since we're running from // in this mod. diff --git a/projects/kitten-heart/src/main/java/net/pixaurora/kitten_heart/impl/EventHandling.java b/projects/kitten-heart/src/main/java/net/pixaurora/kitten_heart/impl/EventHandling.java index 2917f186..b5e578b4 100644 --- a/projects/kitten-heart/src/main/java/net/pixaurora/kitten_heart/impl/EventHandling.java +++ b/projects/kitten-heart/src/main/java/net/pixaurora/kitten_heart/impl/EventHandling.java @@ -66,6 +66,19 @@ public static void tick() { MAIN_THREAD_TASKS.clear(); } + + synchronized (PLAYING_TRACKS) { + for (PlayingSong song : PLAYING_TRACKS.values()) { + if (song.sentMiddleEvent()) { + continue; + } + + if (song.canSendMiddleEvent()) { + processEvent(listener -> listener + .onTrackMiddleReached(new TrackEventImpl(song.path(), song.track(), song.progress()))); + } + } + } } public static void addMainThreadTask(Runnable task) { diff --git a/projects/kitten-heart/src/main/java/net/pixaurora/kitten_heart/impl/event/TrackEventImpl.java b/projects/kitten-heart/src/main/java/net/pixaurora/kitten_heart/impl/event/TrackEventImpl.java index 5523c0a6..934c380d 100644 --- a/projects/kitten-heart/src/main/java/net/pixaurora/kitten_heart/impl/event/TrackEventImpl.java +++ b/projects/kitten-heart/src/main/java/net/pixaurora/kitten_heart/impl/event/TrackEventImpl.java @@ -3,12 +3,13 @@ import java.util.Optional; import net.pixaurora.kit_tunes.api.event.TrackEndEvent; +import net.pixaurora.kit_tunes.api.event.TrackMiddleEvent; import net.pixaurora.kit_tunes.api.event.TrackStartEvent; import net.pixaurora.kit_tunes.api.music.ListeningProgress; import net.pixaurora.kit_tunes.api.music.Track; import net.pixaurora.kit_tunes.api.resource.ResourcePath; -public class TrackEventImpl implements TrackStartEvent, TrackEndEvent { +public class TrackEventImpl implements TrackStartEvent, TrackMiddleEvent, TrackEndEvent { private final ResourcePath path; private final Optional track; private final ListeningProgress progress; diff --git a/projects/kitten-heart/src/main/java/net/pixaurora/kitten_heart/impl/listener/ScrobblingMusicListener.java b/projects/kitten-heart/src/main/java/net/pixaurora/kitten_heart/impl/listener/ScrobblingMusicListener.java index 320d21f6..f0d13a21 100644 --- a/projects/kitten-heart/src/main/java/net/pixaurora/kitten_heart/impl/listener/ScrobblingMusicListener.java +++ b/projects/kitten-heart/src/main/java/net/pixaurora/kitten_heart/impl/listener/ScrobblingMusicListener.java @@ -1,9 +1,9 @@ package net.pixaurora.kitten_heart.impl.listener; import java.io.IOException; -import java.time.Duration; import net.pixaurora.kit_tunes.api.event.TrackEndEvent; +import net.pixaurora.kit_tunes.api.event.TrackMiddleEvent; import net.pixaurora.kit_tunes.api.event.TrackStartEvent; import net.pixaurora.kit_tunes.api.listener.MusicEventListener; import net.pixaurora.kit_tunes.api.music.ListeningProgress; @@ -28,29 +28,25 @@ public void onTrackStart(TrackStartEvent event) { } @Override - public void onTrackEnd(TrackEndEvent event) { + public void onTrackMiddleReached(TrackMiddleEvent event) { if (!event.track().isPresent()) { return; } - Track track = event.track().get(); - ListeningProgress progress = event.progress(); + ListenRecord record = new ListenRecord(event.track().get(), event.progress()); - ListenRecord record = new ListenRecord(track, progress); + KitTunes.SCROBBLER_CACHE + .execute(scrobblers -> scrobblers.completeScrobbling(KitTunes.CLIENT, record)); + } - Duration requiredLength = track.duration().dividedBy(2); - boolean longEnoughToScrobble = progress.amountPlayed().compareTo(requiredLength) > 0; - - if (longEnoughToScrobble) { - KitTunes.SCROBBLER_CACHE - .execute(scrobblers -> scrobblers.completeScrobbling(KitTunes.CLIENT, record)); - } else { - float amountPlayed = (float) progress.amountPlayed().toMillis() / 1000; - float amountRequired = (float) requiredLength.toMillis() / 1000; - KitTunes.LOGGER.info("Skipping scrobbling " + track.name() + " because it only played for " + - amountPlayed + " out of " + amountRequired + " seconds!"); + @Override + public void onTrackEnd(TrackEndEvent event) { + if (!event.track().isPresent()) { + return; } + ListenRecord record = new ListenRecord(event.track().get(), event.progress()); + KitTunes.LISTEN_HISTORY.execute(history -> history.record(record)); try { KitTunes.LISTEN_HISTORY.save(); @@ -58,5 +54,4 @@ public void onTrackEnd(TrackEndEvent event) { KitTunes.LOGGER.error("Failed to save listen history while scrobbling!", e); } } - } diff --git a/projects/kitten-heart/src/main/java/net/pixaurora/kitten_heart/impl/music/progress/PlayingSong.java b/projects/kitten-heart/src/main/java/net/pixaurora/kitten_heart/impl/music/progress/PlayingSong.java index 60206865..54fb5c0c 100644 --- a/projects/kitten-heart/src/main/java/net/pixaurora/kitten_heart/impl/music/progress/PlayingSong.java +++ b/projects/kitten-heart/src/main/java/net/pixaurora/kitten_heart/impl/music/progress/PlayingSong.java @@ -6,6 +6,7 @@ import net.pixaurora.kit_tunes.api.music.ListeningProgress; import net.pixaurora.kit_tunes.api.music.Track; import net.pixaurora.kit_tunes.api.resource.ResourcePath; +import net.pixaurora.kitten_heart.impl.Constants; import net.pixaurora.kitten_heart.impl.music.control.MusicControls; import net.pixaurora.kitten_heart.impl.ui.widget.progress.ProgressProvider; @@ -16,11 +17,16 @@ public class PlayingSong implements ProgressProvider { private final ListeningProgress progress; private final MusicControls controls; + private boolean hasSentMiddleEvent; + private final long middleEventMillis; + public PlayingSong(ResourcePath path, Optional track, ListeningProgress progress, MusicControls controls) { this.path = path; this.track = track; this.progress = progress; this.controls = controls; + this.middleEventMillis = track.map(Track::duration).map(duration -> duration.toMillis() * 6 / 10) + .orElse(Constants.MINIMUM_TIME_TO_SCROBBLE.toMillis()); } public ResourcePath path() { @@ -39,6 +45,19 @@ public MusicControls controls() { return this.controls; } + public boolean sentMiddleEvent() { + return this.hasSentMiddleEvent; + } + + public boolean canSendMiddleEvent() { + if (this.middleEventMillis < this.progress.amountPlayed().toMillis()) { + this.hasSentMiddleEvent = true; + return true; + } else { + return false; + } + } + @Override public double percentComplete() { return (double) this.playedDuration().toMillis() / this.totalDuration().toMillis();