Hook up fswatcher to csv parser, needs proper filename parsing.
This commit is contained in:
		| @@ -3,6 +3,7 @@ using Avalonia.Controls.ApplicationLifetimes; | ||||
| using Avalonia.Markup.Xaml; | ||||
| using StarsAssistant.ViewModels; | ||||
| using StarsAssistant.Views; | ||||
| using Splat; | ||||
|  | ||||
| namespace StarsAssistant; | ||||
|  | ||||
| @@ -23,6 +24,9 @@ public partial class App : Application | ||||
|             }; | ||||
|         } | ||||
|  | ||||
|         var csvloader = Locator.Current.GetService<Services.CSVDataLoader>()!; | ||||
|         csvloader.StartPlanetCSVWatcher(); | ||||
|  | ||||
|         base.OnFrameworkInitializationCompleted(); | ||||
|     } | ||||
| } | ||||
| @@ -66,20 +66,26 @@ public class PlanetLoader | ||||
|                     r = db.Race.Find(owner.Key); | ||||
|                     if (r == null) | ||||
|                     { | ||||
|                         r = new() | ||||
|                         { | ||||
|                             Name = owner.Key | ||||
|                         }; | ||||
|                         r = new() { Name = owner.Key }; | ||||
|                         db.Add(r); | ||||
|                     } | ||||
|                 } | ||||
|  | ||||
|                 foreach (Planet csvp in owner) | ||||
|                 { | ||||
|                     Model.Planet p = new Model.Planet{ Name = csvp.Name }; | ||||
|                     Model.Planet? p = db.Planet.Find(csvp.Name); | ||||
|                     if (p == null) | ||||
|                     { | ||||
|                         p = new() { Name = csvp.Name }; | ||||
|                         csvp.UpdateDbPlanet(p); | ||||
|                         db.Add(p); | ||||
|                     }  | ||||
|                     else  | ||||
|                     { | ||||
|                         csvp.UpdateDbPlanet(p); | ||||
|                         db.Update(p); | ||||
|                     } | ||||
|                 } | ||||
|                 db.SaveChanges(); | ||||
|             } | ||||
|         } | ||||
|   | ||||
| @@ -3,28 +3,8 @@ using System.Reactive.Concurrency; | ||||
|  | ||||
| namespace StarsAssistant.Helpers; | ||||
|  | ||||
| public class FsWatcher | ||||
| public static class FsWatcher | ||||
| { | ||||
|     /// <summary> | ||||
|     /// Throttle a FileSystemObserver and eliminate all duplicates. | ||||
|     /// </summary> | ||||
|     /// <remarks> | ||||
|     /// Curtesy of https://endjin.com/blog/2024/05/observe-file-system-changes-with-rx-dotnet | ||||
|     /// </remarks> | ||||
|     /// <param name="watcher">An observer created with <c>ObserveFileSystem</c></param> | ||||
|     /// <param name="inactivitySeconds">Throttling window, defaults to 1 second.</param> | ||||
|     /// <param name="scheduler">Scheduler to user for throttling, default is set by <c>Quiescent</c></param> | ||||
|     /// <returns>A throttled observer with duplicate elimination.</returns> | ||||
|     public static IObservable<IEnumerable<FileSystemEventArgs>> ThrottleAndDistinctObserver ( | ||||
|         IObservable<FileSystemEventArgs> watcher,  | ||||
|         int inactivitySeconds = 1, | ||||
|         IScheduler? scheduler = null) | ||||
|     { | ||||
|         return watcher | ||||
|                 .Quiescent(TimeSpan.FromSeconds(inactivitySeconds), scheduler) | ||||
|                 .Select(changes => changes.DistinctBy(x => (x.ChangeType, x.FullPath))); | ||||
|     } | ||||
|  | ||||
|     /// <summary> | ||||
|     /// Helper to convert a FileSystemWatcher into an obervable stream. See FileSystemWatcher | ||||
|     /// documentation for further details on the parameters. | ||||
| @@ -52,6 +32,7 @@ public class FsWatcher | ||||
|                     if (filters != null) | ||||
|                         foreach (string filter in filters) | ||||
|                             fsw.Filters.Add(filter); | ||||
|                              | ||||
|                     if (notifyFilter != null) | ||||
|                         fsw.NotifyFilter = (NotifyFilters) notifyFilter; | ||||
|                     fsw.EnableRaisingEvents = true; | ||||
| @@ -90,4 +71,29 @@ public class FsWatcher | ||||
|                 .RefCount(); | ||||
|     } | ||||
|  | ||||
|     /// <summary> | ||||
|     /// Throttle a FileSystemObserver and eliminate all duplicates. | ||||
|     /// </summary> | ||||
|     /// <remarks> | ||||
|     /// Curtesy of https://endjin.com/blog/2024/05/observe-file-system-changes-with-rx-dotnet | ||||
|     /// </remarks> | ||||
|     /// <param name="watcher">An observer created with <c>ObserveFileSystem</c></param> | ||||
|     /// <param name="inactivitySeconds">Throttling window, defaults to 1 second.</param> | ||||
|     /// <param name="scheduler">Scheduler to user for throttling, default is set by <c>Quiescent</c></param> | ||||
|     /// <returns>A throttled observer with duplicate elimination.</returns> | ||||
|     public static IObservable<FileSystemEventArgs> ThrottleAndDistinct ( | ||||
|         this IObservable<FileSystemEventArgs> watcher,  | ||||
|         int inactivitySeconds = 1, | ||||
|         IScheduler? scheduler = null) | ||||
|     { | ||||
|         return watcher | ||||
|             .Quiescent(TimeSpan.FromSeconds(inactivitySeconds), scheduler) | ||||
|             .SelectMany( | ||||
|                 changes => changes | ||||
|                     .DistinctBy(x => (x.ChangeType, x.FullPath)) | ||||
|                     .ToObservable() | ||||
|                 ) | ||||
|         ; | ||||
|     } | ||||
|  | ||||
| } | ||||
|   | ||||
| @@ -34,24 +34,4 @@ public static class RxExtensions | ||||
|  | ||||
|         return src.Buffer(zeroCrossings); | ||||
|     } | ||||
|  | ||||
|     /// <summary> | ||||
|     /// Throttle a FileSystemObserver and eliminate all duplicates. | ||||
|     /// </summary> | ||||
|     /// <remarks> | ||||
|     /// Curtesy of https://endjin.com/blog/2024/05/observe-file-system-changes-with-rx-dotnet | ||||
|     /// </remarks> | ||||
|     /// <param name="watcher">An observer created with <c>ObserveFileSystem</c></param> | ||||
|     /// <param name="inactivitySeconds">Throttling window, defaults to 1 second.</param> | ||||
|     /// <param name="scheduler">Scheduler to user for throttling, default is set by <c>Quiescent</c></param> | ||||
|     /// <returns>A throttled observer with duplicate elimination.</returns> | ||||
|     public static IObservable<IEnumerable<FileSystemEventArgs>> ThrottleAndDistinct ( | ||||
|         this IObservable<FileSystemEventArgs> watcher,  | ||||
|         int inactivitySeconds = 1, | ||||
|         IScheduler? scheduler = null) | ||||
|     { | ||||
|         return watcher | ||||
|                 .Quiescent(TimeSpan.FromSeconds(inactivitySeconds), scheduler) | ||||
|                 .Select(changes => changes.DistinctBy(x => (x.ChangeType, x.FullPath))); | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -22,6 +22,9 @@ sealed class Program | ||||
|     { | ||||
|         ModeDetector.OverrideModeDetector(Splat.ModeDetection.Mode.Run); | ||||
|  | ||||
|         var logger = new ConsoleLogger() { Level = LogLevel.Debug }; | ||||
|         Locator.CurrentMutable.RegisterConstant(logger, typeof(ILogger)); | ||||
|  | ||||
|         Services.Game g = new() | ||||
|         { | ||||
|             BaseName = "GOINGTH", | ||||
| @@ -31,6 +34,7 @@ sealed class Program | ||||
|         Locator.CurrentMutable.RegisterConstant(g, typeof(Services.Game)); | ||||
|         Locator.CurrentMutable.RegisterConstant(new Services.CSVDataLoader(), typeof(Services.CSVDataLoader)); | ||||
|         Locator.CurrentMutable.Register(() => new StarsDatabase(g.DatabaseFileName), typeof(StarsDatabase)); | ||||
|         Locator.CurrentMutable.RegisterConstant(new Services.CSVDataLoader(), typeof(Services.CSVDataLoader)); | ||||
|  | ||||
|         __createTestData(); | ||||
|          | ||||
|   | ||||
| @@ -1,41 +1,58 @@ | ||||
| using System; | ||||
| using System.IO; | ||||
| using System.Reactive.Linq; | ||||
| using System.Text.RegularExpressions; | ||||
| using ReactiveUI; | ||||
| using Splat; | ||||
| using StarsAssistant.Helpers; | ||||
|  | ||||
| namespace StarsAssistant.Services; | ||||
|  | ||||
|  | ||||
| public class CSVDataLoader  | ||||
| public partial class CSVDataLoader : IEnableLogger | ||||
| { | ||||
|     /// <summary> | ||||
|     /// Reference to the game metadata, retrieved by DI | ||||
|     /// </summary> | ||||
|     protected Services.Game Game = Locator.Current.GetService<Services.Game>()!; | ||||
|  | ||||
|     public void CSVDataLoader()  | ||||
|     [GeneratedRegex(@".*\.(?<type>[pf])(?<player>\d)+$")] | ||||
|     private static partial Regex MyRegex(); | ||||
|  | ||||
|     protected Regex FileTypeRegEx = MyRegex(); | ||||
|  | ||||
|     public CSVDataLoader()  | ||||
|     { | ||||
|          | ||||
|     } | ||||
|  | ||||
|     public void StartPlanetCSVWatcher()  | ||||
|     { | ||||
|         // TODO: which scheduler for Throttle? | ||||
|         // string[] filters = { "*.p*", "*.f*", "*.map" }; | ||||
|  | ||||
|         var watcher = FsWatcher | ||||
|             .ObserveFileSystem(Game.GamePath, new string[] { Game.PlanetFileSearchPattern }); | ||||
|             .ThrottleAndDistinct(2); | ||||
|             .ObserveFileSystem(Game.GamePath, [ Game.PlanetFileSearchPattern ]) | ||||
|             .ThrottleAndDistinct(2, RxApp.TaskpoolScheduler) | ||||
|             .Log(this, $"{DateTime.Now.ToLongTimeString()} FsEvent", fsEvent => $"{fsEvent.FullPath} {fsEvent.ChangeType}") | ||||
|             .ObserveOn(RxApp.TaskpoolScheduler); | ||||
|          | ||||
|         /* | ||||
|         watcher.Subscribe(x =>  | ||||
|         { | ||||
|             Console.WriteLine($"{DateTime.Now.ToLongTimeString()} got {x.Count()} events:"); | ||||
|  | ||||
|             foreach (var fsEvent in x) | ||||
|             { | ||||
|                 Console.WriteLine($"{DateTime.Now.ToLongTimeString()} {i++} {fsEvent.FullPath} - {fsEvent.ChangeType}"); | ||||
|         watcher.Subscribe(fsEvent => this.LoadPlanetFile(fsEvent.FullPath)); | ||||
|     } | ||||
|         }); | ||||
|         */ | ||||
|  | ||||
|     protected void LoadPlanetFile(string fileName) | ||||
|     { | ||||
|         Match m = FileTypeRegEx.Match(fileName); | ||||
|         if (! m.Success) | ||||
|         { | ||||
|             this.Log().Error($"Failed to parse {fileName} to identify what we are looking at. Ignoring file."); | ||||
|             return; | ||||
|         } | ||||
|  | ||||
|         string type = m.Groups["type"].Value; | ||||
|         string player = m.Groups["player"].Value; | ||||
|  | ||||
|         this.Log().Debug($"Got file type {type} for player {player}"); | ||||
|         var loader = new CSV.PlanetLoader(); | ||||
|         loader.ImportForRace(Model.Race.Player); | ||||
|     } | ||||
| }    | ||||
|   | ||||
		Reference in New Issue
	
	Block a user