diff --git a/Selector/Equality/UriEqual.cs b/Selector/Equality/UriEqual.cs index d561320..98df5c8 100644 --- a/Selector/Equality/UriEqual.cs +++ b/Selector/Equality/UriEqual.cs @@ -1,7 +1,4 @@ using System; -using System.Collections.Generic; -using System.Text; -using SpotifyAPI.Web; namespace Selector { diff --git a/Selector/Helpers/DateHelper.cs b/Selector/Helpers/DateHelper.cs index 2b25db4..26f6d0f 100644 --- a/Selector/Helpers/DateHelper.cs +++ b/Selector/Helpers/DateHelper.cs @@ -1,6 +1,4 @@ using System; -using System.Collections.Generic; -using System.Text; namespace Selector { diff --git a/Selector/Timeline/Interfaces/ITimeline.cs b/Selector/Timeline/Interfaces/ITimeline.cs index a06f1c2..80948ce 100644 --- a/Selector/Timeline/Interfaces/ITimeline.cs +++ b/Selector/Timeline/Interfaces/ITimeline.cs @@ -4,7 +4,7 @@ namespace Selector { public interface ITimeline { - public int Count { get; set; } + public int Count { get; } public T Get(DateTime at); public T Get(); public void Add(T item, DateTime timestamp); diff --git a/Selector/Timeline/PlayerTimeline.cs b/Selector/Timeline/PlayerTimeline.cs new file mode 100644 index 0000000..a79bf6f --- /dev/null +++ b/Selector/Timeline/PlayerTimeline.cs @@ -0,0 +1,122 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using SpotifyAPI.Web; + +namespace Selector +{ + public class PlayerTimeline : ITimeline + { + + private List> recentlyPlayed = new List>(); + public IEqual EqualityChecker { get; set; } + public bool SortOnBackDate { get; set; } + public int Count { get => recentlyPlayed.Count; } + + public void Add(CurrentlyPlayingContext item) => Add(item, DateHelper.FromUnixMilli(item.Timestamp)); + public void Add(CurrentlyPlayingContext item, DateTime timestamp) + { + recentlyPlayed.Add(new TimelineItem(){ + Item = item, + Time = timestamp + }); + + if (timestamp < recentlyPlayed.Last().Time && SortOnBackDate) + { + Sort(); + } + } + + public void Sort() + { + recentlyPlayed = recentlyPlayed + .OrderBy(i => i.Time) + .ToList(); + } + + public void Clear() => recentlyPlayed.Clear(); + + public CurrentlyPlayingContext Get() + => recentlyPlayed.Last().Item; + + public CurrentlyPlayingContext Get(DateTime at) + => GetTimelineItem(at)?.Item; + public TimelineItem GetTimelineItem(DateTime at) + => recentlyPlayed.Where(i => i.Time <= at).LastOrDefault(); + + public CurrentlyPlayingContext Get(FullTrack track) + => GetAll(track) + .LastOrDefault(); + + public IEnumerable GetAll(FullTrack track) + => GetAllTimelineItems(track) + .Select(t => t.Item); + + private IEnumerable> GetAllTimelineItems(FullTrack track) + => recentlyPlayed + .Where(i => i.Item.Item is FullTrack iterTrack + && EqualityChecker.IsEqual(iterTrack, track)); + + public CurrentlyPlayingContext Get(FullEpisode ep) + => GetAll(ep) + .LastOrDefault(); + + public IEnumerable GetAll(FullEpisode ep) + => GetAllTimelineItems(ep) + .Select(t => t.Item); + + private IEnumerable> GetAllTimelineItems(FullEpisode ep) + => recentlyPlayed + .Where(i => i.Item.Item is FullEpisode iterEp + && EqualityChecker.IsEqual(iterEp, ep)); + + public CurrentlyPlayingContext Get(SimpleAlbum album) + => GetAll(album) + .LastOrDefault(); + + public IEnumerable GetAll(SimpleAlbum album) + => GetAllTimelineItems(album) + .Select(t => t.Item); + + private IEnumerable> GetAllTimelineItems(SimpleAlbum album) + => recentlyPlayed + .Where(i => i.Item.Item is FullTrack iterTrack + && EqualityChecker.IsEqual(iterTrack.Album, album)); + + public CurrentlyPlayingContext Get(SimpleArtist artist) + => GetAll(artist) + .LastOrDefault(); + + public IEnumerable GetAll(SimpleArtist artist) + => GetAllTimelineItems(artist) + .Select(t => t.Item); + + private IEnumerable> GetAllTimelineItems(SimpleArtist artist) + => recentlyPlayed + .Where(i => i.Item.Item is FullTrack iterTrack + && EqualityChecker.IsEqual(iterTrack.Artists[0], artist)); + + public CurrentlyPlayingContext Get(Device device) + => GetAll(device) + .LastOrDefault(); + + public IEnumerable GetAll(Device device) + => GetAllTimelineItems(device) + .Select(t => t.Item); + + private IEnumerable> GetAllTimelineItems(Device device) + => recentlyPlayed.Where(i => EqualityChecker.IsEqual(i.Item.Device, device)); + + public CurrentlyPlayingContext Get(Context context) + => GetAll(context) + .LastOrDefault(); + + public IEnumerable GetAll(Context context) + => GetAllTimelineItems(context) + .Select(t => t.Item); + + private IEnumerable> GetAllTimelineItems(Context context) + => recentlyPlayed.Where(i => EqualityChecker.IsEqual(i.Item.Context, context)); + + } +} diff --git a/Selector/Timeline/Timeline.cs b/Selector/Timeline/Timeline.cs deleted file mode 100644 index e89d8ca..0000000 --- a/Selector/Timeline/Timeline.cs +++ /dev/null @@ -1,29 +0,0 @@ -using System; - -namespace Selector -{ - public class Timeline : ITimeline - { - public int Count { get => throw new NotImplementedException(); set => throw new NotImplementedException(); } - - public void Add(T item, DateTime timestamp) - { - throw new NotImplementedException(); - } - - public void Clear() - { - throw new NotImplementedException(); - } - - public T Get(DateTime at) - { - throw new NotImplementedException(); - } - - public T Get() - { - throw new NotImplementedException(); - } - } -} diff --git a/Selector/Watcher/PlayerWatcher.cs b/Selector/Watcher/PlayerWatcher.cs index 83438ce..4964b11 100644 --- a/Selector/Watcher/PlayerWatcher.cs +++ b/Selector/Watcher/PlayerWatcher.cs @@ -22,18 +22,15 @@ namespace Selector public event EventHandler PlayingChange; public CurrentlyPlayingContext Live { get; private set; } - public ITimeline Past { get; private set; } - private List> lastPlays { get; set; } + public PlayerTimeline Past { get; private set; } public PlayerWatcher(IPlayerClient spotifyClient, IEqual equalityChecker, int pollPeriod = 3000) { this.spotifyClient = spotifyClient; - this.eq = equalityChecker; - this.PollPeriod = pollPeriod; - - lastPlays = new List>(); + eq = equalityChecker; + PollPeriod = pollPeriod; } public override async Task WatchOne() @@ -41,7 +38,7 @@ namespace Selector try{ var polledCurrent = await spotifyClient.GetCurrentPlayback(); - if (polledCurrent != null) StoreCurrentPlaying(Live, polledCurrent); + if (polledCurrent != null) StoreCurrentPlaying(polledCurrent); // swap new item into live and bump existing down to previous CurrentlyPlayingContext previous; @@ -78,15 +75,15 @@ namespace Selector if(previous.Item is FullTrack previousTrack && Live.Item is FullTrack currentTrack) { - if(!eq.IsEqual(previousTrack, currentTrack)) { + if(!eq.IsEqual(previousTrack, currentTrack)) { OnItemChange(ListeningChangeEventArgs.From(previous, Live)); } - if(!eq.IsEqual(previousTrack.Album, currentTrack.Album)) { + if(!eq.IsEqual(previousTrack.Album, currentTrack.Album)) { OnAlbumChange(ListeningChangeEventArgs.From(previous, Live)); } - if(!eq.IsEqual(previousTrack.Artists[0], currentTrack.Artists[0])) { + if(!eq.IsEqual(previousTrack.Artists[0], currentTrack.Artists[0])) { OnArtistChange(ListeningChangeEventArgs.From(previous, Live)); } } @@ -100,7 +97,7 @@ namespace Selector // PODCASTS else if(previous.Item is FullEpisode previousEp && Live.Item is FullEpisode currentEp) { - if(!eq.IsEqual(previousEp, currentEp)) { + if(!eq.IsEqual(previousEp, currentEp)) { OnItemChange(ListeningChangeEventArgs.From(previous, Live)); } } @@ -109,12 +106,12 @@ namespace Selector } // CONTEXT - if(!eq.IsEqual(previous.Context, Live.Context)) { + if(!eq.IsEqual(previous.Context, Live.Context)) { OnContextChange(ListeningChangeEventArgs.From(previous, Live)); } // DEVICE - if(!eq.IsEqual(previous?.Device, Live?.Device)) { + if(!eq.IsEqual(previous?.Device, Live?.Device)) { OnDeviceChange(ListeningChangeEventArgs.From(previous, Live)); } @@ -148,53 +145,12 @@ namespace Selector /// Store currently playing in last plays. Determine whether new list or appending required /// /// New currently playing to store - private void StoreCurrentPlaying(CurrentlyPlayingContext previous, CurrentlyPlayingContext current) + private void StoreCurrentPlaying(CurrentlyPlayingContext current) { - if(lastPlays.Count > 0) - { - bool matchesMostRecent; - - try { - var castItem = (FullTrack) current.Item; - var castStoredItem = (FullTrack) lastPlays[0][0].Item; - - matchesMostRecent = eq.IsEqual(castItem, castStoredItem); - } - catch(InvalidCastException) - { - var castItem = (FullEpisode) current.Item; - var castStoredItem = (FullEpisode) lastPlays[0][0].Item; - - matchesMostRecent = eq.IsEqual(castItem, castStoredItem); - } - - if (matchesMostRecent) - { - lastPlays[0].Add(current); - } - else - { - StoreNewTrack(previous, current); - } - } - else { - StoreNewTrack(previous, current); - } - } - - /// - /// Store currently playing at front of last plays list. Pushes new list to hold same track - /// - /// New currently playing to store - private void StoreNewTrack(CurrentlyPlayingContext previous, CurrentlyPlayingContext current) - { - if (previous != null) { - var newPlayingList = new List(); - newPlayingList.Add(previous); - lastPlays.Insert(0, newPlayingList); - } + Past?.Add(current); } + #region Event Firers protected virtual void OnItemChange(ListeningChangeEventArgs args) { ItemChange?.Invoke(this, args); @@ -234,5 +190,7 @@ namespace Selector { PlayingChange?.Invoke(this, args); } + + #endregion } }