sa/Stars Assistant/ViewModels/PlayerPlanetViewModel.cs

253 lines
8.1 KiB
C#
Raw Normal View History

2024-09-24 20:32:13 +00:00
using System.Collections.ObjectModel;
using System.Reactive.Disposables;
using System.Reactive.Linq;
2024-09-24 20:32:13 +00:00
using Microsoft.EntityFrameworkCore;
using DynamicData;
2024-09-24 20:32:13 +00:00
using ReactiveUI;
using ReactiveUI.SourceGenerators;
2024-09-24 20:32:13 +00:00
using StarsAssistant.Services;
using Splat;
2024-10-19 18:05:12 +00:00
using StarsAssistant.Model;
2024-09-24 20:32:13 +00:00
namespace StarsAssistant.ViewModels;
public partial class PlayerPlanetViewModel : ViewModelBase
{
private readonly Model.Planet Planet;
2024-10-19 18:05:12 +00:00
private readonly Services.Game Game;
private readonly IObservable<Change<FleetSummaryByDestination, string>> _fleetSummaryChanges;
2024-09-24 20:32:13 +00:00
public PlayerPlanetViewModel(Model.Planet planet)
{
2024-10-19 18:05:12 +00:00
Game = Locator.Current.GetService<Services.Game>()!;
2024-09-24 20:32:13 +00:00
2024-10-19 18:05:12 +00:00
if (planet.OwnerId != Services.Game.Player.Name)
2024-09-24 20:32:13 +00:00
throw new InvalidOperationException("PlayerPlanet ViewModels can only be created for player planets.");
Planet = planet;
PopulationTargetPercent = planet.PopulationTargetPercent;
_populationTargetHelper = this
.WhenAnyValue(vm => vm.PopulationTargetPercent)
.Select(popTgt => this.MaxPopulation * popTgt / 10000 * 100)
.ToProperty(this, vm => vm.PopulationTarget);
2024-09-24 20:32:13 +00:00
2024-09-26 20:18:50 +00:00
_populationToShipHelper = this
.WhenAnyValue(vm => vm.PopulationTarget)
.Select(popToShip => this.ComputePopulationToShip())
.ToProperty(this, vm => vm.PopulationToShip);
_targetFactoriesHelper = this
.WhenAnyValue(vm => vm.PopulationTarget)
.Select(tgtFact => GameEngine.MaxOperableFactoriesForPlayer(_populationTarget, Value))
.ToProperty(this, vm => vm.TargetFactories);
_remainingFactoriesHelper = this
.WhenAnyValue(vm => vm.TargetFactories)
.Select(factRem => Factories < _targetFactories ? _targetFactories - Factories : 0)
.ToProperty(this, vm => vm.RemainingFactories);
_factoryGermaniumDeltaHelper = this
.WhenAnyValue(vm => vm.RemainingFactories)
.Select(gerCost => ComputeFactoryGermaniumDelta())
.ToProperty(this, vm => vm.FactoryGermaniumDelta);
_remainingMinesHelper = this
.WhenAnyValue(vm => vm.PopulationTarget)
.Select(remMines => Math.Max(0, GameEngine.MaxOperableMinesForPlayer(_populationTarget, Value) - Mines))
.ToProperty(this, vm => vm.RemainingMines);
FleetManager fm = Locator.Current.GetService<FleetManager>()!;
2024-10-19 18:05:12 +00:00
_fleetSummaryChanges = fm.FleetSummariesByDestination
.Connect()
.Watch(Name)
.Log(this, "fleetSummaryChange", change => $"{Name}: {change.Reason}: {change.Previous} => {change.Current}")
;
2024-10-19 18:05:12 +00:00
_populationEnRouteHelper = _fleetSummaryChanges
.Select(change => change.Reason != ChangeReason.Remove ? change.Current.TotalColonists : 0)
.Log(this, "PopulationEnRoute", pop => $"{Name}: {pop}")
.ToProperty(this, vm => vm.PopulationEnRoute)
;
2024-09-24 20:32:13 +00:00
this.WhenActivated((CompositeDisposable disposables) =>
{
disposables.Add(_populationEnRouteHelper);
2024-09-24 20:32:13 +00:00
// /* handle activation */
// Disposable
// .Create(() => { /* handle deactivation */ })
// .DisposeWith(disposables);
});
}
#region Database Properties
public string Name => Planet.Name;
public string Owner => Planet.OwnerId;
public string StarbaseType => Planet.StarbaseType;
public int Population => Planet.Population ?? 0;
public int Value => Planet.Value ?? 0;
public int Mines => Planet.Mines ?? 0;
public int Factories => Planet.Factories ?? 0;
public decimal DefPercent => Planet.DefPercent ?? 0;
public int SurfaceIronium => Planet.SurfaceIronium ?? 0;
public int SurfaceBoranium => Planet.SurfaceBoranium ?? 0;
public int SurfaceGermanium => Planet.SurfaceGermanium ?? 0;
public int MRIronium => Planet.MRIronium ?? 0;
public int MRBoranium => Planet.MRBoranium ?? 0;
public int MRGermanium => Planet.MRGermanium ?? 0;
public int MCIronium => Planet.MCIronium ?? 0;
public int MCBoranium => Planet.MCBoranium ?? 0;
public int MCGermanium => Planet.MCGermanium ?? 0;
public int Resources => Planet.Resources ?? 0;
public decimal Gravity => Planet.Gravity ?? 0;
public decimal Temperature => Planet.Temperature ?? 0;
public decimal Radiation => Planet.Radiation ?? 0;
public decimal GravityOrig => Planet.GravityOrig ?? 0;
public decimal TemperatureOrig => Planet.TemperatureOrig ?? 0;
public decimal RadiationOrig => Planet.RadiationOrig ?? 0;
public int MaxTerraforming => Planet.MaxTerraforming ?? 0;
public int CapacityPercent => Planet.CapacityPercent ?? 0;
public int ScanRange => Planet.ScanRange ?? 0;
public int PenScanRange => Planet.PenScanRange ?? 0;
public int Driver => Planet.Driver ?? 0;
public int DriverWarp => Planet.DriverWarp ?? 0;
public string RouteTarget => Planet.RouteTarget;
public int GateRange => Planet.GateRange ?? 0;
public int GateMass => Planet.GateMass ?? 0;
public int PctDamage => Planet.PctDamage ?? 0;
[Reactive]
private int _populationTargetPercent;
2024-09-24 20:32:13 +00:00
#endregion
#region Derived Properties
public int EffectiveValue => GameEngine.EffectivePlanetValue(Value);
public int MaxPopulation => GameEngine.MaxPopOnPlanetForPlayer(Value);
public int PopulationGrowth => GameEngine.PlanetPopGrowthForPlayer(Population, Value);
2024-09-26 20:18:50 +00:00
public int PopulationT1 => Population + PopulationGrowth /* TODO + Pop En Route */;
2024-09-24 20:32:13 +00:00
public int BuildableFactories => GameEngine.MaxBuildableFactoriesForPlayer(Value);
public int BuildableMines => GameEngine.MaxBuildableMinesForPlayer(Value);
public int OperableFactories => GameEngine.MaxOperableFactoriesForPlayer(Population, Value);
public int OperableMines => GameEngine.MaxOperableMinesForPlayer(Population, Value);
public int ResourcesFromPopulation => GameEngine.ResourcesFromPopForPlayer(Population, Value);
public int ResourcesFromFactories => GameEngine.ResourcesFromFactForPlayer(Population, Factories, Value);
2024-09-26 20:18:50 +00:00
public int AvailableIronium => MRIronium + SurfaceIronium;
public int AvailableBoranium => MRBoranium + SurfaceBoranium;
public int AvailableGermanium => MRGermanium + SurfaceGermanium;
[ObservableAsProperty]
private int _populationTarget;
2024-09-26 20:18:50 +00:00
[ObservableAsProperty]
private int _populationToShip;
[ObservableAsProperty]
private int _targetFactories;
[ObservableAsProperty]
private int _remainingFactories;
[ObservableAsProperty]
private int _factoryGermaniumDelta;
[ObservableAsProperty]
private int _remainingMines;
[ObservableAsProperty]
private int _populationEnRoute;
2024-09-26 20:18:50 +00:00
#endregion
#region Helper functions
private int ComputePopulationToShip()
{
if (Population >= _populationTarget)
return Population - _populationTarget;
if (PopulationT1 < _populationTarget)
return PopulationT1 - _populationTarget;
return 0;
}
private int ComputeFactoryGermaniumDelta()
{
int gerReq = GameEngine.FactoryGermaniumCostForPlayer(_remainingFactories);
if (gerReq < AvailableGermanium)
return Math.Max(0, SurfaceGermanium - gerReq);
return AvailableGermanium + MRGermanium - gerReq;
// TODO: Extrapolate to T1, so that excess Germanium is visible.
// TODO: Take shipping into account.
}
2024-10-02 18:18:00 +00:00
/*
private int ComputePopulationEnRoute()
{
using var db = Locator.Current.GetService<Model.StarsDatabase>()!;
var enRoute = from flt in db.Fleet
where flt.OwnerFileId == Game.Player.PlayerFileId && flt.TrueDestination == Planet.Name
select new { Colonists = flt.Sum(f => f.Colonists) };
return enRoute.Colonists ?? 0;
}
*/
2024-09-24 20:32:13 +00:00
#endregion
}