Skip to content

Commit

Permalink
2024.49
Browse files Browse the repository at this point in the history
- Broadcasting and Observing for log messages
  • Loading branch information
simon-techkid committed Jun 18, 2024
1 parent 285116e commit 62c11b0
Show file tree
Hide file tree
Showing 53 changed files with 482 additions and 158 deletions.
6 changes: 4 additions & 2 deletions SpotifyGPX/ArgumentParser.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
// SpotifyGPX by Simon Field

using SpotifyGPX.Broadcasting;
using System;
using System.Collections.Generic;

Expand Down Expand Up @@ -39,8 +40,9 @@ public static (Dictionary<string, string> options, HashSet<string> flags) Parse(
return (options, flags);
}

public static void PrintHelp()
public static void PrintHelp(Broadcaster bcast)
{
Console.WriteLine(Help);
bcast.Type = "HELP";
bcast.Broadcast(Help);
}
}
78 changes: 78 additions & 0 deletions SpotifyGPX/Broadcasting/Broadcaster.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
// SpotifyGPX by Simon Field

using System;
using System.Collections.Generic;

namespace SpotifyGPX.Broadcasting;

public class Broadcaster
{
public List<IObserver<string>> Observers { get; set; }

public string Type { get; set; }

public Broadcaster()
{
Type = "INFO";
Observers = new();
}

public void Broadcast(string message)
{
foreach (var observer in Observers)
{
observer.OnNext($"[{Type}] {message}");
}
}

public void BroadcastError(Exception error)
{
foreach (var observer in Observers)
{
observer.OnError(error);
}
}

public void BroadcastCompletion()
{
foreach (var observer in Observers)
{
observer.OnCompleted();
}
}

public IDisposable Subscribe(IObserver<string> observer)
{
if (!Observers.Contains(observer))
{
Observers.Add(observer);
}

IDisposable? additional = observer as IDisposable ?? null;

return new Unsubscriber(observer, Observers, additional);
}

private class Unsubscriber : IDisposable
{
private IObserver<string> _observer;
private List<IObserver<string>> _observers;
private IDisposable? _additional;

public Unsubscriber(IObserver<string> observer, List<IObserver<string>> observers, IDisposable? additional)
{
_observer = observer;
_observers = observers;
_additional = additional;
}

public void Dispose()
{
if (_observer != null && _observers.Contains(_observer))
{
_additional?.Dispose();
_observers.Remove(_observer);
}
}
}
}
23 changes: 23 additions & 0 deletions SpotifyGPX/Broadcasting/BroadcasterBase.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
// SpotifyGPX by Simon Field

using System;

namespace SpotifyGPX.Broadcasting;

public abstract class BroadcasterBase : IObservable<string>
{
public Broadcaster BCaster { get; }

protected BroadcasterBase(Broadcaster bCaster)
{
BCaster = bCaster;
BCaster.Type = BroadcasterPrefix;
}

protected abstract string BroadcasterPrefix { get; }

public IDisposable Subscribe(IObserver<string> observer)
{
return BCaster.Subscribe(observer);
}
}
5 changes: 4 additions & 1 deletion SpotifyGPX/DisposableBase.cs
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
// SpotifyGPX by Simon Field

using SpotifyGPX.Broadcasting;
using System;

namespace SpotifyGPX;

