diff --git a/Stars Assistant/Model/Fleet.cs b/Stars Assistant/Model/Fleet.cs index 5a09109..370e8aa 100644 --- a/Stars Assistant/Model/Fleet.cs +++ b/Stars Assistant/Model/Fleet.cs @@ -87,4 +87,5 @@ public class Fleet public Race? Owner { get; set; } #endregion + } diff --git a/Stars Assistant/Model/FleetSummary.cs b/Stars Assistant/Model/FleetSummary.cs index 1db39dd..b360359 100644 --- a/Stars Assistant/Model/FleetSummary.cs +++ b/Stars Assistant/Model/FleetSummary.cs @@ -2,7 +2,7 @@ using System; namespace StarsAssistant.Model; -public class FleetSummary +public class FleetSummaryByDestination { public string Destination { get; set; } = string.Empty; public int TotalIronium { get; set; } diff --git a/Stars Assistant/Services/FleetManager.cs b/Stars Assistant/Services/FleetManager.cs index 02c6903..47b3904 100644 --- a/Stars Assistant/Services/FleetManager.cs +++ b/Stars Assistant/Services/FleetManager.cs @@ -28,79 +28,93 @@ public class FleetManager : IEnableLogger, IDisposable /// /// Fleet data summarized by destination, will be chaned to _fleets /// - private SourceCache _fleetSummaries = new(fs => fs.Destination); + private SourceCache _fleetSummariesByDestination = new(fs => fs.Destination); + + /// + /// Extract a readonly Cache for all fleet summaries tracked by the + /// fleet manager. + /// + public IObservableCache FleetSummariesByDestination + => _fleetSummariesByDestination.AsObservableCache(); /// /// Public accessor to the continously updated fleet summaries. /// - public IObservableCache FleetSummaries => _fleetSummaries.AsObservableCache(); + // public IObservableCache FleetSummariesByDestination => _fleetSummaries.AsObservableCache(); /// /// Disposal tracking /// - private IDisposable _fleetSummariesSubscription; + // private IDisposable _fleetSummariesSubscription; public FleetManager() { - CreateFleetSummariesLink(); + // CreateFleetSummariesLink(); } - [MemberNotNull(nameof(_fleetSummariesSubscription))] - protected void CreateFleetSummariesLink() - { - _fleetSummariesSubscription = _fleets.Connect() - .Filter(fleet => fleet.TrueDestination != "-- ") - .GroupOn(fleet => fleet.TrueDestination) - .Log(this, $"{DateTime.Now.ToLongTimeString()} fleetWatcher", grp => $"{grp.TotalChanges} detected") - .Transform(group => new FleetSummary - { - Destination = group.GroupKey, - TotalIronium = group.List.Items.Sum(f => f.Ironium), - TotalBoranium = group.List.Items.Sum(f => f.Boranium), - TotalGermanium = group.List.Items.Sum(f => f.Germanium), - TotalColonists = group.List.Items.Sum(f => f.Colonists) - }) - .AddKey(fs => fs.Destination) - .Log(this, "FleetManager _fleetSummaries update", changes => - $"{changes.Adds} adds, {changes.Updates} updates, {changes.Removes} removes" - ) - .PopulateInto(_fleetSummaries) - ; + // [MemberNotNull(nameof(_fleetSummariesSubscription))] + // protected void CreateFleetSummariesLink() + // { + // /* + // _fleetSummariesSubscription = _fleets.Connect() + // .Filter(fleet => fleet.TrueDestination != "-- ") + // .Log(this, $"{DateTime.Now.ToLongTimeString()} fleetWatcher filter", fleet => $"{fleet}") + // // .AutoRefreshOnObservable(fleet => fleet.WhenAnyValue( + // // f => f.Ironium, f => f.Boranium, f => f.Germanium, f => f.Colonists)) + // .Log(this, $"{DateTime.Now.ToLongTimeString()} fleetWatcher refresh", fleet => $"{fleet}") + // .GroupOn(fleet => fleet.TrueDestination) + // .Log(this, $"{DateTime.Now.ToLongTimeString()} fleetWatcher group", grp => $"{grp.TotalChanges} detected") + // .Transform(group => new FleetSummaryByDestination + // { + // Destination = group.GroupKey, + // TotalIronium = group.List.Items.Sum(f => f.Ironium), + // TotalBoranium = group.List.Items.Sum(f => f.Boranium), + // TotalGermanium = group.List.Items.Sum(f => f.Germanium), + // TotalColonists = group.List.Items.Sum(f => f.Colonists) + // }) - /* - // Demo only - var sourceCache = new SourceCache(fs => fs.Destination); - var tmp = fleetSummaries - .AddKey(fs => fs.Destination) - .PopulateInto(sourceCache); + // .AddKey(fs => fs.Destination) + // .Log(this, "FleetManager _fleetSummaries update", changes => + // $"{changes.Adds} adds, {changes.Updates} updates, {changes.Removes} removes" + // ) + // .PopulateInto(_fleetSummaries) + // ; + // */ + + // /* + // // Demo only + // var sourceCache = new SourceCache(fs => fs.Destination); + // var tmp = fleetSummaries + // .AddKey(fs => fs.Destination) + // .PopulateInto(sourceCache); - _fleetSummaries - .ObserveOn(RxApp.MainThreadScheduler) - .Bind(out summaries) - .DisposeMany() - .Subscribe(); + // _fleetSummaries + // .ObserveOn(RxApp.MainThreadScheduler) + // .Bind(out summaries) + // .DisposeMany() + // .Subscribe(); - d1 = summaries - .Subscribe(Observer.Create(f => - { - this.Log().Debug($"FleetSummary observed: {f}"); - } - )); - - d2 = _fleetSummaries - .ObserveOn(RxApp.MainThreadScheduler) - .Subscribe(x => - { - var lst = x.ToList(); - foreach (var f in lst) - { - this.Log().Debug($"Reason {f.Reason}, Type {f.Type}: {f.Item.Current}"); - } - } - ); - */ - } + // d1 = summaries + // .Subscribe(Observer.Create(f => + // { + // this.Log().Debug($"FleetSummaryByDestination observed: {f}"); + // } + // )); + // d2 = _fleetSummaries + // .ObserveOn(RxApp.MainThreadScheduler) + // .Subscribe(x => + // { + // var lst = x.ToList(); + // foreach (var f in lst) + // { + // this.Log().Debug($"Reason {f.Reason}, Type {f.Type}: {f.Item.Current}"); + // } + // } + // ); + // */ + // } + /// /// Load the fleet records from the database and push them into our source cache. /// If the data has been freshly imported, call PostProcessImportedData first. @@ -108,6 +122,8 @@ public class FleetManager : IEnableLogger, IDisposable public void InitFromDatabase() { using var db = Locator.Current.GetService()!; + + // Load the full list var allFleets = db.Fleet.ToList(); _fleets.Edit(innerCache => { @@ -115,6 +131,25 @@ public class FleetManager : IEnableLogger, IDisposable innerCache.Add(allFleets); } ); + + var summaries = from f in allFleets + group f by f.TrueDestination into grp + select new FleetSummaryByDestination + { + Destination = grp.Key, + TotalIronium = grp.Sum(f => f.Ironium), + TotalBoranium = grp.Sum(f => f.Boranium), + TotalGermanium = grp.Sum(f => f.Germanium), + TotalColonists = grp.Sum(f => f.Colonists) + }; + + var cacheKeys = _fleetSummariesByDestination.Keys.ToList(); + var summariesToDelete = cacheKeys.Except(summaries.Select(sum => sum.Destination)); + _fleetSummariesByDestination.Edit(innerCache => { + innerCache.RemoveKeys(summariesToDelete); + innerCache.AddOrUpdate(summaries); + } + ); } /// @@ -166,8 +201,8 @@ public class FleetManager : IEnableLogger, IDisposable { if (disposing) { - _fleetSummariesSubscription.Dispose(); - _fleetSummaries.Dispose(); + // _fleetSummariesSubscription.Dispose(); + _fleetSummariesByDestination.Dispose(); _fleets.Dispose(); } } diff --git a/Stars Assistant/ViewModels/PlayerPlanetViewModel.cs b/Stars Assistant/ViewModels/PlayerPlanetViewModel.cs index 3df2c8c..8cbf6e5 100644 --- a/Stars Assistant/ViewModels/PlayerPlanetViewModel.cs +++ b/Stars Assistant/ViewModels/PlayerPlanetViewModel.cs @@ -7,6 +7,7 @@ using ReactiveUI; using ReactiveUI.SourceGenerators; using StarsAssistant.Services; using Splat; +using StarsAssistant.Model; namespace StarsAssistant.ViewModels; @@ -14,13 +15,15 @@ public partial class PlayerPlanetViewModel : ViewModelBase { private readonly Model.Planet Planet; - private Game Game; + private readonly Services.Game Game; + + private readonly IObservable> _fleetSummaryChanges; public PlayerPlanetViewModel(Model.Planet planet) { - Game = Locator.Current.GetService()!; + Game = Locator.Current.GetService()!; - if (planet.OwnerId != Game.Player.Name) + if (planet.OwnerId != Services.Game.Player.Name) throw new InvalidOperationException("PlayerPlanet ViewModels can only be created for player planets."); Planet = planet; @@ -58,13 +61,13 @@ public partial class PlayerPlanetViewModel : ViewModelBase FleetManager fm = Locator.Current.GetService()!; - var fleetSummaryChanges = fm.FleetSummaries + _fleetSummaryChanges = fm.FleetSummariesByDestination .Connect() .Watch(Name) .Log(this, "fleetSummaryChange", change => $"{Name}: {change.Reason}: {change.Previous} => {change.Current}") ; - _populationEnRouteHelper = fleetSummaryChanges + _populationEnRouteHelper = _fleetSummaryChanges .Select(change => change.Reason != ChangeReason.Remove ? change.Current.TotalColonists : 0) .Log(this, "PopulationEnRoute", pop => $"{Name}: {pop}") .ToProperty(this, vm => vm.PopulationEnRoute)