2024-10-02 18:18:00 +00:00
|
|
|
using System;
|
2024-10-05 17:38:48 +00:00
|
|
|
using System.Collections.Immutable;
|
|
|
|
using System.Collections.ObjectModel;
|
2024-10-02 18:18:00 +00:00
|
|
|
using System.ComponentModel;
|
2024-10-09 18:18:26 +00:00
|
|
|
using System.Diagnostics.CodeAnalysis;
|
2024-10-05 17:38:48 +00:00
|
|
|
using System.Reactive;
|
2024-10-02 18:18:00 +00:00
|
|
|
using System.Reactive.Linq;
|
|
|
|
using System.Text.RegularExpressions;
|
2024-10-05 17:38:48 +00:00
|
|
|
using Avalonia.Controls.Platform;
|
2024-10-02 18:18:00 +00:00
|
|
|
using DynamicData;
|
|
|
|
using DynamicData.Binding;
|
2024-10-05 17:38:48 +00:00
|
|
|
using ReactiveUI;
|
2024-10-02 18:18:00 +00:00
|
|
|
using Splat;
|
|
|
|
using StarsAssistant.Model;
|
|
|
|
using StarsAssistant.ViewModels;
|
|
|
|
|
|
|
|
namespace StarsAssistant.Services;
|
|
|
|
|
2024-10-09 18:18:26 +00:00
|
|
|
public class FleetManager : IEnableLogger, IDisposable
|
2024-10-02 18:18:00 +00:00
|
|
|
{
|
|
|
|
protected Services.Game Game = Locator.Current.GetService<Services.Game>()!;
|
|
|
|
|
|
|
|
/// <summary>
|
2024-10-09 18:18:26 +00:00
|
|
|
/// SourceList for fleets read from the game files
|
2024-10-02 18:18:00 +00:00
|
|
|
/// </summary>
|
2024-10-05 16:47:53 +00:00
|
|
|
private SourceList<Fleet> _fleets = new();
|
2024-10-02 18:18:00 +00:00
|
|
|
|
2024-10-09 18:18:26 +00:00
|
|
|
/// <summary>
|
|
|
|
/// Fleet data summarized by destination, will be chaned to _fleets
|
|
|
|
/// </summary>
|
2024-10-19 18:05:12 +00:00
|
|
|
private SourceCache<FleetSummaryByDestination, string> _fleetSummariesByDestination = new(fs => fs.Destination);
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// Extract a readonly Cache for all fleet summaries tracked by the
|
|
|
|
/// fleet manager.
|
|
|
|
/// </summary>
|
|
|
|
public IObservableCache<FleetSummaryByDestination, string> FleetSummariesByDestination
|
|
|
|
=> _fleetSummariesByDestination.AsObservableCache();
|
2024-10-05 17:38:48 +00:00
|
|
|
|
2024-10-09 18:18:26 +00:00
|
|
|
/// <summary>
|
|
|
|
/// Public accessor to the continously updated fleet summaries.
|
|
|
|
/// </summary>
|
2024-10-19 18:05:12 +00:00
|
|
|
// public IObservableCache<FleetSummaryByDestination, string> FleetSummariesByDestination => _fleetSummaries.AsObservableCache();
|
2024-10-05 17:38:48 +00:00
|
|
|
|
2024-10-09 18:18:26 +00:00
|
|
|
/// <summary>
|
|
|
|
/// Disposal tracking
|
|
|
|
/// </summary>
|
2024-10-19 18:05:12 +00:00
|
|
|
// private IDisposable _fleetSummariesSubscription;
|
2024-10-05 17:38:48 +00:00
|
|
|
|
2024-10-09 18:18:26 +00:00
|
|
|
public FleetManager()
|
|
|
|
{
|
2024-10-19 18:05:12 +00:00
|
|
|
// CreateFleetSummariesLink();
|
2024-10-09 18:18:26 +00:00
|
|
|
}
|
2024-10-04 17:05:23 +00:00
|
|
|
|
2024-10-19 18:05:12 +00:00
|
|
|
// [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)
|
|
|
|
// })
|
|
|
|
|
|
|
|
// .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<FleetSummaryByDestination, string>(fs => fs.Destination);
|
|
|
|
// var tmp = fleetSummaries
|
|
|
|
// .AddKey(fs => fs.Destination)
|
|
|
|
// .PopulateInto(sourceCache);
|
2024-10-05 17:38:48 +00:00
|
|
|
|
2024-10-19 18:05:12 +00:00
|
|
|
// _fleetSummaries
|
|
|
|
// .ObserveOn(RxApp.MainThreadScheduler)
|
|
|
|
// .Bind(out summaries)
|
|
|
|
// .DisposeMany()
|
|
|
|
// .Subscribe();
|
|
|
|
|
|
|
|
// d1 = summaries
|
|
|
|
// .Subscribe(Observer.Create<FleetSummaryByDestination>(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}");
|
|
|
|
// }
|
|
|
|
// }
|
|
|
|
// );
|
|
|
|
// */
|
|
|
|
// }
|
|
|
|
|
2024-10-02 18:18:00 +00:00
|
|
|
/// <summary>
|
|
|
|
/// Load the fleet records from the database and push them into our source cache.
|
|
|
|
/// If the data has been freshly imported, call PostProcessImportedData first.
|
|
|
|
/// </summary>
|
|
|
|
public void InitFromDatabase()
|
|
|
|
{
|
|
|
|
using var db = Locator.Current.GetService<StarsDatabase>()!;
|
2024-10-19 18:05:12 +00:00
|
|
|
|
|
|
|
// Load the full list
|
2024-10-02 18:18:00 +00:00
|
|
|
var allFleets = db.Fleet.ToList();
|
2024-10-04 17:05:23 +00:00
|
|
|
_fleets.Edit(innerCache =>
|
|
|
|
{
|
|
|
|
innerCache.Clear();
|
2024-10-05 16:47:53 +00:00
|
|
|
innerCache.Add(allFleets);
|
2024-10-04 17:05:23 +00:00
|
|
|
}
|
|
|
|
);
|
2024-10-19 18:05:12 +00:00
|
|
|
|
|
|
|
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);
|
|
|
|
}
|
|
|
|
);
|
2024-10-02 18:18:00 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// Helper to fill up missing data from the original import. Tries to deduce
|
|
|
|
/// missing properties using heuristics.
|
|
|
|
/// </summary>
|
|
|
|
public static void PostProcessImportedData()
|
|
|
|
{
|
|
|
|
using var db = Locator.Current.GetService<StarsDatabase>()!;
|
|
|
|
|
|
|
|
// 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)} (?<ShipType>.+) #\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
|
|
|
|
{
|
2024-10-13 20:26:29 +00:00
|
|
|
flt.TrueDestination = flt.Planet;
|
2024-10-02 18:18:00 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
Match m = shipPattern.Match(flt.FleetName);
|
|
|
|
if (m.Success)
|
|
|
|
flt.ShipTypeGuess = m.Groups[1].Value;
|
|
|
|
|
2024-10-13 20:26:29 +00:00
|
|
|
flt.Colonists *= 100;
|
|
|
|
|
|
|
|
db.Update(flt);
|
2024-10-02 18:18:00 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
db.SaveChanges();
|
|
|
|
}
|
|
|
|
|
2024-10-09 18:18:26 +00:00
|
|
|
/// <summary>
|
|
|
|
/// Handle disposal of all subscriptions and dependencies.
|
|
|
|
/// </summary>/
|
|
|
|
protected virtual void Dispose(bool disposing)
|
|
|
|
{
|
|
|
|
if (disposing)
|
|
|
|
{
|
2024-10-19 18:05:12 +00:00
|
|
|
// _fleetSummariesSubscription.Dispose();
|
|
|
|
_fleetSummariesByDestination.Dispose();
|
2024-10-09 18:18:26 +00:00
|
|
|
_fleets.Dispose();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// Boilerplate disposal
|
|
|
|
/// </summary>
|
|
|
|
public void Dispose()
|
|
|
|
{
|
|
|
|
Dispose(true);
|
|
|
|
GC.SuppressFinalize(this);
|
|
|
|
}
|
2024-10-02 18:18:00 +00:00
|
|
|
}
|