public abstract class DisposableBase : IDisposable
public abstract class DisposableBase : BroadcasterBase, IDisposable
{
protected DisposableBase(Broadcaster bcast) : base(bcast) { }

/// <summary>
/// Indicates whether the class has been disposed of.
/// </summary>
Expand Down
28 changes: 16 additions & 12 deletions SpotifyGPX/DupeHandler.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
// SpotifyGPX by Simon Field

using SpotifyGPX.Broadcasting;
using System;
using System.Collections.Generic;
using System.Linq;
Expand All @@ -9,15 +10,18 @@ namespace SpotifyGPX;
/// <summary>
/// Handle duplicate coordinate placements by shifting them to other locations.
/// </summary>
public partial class DupeHandler
public partial class DupeHandler : BroadcasterBase
{
private List<SongPoint> Pairs { get; }

/// <summary>
/// Create a handler for duplicate positions.
/// </summary>
/// <param name="pairs">A list of pairs to be searched for duplicate positions.</param>
public DupeHandler(List<SongPoint> pairs) => Pairs = pairs;
public DupeHandler(List<SongPoint> pairs, Broadcaster bcast) : base(bcast)
{
Pairs = pairs;
}

/// <summary>
/// Run prediction (dupe calculation) using the pairs list this DupeHandler was initialized with.
Expand All @@ -28,11 +32,11 @@ public List<SongPoint> GetDupes(bool autoPredict)
{
if (Pairs.Count < MinimumMatchingCoords)
{
Console.WriteLine($"[PRED] Point prediction cannot be run when there are less than {MinimumMatchingCoords} pairs");
BCaster.Broadcast($"Point prediction cannot be run when there are less than {MinimumMatchingCoords} pairs");
return Pairs;
}

Console.WriteLine($"[PRED] Autopredict is {(autoPredict == true ? "enabled, automatically predicting" : "disabled, you will be prompted")}");
BCaster.Broadcast($"Autopredict is {(autoPredict == true ? "enabled, automatically predicting" : "disabled, you will be prompted")}");
return PredictPoints(autoPredict);
}

Expand All @@ -43,7 +47,7 @@ public List<SongPoint> GetDupes(bool autoPredict)
/// <returns>The original pairs list, with duplicate coordinates shifted.</returns>
private List<SongPoint> PredictPoints(bool autoPredict)
{
Console.WriteLine("[PRED] Scanning for duplicate entries:");
BCaster.Broadcast("Scanning for duplicate entries:");
var dupes = GroupDuplicates();
PrintDuplicates(dupes);

Expand Down Expand Up @@ -93,7 +97,7 @@ private List<SongPoint> PredictPoints(bool autoPredict)

bool isValidInput = false;

Console.Write("[DUPE] Write the start and end indexes (separated by a dash) of each of your dupes, with dupes separated by commas: ");
BCaster.Broadcast("Write the start and end indexes (separated by a dash) of each of your dupes, with dupes separated by commas: ");
while (!isValidInput)
{
string dupeDefinition = Console.ReadLine() ?? string.Empty;
Expand All @@ -110,19 +114,19 @@ private List<SongPoint> PredictPoints(bool autoPredict)
{
if (startIndex < 0 || startIndex >= Pairs.Count)
{
Console.WriteLine($"Invalid startIndex: {startIndex}. Must be between 0 and {maximumAllowedIndex}.");
BCaster.Broadcast($"Invalid startIndex: {startIndex}. Must be between 0 and {maximumAllowedIndex}.");
isValidInput = false;
break;
}
else if (endIndex < 0 || endIndex >= Pairs.Count)
{
Console.WriteLine($"Invalid endIndex: {endIndex}. Must be between 0 and {maximumAllowedIndex}.");
BCaster.Broadcast($"Invalid endIndex: {endIndex}. Must be between 0 and {maximumAllowedIndex}.");
isValidInput = false;
break;
}
else if (endIndex - startIndex == 0)
{
Console.WriteLine($"Invalid range: {startIndex}-{endIndex}. Range must include at least one element.");
BCaster.Broadcast($"Invalid range: {startIndex}-{endIndex}. Range must include at least one element.");
isValidInput = false;
break;
}
Expand All @@ -132,7 +136,7 @@ private List<SongPoint> PredictPoints(bool autoPredict)
}
else
{
Console.WriteLine($"Invalid input: '{dupe}'. Please enter start and end indexes separated by a dash.");
BCaster.Broadcast($"Invalid input: '{dupe}'. Please enter start and end indexes separated by a dash.");
isValidInput = false;
break;
}
Expand Down Expand Up @@ -262,12 +266,12 @@ private List<IGrouping<Coordinate, SongPoint>> GroupDuplicates()
/// Prints each group of shared-coordinate pairs to the console.
/// </summary>
/// <param name="dupes">An IGrouping, with TKey as Coordinate (the shared coordinate), and TElement as SongPoint (the SongPoint implicated).</param>
private static void PrintDuplicates(List<IGrouping<Coordinate, SongPoint>> dupes)
private void PrintDuplicates(List<IGrouping<Coordinate, SongPoint>> dupes)
{
foreach (var dupe in dupes)
{
string g = string.Join(", ", dupe.Select(s => $"{s.Song.Song_Name} ({s.Index})"));
Console.WriteLine($"[DUPE {dupes.IndexOf(dupe)}] {g}");
BCaster.Broadcast($"[{dupes.IndexOf(dupe)}] {g}");
}
}

Expand Down
13 changes: 10 additions & 3 deletions SpotifyGPX/EasterEggs.cs
Original file line number Diff line number Diff line change
@@ -1,13 +1,18 @@
// SpotifyGPX by Simon Field

using SpotifyGPX.Broadcasting;
using System;
using System.Linq;
using System.Collections.Generic;
using System.Linq;

namespace SpotifyGPX;

public abstract class EasterEggs<T>
public abstract class EasterEggs<T> : BroadcasterBase
{
protected EasterEggs(Broadcaster bcast) : base(bcast) { }

protected override string BroadcasterPrefix => "EGG";

/// <summary>
/// Defines the conditions for Easter eggs of type <typeparamref name="T"/>.
/// </summary>
Expand Down Expand Up @@ -44,7 +49,7 @@ public void CheckAllPairsForEggs(IEnumerable<SongPoint> points)
var eggString = EggAsString(point);
if (foundEggs.Add(eggString))
{
Console.WriteLine($"[EGG] You found an egg: {eggString}. You've got a great taste in {Taste}!");
BCaster.Broadcast($"You found an egg: {eggString}. You've got a great taste in {Taste}!");
}
}
}
Expand All @@ -65,6 +70,8 @@ public void CheckAllPairsForEggs(IEnumerable<SongPoint> points)

public class SongEasterEggs : EasterEggs<ISongEntry>
{
public SongEasterEggs(Broadcaster bcast) : base(bcast) { }

protected override Func<ISongEntry, bool>[] EggParameters => new Func<ISongEntry, bool>[]
{
song => song.Song_Name == "Hello" && song.Song_Artist == "Adele",
Expand Down
4 changes: 3 additions & 1 deletion SpotifyGPX/Input/Csv.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
// SpotifyGPX by Simon Field

using SpotifyGPX.Broadcasting;
using System;
using System.Collections.Generic;
using System.IO;
Expand All @@ -12,10 +13,11 @@ public sealed partial class Csv : SongInputBase
{
private static readonly Regex CSVRegex = MyRegex();
private string[] Document { get; set; }
protected override string FormatName => nameof(Csv);
public override List<ISongEntry> ParseSongsMethod() => ParseSongs();
public override List<ISongEntry> FilterSongsMethod() => FilterSongs();

public Csv(string path) : base(path)
public Csv(string path, Broadcaster bcast) : base(path, bcast)
{
Document = ReadAllLines();
}
Expand Down
10 changes: 9 additions & 1 deletion SpotifyGPX/Input/FileInputBase.cs
Original file line number Diff line number Diff line change
@@ -1,17 +1,25 @@
// SpotifyGPX by Simon Field

using SpotifyGPX.Broadcasting;
using System.IO;

namespace SpotifyGPX.Input;

public abstract class FileInputBase : DisposableBase
{
protected FileInputBase(string path)
protected FileInputBase(string path, Broadcaster bcaster) : base(bcaster)
{
FileStream = new FileStream(path, FileMode.Open, FileAccess.Read);
StreamReader = new StreamReader(FileStream);
}

/// <summary>
/// The name of the file format.
/// </summary>
protected abstract string FormatName { get; }

protected override string BroadcasterPrefix => $"INP, {FormatName.ToUpper()}";

/// <summary>
/// Serves as the reading stream for a file on the disk.
/// </summary>
Expand Down
6 changes: 4 additions & 2 deletions SpotifyGPX/Input/GeoJson.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
// SpotifyGPX by Simon Field

using SpotifyGPX.Broadcasting;
using System;
using System.Collections.Generic;
using System.Linq;
Expand All @@ -10,12 +11,13 @@ namespace SpotifyGPX.Input;
public sealed partial class GeoJson : GpsInputBase
{
private JsonDocument Document { get; }
protected override string FormatName => nameof(GeoJson);
public override List<GpsTrack> ParseTracksMethod() => ParseTracks();
public override List<GpsTrack> FilterTracksMethod() => FilterTracks();

public GeoJson(string path) : base(path)
public GeoJson(string path, Broadcaster bcast) : base(path, bcast)
{
using JsonNetDeserializer deserializer = new(path);
using JsonNetDeserializer deserializer = new(path, bcast);
Document = deserializer.GetDocument();
}

Expand Down
3 changes: 2 additions & 1 deletion SpotifyGPX/Input/GpsInputBase.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
// SpotifyGPX by Simon Field

using SpotifyGPX.Broadcasting;
using System.Collections.Generic;
using System.Linq;

Expand All @@ -10,7 +11,7 @@ namespace SpotifyGPX.Input;
/// </summary>
public abstract class GpsInputBase : FileInputBase, IGpsInput
{
protected GpsInputBase(string path) : base(path)
protected GpsInputBase(string path, Broadcaster bcast) : base(path, bcast)
{
}

Expand Down
4 changes: 3 additions & 1 deletion SpotifyGPX/Input/Gpx.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
// SpotifyGPX by Simon Field

using SpotifyGPX.Broadcasting;
using System;
using System.Collections.Generic;
using System.Linq;
Expand All @@ -10,10 +11,11 @@ namespace SpotifyGPX.Input;
public sealed partial class Gpx : GpsInputBase
{
private XDocument Document { get; set; }
protected override string FormatName => nameof(Gpx);
public override List<GpsTrack> ParseTracksMethod() => ParseTracks();
public override List<GpsTrack> FilterTracksMethod() => FilterTracks();

public Gpx(string path) : base(path)
public Gpx(string path, Broadcaster bcast) : base(path, bcast)
{
Document = XDocument.Load(StreamReader, loadOptions);
}
Expand Down
Loading

0 comments on commit 62c11b0

Please sign in to comment.