using System; using System.Collections.Immutable; using System.Collections.ObjectModel; using System.ComponentModel; using System.Reactive; using System.Reactive.Linq; using System.Text.RegularExpressions; using Avalonia.Controls.Platform; using DynamicData; using DynamicData.Binding; using ReactiveUI; using Splat; using StarsAssistant.Model; using StarsAssistant.ViewModels; namespace StarsAssistant.Services; public class FleetManager : IEnableLogger { protected Services.Game Game = Locator.Current.GetService()!; /// /// SourceCache for DynamicData views /// private SourceList _fleets = new(); public FleetManager() {} public class FleetSummary { public string Destination { get; set; } = string.Empty; public int TotalIronium { get; set; } public int TotalBoranium { get; set; } public int TotalGermanium { get; set; } public int TotalColonists { get; set; } public override string ToString() => $"To {Destination}: {TotalIronium}I/{TotalBoranium}B/{TotalGermanium}G/{TotalColonists}C"; } private IObservable>? _fleetSummaries; private ReadOnlyObservableCollection? summaries; private IDisposable? d1; private IDisposable? d2; public void test() { _fleetSummaries = _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) }) ; // 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(); 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}"); } } ); } /// /// Load the fleet records from the database and push them into our source cache. /// If the data has been freshly imported, call PostProcessImportedData first. /// public void InitFromDatabase() { using var db = Locator.Current.GetService()!; var allFleets = db.Fleet.ToList(); _fleets.Edit(innerCache => { innerCache.Clear(); innerCache.Add(allFleets); } ); } /// /// Helper to fill up missing data from the original import. Tries to deduce /// missing properties using heuristics. /// public static void PostProcessImportedData() { using var db = Locator.Current.GetService()!; // Check for all cases where we're targeting another fleet instead of // a planet. Update the DB accordingly. var playerFleets = from flt in db.Fleet where flt.OwnerFileId == Game.Player.PlayerFileId select flt; Regex shipPattern = new ($@"^{Regex.Escape(Game.Player.Name)} (?.+) #\d+$"); foreach (Fleet flt in playerFleets) { if (flt.Destination != "-- ") { var trueDest = db.Fleet .FirstOrDefault(f => f.FleetName == $"{Game.Player.Name} {flt.Destination}" && f.Planet != String.Empty); flt.TrueDestination = trueDest?.Planet ?? flt.Destination; } else { flt.TrueDestination = "-- "; } Match m = shipPattern.Match(flt.FleetName); if (m.Success) flt.ShipTypeGuess = m.Groups[1].Value; db.Update(flt); } db.SaveChanges(); } }