117 lines
3.9 KiB
C#
117 lines
3.9 KiB
C#
using System;
|
|
using System.ComponentModel;
|
|
using System.Reactive;
|
|
using System.Reactive.Disposables;
|
|
using System.Reactive.Linq;
|
|
using System.Reactive.Subjects;
|
|
using DynamicData;
|
|
using DynamicData.Binding;
|
|
using Splat;
|
|
using StarsAssistant.Model;
|
|
using StarsAssistant.ViewModels;
|
|
|
|
namespace StarsAssistant.Services;
|
|
|
|
public class PlanetManager : IDisposable, IEnableLogger
|
|
{
|
|
protected Services.Game Game = Locator.Current.GetService<Services.Game>()!;
|
|
|
|
/// <summary>
|
|
/// SourceCache for DynamicData views
|
|
/// </summary>
|
|
private SourceCache<Planet, string> _planets = new(p => p.Name);
|
|
|
|
/// <summary>
|
|
/// Observable changeset showing all player planets converted to view models.
|
|
/// </summary>
|
|
public IObservable<IChangeSet<PlayerPlanetViewModel, string>> PlayerPlanetsSource
|
|
=> _planets
|
|
.Connect()
|
|
.Filter(planet => planet.OwnerId == Game.Player.Name)
|
|
.Transform(planet => new PlayerPlanetViewModel(planet));
|
|
|
|
/// <summary>
|
|
/// Cache with all player planets, indexed by planet name.
|
|
/// </summary>
|
|
private SourceCache<PlayerPlanetViewModel, string> _playerPlanets = new(p => p.Planet.Name);
|
|
|
|
/// <summary>
|
|
/// Observable subject to trigger when we update the planet cache, allows the
|
|
/// UI to react to it.
|
|
/// </summary>
|
|
private readonly Subject<Unit> _planetsReloadedSubject = new();
|
|
|
|
/// <summary>
|
|
/// Exposes _planetReloadedSubject as IObservable.
|
|
/// </summary>
|
|
public IObservable<Unit> PlanetsReloaded => _planetsReloadedSubject.AsObservable();
|
|
|
|
|
|
public PlanetManager()
|
|
{
|
|
FleetManager fleetManager = Locator.Current.GetService<FleetManager>()!;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Load the planet records from the database and push them into our source cache.
|
|
/// </summary>
|
|
public void InitFromDatabase()
|
|
{
|
|
using var db = Locator.Current.GetService<StarsDatabase>()!;
|
|
var allPlanets = db.Planet.ToList();
|
|
var cacheKeys = _planets.Keys.ToList();
|
|
var planetNames = from p in allPlanets select p.Name;
|
|
var planetsToDelete = cacheKeys.Except(planetNames);
|
|
_planets.Edit(innerCache =>
|
|
{
|
|
foreach (var name in planetsToDelete)
|
|
innerCache.RemoveKey(name);
|
|
innerCache.AddOrUpdate(allPlanets);
|
|
}
|
|
);
|
|
|
|
var allPlayerPlanets = allPlanets.Where(planet => planet.OwnerId == Game.Player.Name);
|
|
var allPlayerCacheKeys = _playerPlanets.Keys.ToList();
|
|
var playerPlanetNames = from p in allPlayerPlanets select p.Name;
|
|
var playerPlanetsToDelete = allPlayerCacheKeys.Except(playerPlanetNames);
|
|
|
|
_playerPlanets.Edit(innerCache =>
|
|
{
|
|
foreach (var name in playerPlanetsToDelete)
|
|
innerCache.RemoveKey(name);
|
|
foreach (var planet in allPlayerPlanets)
|
|
{
|
|
var playerPlanet = innerCache.Lookup(planet.Name);
|
|
if (playerPlanet.HasValue)
|
|
playerPlanet.Value.Planet = planet;
|
|
else
|
|
innerCache.AddOrUpdate(new PlayerPlanetViewModel(planet));
|
|
}
|
|
}
|
|
);
|
|
|
|
_planetsReloadedSubject.OnNext(Unit.Default);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Handle disposal of all subscriptions and dependencies.
|
|
/// </summary>/
|
|
protected virtual void Dispose(bool disposing)
|
|
{
|
|
if (disposing)
|
|
{
|
|
_planets.Dispose();
|
|
_planetsReloadedSubject.Dispose();
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Boilerplate disposal
|
|
/// </summary>
|
|
public void Dispose()
|
|
{
|
|
Dispose(true);
|
|
GC.SuppressFinalize(this);
|
|
}
|
|
}
|