From 7e8a9d1e29d943802a20db9bdf6ba8dd7ee57a3c Mon Sep 17 00:00:00 2001 From: Andy Pack <andy@sarsoo.xyz> Date: Mon, 31 Mar 2025 21:34:30 +0100 Subject: [PATCH] moving resampler --- Selector/Listen/Resampler.cs | 130 +++++++++++++++++++++++++++++++++ Selector/Scrobble/Resampler.cs | 130 --------------------------------- 2 files changed, 130 insertions(+), 130 deletions(-) create mode 100644 Selector/Listen/Resampler.cs delete mode 100644 Selector/Scrobble/Resampler.cs diff --git a/Selector/Listen/Resampler.cs b/Selector/Listen/Resampler.cs new file mode 100644 index 0000000..1a4db69 --- /dev/null +++ b/Selector/Listen/Resampler.cs @@ -0,0 +1,130 @@ +using System; +using System.Collections.Generic; +using System.Linq; + +namespace Selector +{ + public record struct CountSample + { + public DateTime TimeStamp { get; set; } + public int Value { get; set; } + } + + public static class Resampler + { + public static IEnumerable<CountSample> Resample(this IEnumerable<IListen> scrobbles, TimeSpan window) + { + var sortedScrobbles = scrobbles.OrderBy(s => s.Timestamp).ToList(); + + if (!sortedScrobbles.Any()) + { + yield break; + } + + var sortedScrobblesIter = sortedScrobbles.GetEnumerator(); + sortedScrobblesIter.MoveNext(); + + var earliest = sortedScrobbles.First().Timestamp; + var latest = sortedScrobbles.Last().Timestamp; + + yield return new CountSample() + { + TimeStamp = earliest - (window / 2), + Value = 0 + }; + + var enumeratorExhausted = false; + + for (var windowStart = earliest; windowStart <= latest; windowStart += window) + { + var windowEnd = windowStart + window; + + var count = 0; + var windowOverran = false; + + while (!windowOverran && !enumeratorExhausted) + { + if (windowStart <= sortedScrobblesIter.Current.Timestamp) + { + if (sortedScrobblesIter.Current.Timestamp < windowEnd) + { + count++; + if (!sortedScrobblesIter.MoveNext()) + { + enumeratorExhausted = true; + } + } + else + { + windowOverran = true; + } + } + } + + yield return new CountSample() + { + TimeStamp = windowStart + (window / 2), + Value = count + }; + } + } + + public static IEnumerable<CountSample> ResampleByMonth(this IEnumerable<IListen> scrobbles) + { + var sortedScrobbles = scrobbles.OrderBy(s => s.Timestamp).ToList(); + + if (!sortedScrobbles.Any()) + { + yield break; + } + + var sortedScrobblesIter = sortedScrobbles.GetEnumerator(); + sortedScrobblesIter.MoveNext(); + + var earliest = sortedScrobbles.First().Timestamp; + var latest = sortedScrobbles.Last().Timestamp; + var latestPlusMonth = latest.AddMonths(1); + + var periodStart = new DateTime(earliest.Year, earliest.Month, 1); + var periodEnd = new DateTime(latestPlusMonth.Year, latestPlusMonth.Month, 1); + + for (var counter = periodStart; counter <= periodEnd; counter = counter.AddMonths(1)) + { + var count = 0; + + if (sortedScrobblesIter.Current is not null) + { + count++; + } + + while (sortedScrobblesIter.MoveNext() + && sortedScrobblesIter.Current.Timestamp.Year == counter.Year + && sortedScrobblesIter.Current.Timestamp.Month == counter.Month) + { + count++; + } + + yield return new CountSample() + { + TimeStamp = counter, + Value = count + }; + } + } + + public static IEnumerable<CountSample> CumulativeSum(this IEnumerable<CountSample> samples) + { + var sum = 0; + foreach (var sample in samples) + { + sum += sample.Value; + + yield return new CountSample + { + TimeStamp = sample.TimeStamp, + Value = sum + }; + } + } + } +} \ No newline at end of file diff --git a/Selector/Scrobble/Resampler.cs b/Selector/Scrobble/Resampler.cs deleted file mode 100644 index 7289d15..0000000 --- a/Selector/Scrobble/Resampler.cs +++ /dev/null @@ -1,130 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; - -namespace Selector -{ - public record struct CountSample { - public DateTime TimeStamp { get; set; } - public int Value { get; set; } - } - - public static class Resampler - { - public static IEnumerable<CountSample> Resample(this IEnumerable<IListen> scrobbles, TimeSpan window) - { - var sortedScrobbles = scrobbles.OrderBy(s => s.Timestamp).ToList(); - - if (!sortedScrobbles.Any()) - { - yield break; - } - - var sortedScrobblesIter = sortedScrobbles.GetEnumerator(); - sortedScrobblesIter.MoveNext(); - - var earliest = sortedScrobbles.First().Timestamp; - var latest = sortedScrobbles.Last().Timestamp; - - yield return new CountSample() - { - TimeStamp = earliest - (window / 2), - Value = 0 - }; - - var enumeratorExhausted = false; - - for (var windowStart = earliest; windowStart <= latest; windowStart += window) - { - var windowEnd = windowStart + window; - - var count = 0; - var windowOverran = false; - - while(!windowOverran && !enumeratorExhausted) - { - if (windowStart <= sortedScrobblesIter.Current.Timestamp) - { - if(sortedScrobblesIter.Current.Timestamp < windowEnd) - { - count++; - if (!sortedScrobblesIter.MoveNext()) - { - enumeratorExhausted = true; - } - } - else - { - windowOverran = true; - } - } - } - - yield return new CountSample() - { - TimeStamp = windowStart + (window / 2), - Value = count - }; - } - } - - public static IEnumerable<CountSample> ResampleByMonth(this IEnumerable<IListen> scrobbles) - { - var sortedScrobbles = scrobbles.OrderBy(s => s.Timestamp).ToList(); - - if (!sortedScrobbles.Any()) - { - yield break; - } - - var sortedScrobblesIter = sortedScrobbles.GetEnumerator(); - sortedScrobblesIter.MoveNext(); - - var earliest = sortedScrobbles.First().Timestamp; - var latest = sortedScrobbles.Last().Timestamp; - var latestPlusMonth = latest.AddMonths(1); - - var periodStart = new DateTime(earliest.Year, earliest.Month, 1); - var periodEnd = new DateTime(latestPlusMonth.Year, latestPlusMonth.Month, 1); - - for (var counter = periodStart; counter <= periodEnd; counter = counter.AddMonths(1)) - { - var count = 0; - - if (sortedScrobblesIter.Current is not null) - { - count++; - } - - while (sortedScrobblesIter.MoveNext() - && sortedScrobblesIter.Current.Timestamp.Year == counter.Year - && sortedScrobblesIter.Current.Timestamp.Month == counter.Month) - { - count++; - } - - yield return new CountSample() - { - TimeStamp = counter, - Value = count - }; - } - } - - public static IEnumerable<CountSample> CumulativeSum(this IEnumerable<CountSample> samples) - { - var sum = 0; - foreach(var sample in samples) - { - sum += sample.Value; - - yield return new CountSample - { - TimeStamp = sample.TimeStamp, - Value = sum - }; - } - } - } -} -