Setup CSV Fleet import and EF Fleet Entity, fix a few bugs

This commit is contained in:
Torben Nehmer 2024-10-01 22:21:50 +02:00
parent 3f04de398a
commit e6c2f969b4
7 changed files with 192 additions and 31 deletions

View File

@ -35,61 +35,116 @@ public class Fleet
[Index(9)]
public int Germanium { get; set; }
[Index(0)]
[Index(10)]
public int Colonists { get; set; }
[Index(1)]
[Index(11)]
public int Fuel { get; set; }
[Index(2)]
public int OwnerPlayerNumber { get; set; }
[Index(12)]
public int OwnerFileId { get; set; }
[Index(3)]
public int ETA { get; set; }
[Ignore()]
public int ETA { get; private set; }
[Index(4)]
[Index(13)]
public string CSVETA {
set {
if ( value.Length >= 2
&& int.TryParse(value[..^1], out int result))
{
ETA = result;
} else {
ETA = 0;
}
}
}
[Index(14)]
public int Warp { get; set; }
[Index(5)]
[Index(15)]
public int Mass { get; set; }
[Index(6)]
[Index(16)]
public int Cloak { get; set; }
[Index(7)]
[Index(17)]
public int Scan { get; set; }
[Index(8)]
[Index(18)]
public int PenScan { get; set; }
[Index(9)]
[Index(19)]
public string Task { get; set; } = String.Empty;
[Index(0)]
[Index(20)]
public int Mining { get; set; }
[Index(1)]
[Index(21)]
public int Sweep { get; set; }
[Index(2)]
[Index(22)]
public int Laying { get; set; }
[Index(3)]
[Index(23)]
public int Terraforming { get; set; }
[Index(4)]
[Index(24)]
public int Unarmed { get; set; }
[Index(5)]
[Index(25)]
public int Scout { get; set; }
[Index(6)]
[Index(26)]
public int Warship { get; set; }
[Index(7)]
[Index(27)]
public int Utility { get; set; }
[Index(8)]
[Index(28)]
public int Bomber { get; set; }
/// <summary>
/// This will update a DB Fleet recrod with this CSV Data. DB/EF Handling
/// has to be done by the caller, we'll take care of none PK properties
/// only.
/// </summary>
/// <param name="dbFleet">record to fill</param>
public void UpdateDbFleet(Model.Fleet dbFleet)
{
if (dbFleet == null)
throw new InvalidOperationException("Cannot update a null DB fleet instance");
dbFleet.FleetName = FleetName;
dbFleet.X = X;
dbFleet.Y = Y;
dbFleet.Planet = Planet;
dbFleet.Destination = Destination;
dbFleet.BattlePlan = BattlePlan;
dbFleet.ShipCount = ShipCount;
dbFleet.Ironium = Ironium;
dbFleet.Boranium = Boranium;
dbFleet.Germanium = Germanium;
dbFleet.Colonists = Colonists;
dbFleet.Fuel = Fuel;
dbFleet.OwnerFileId = OwnerFileId;
dbFleet.ETA = ETA;
dbFleet.Warp = Warp;
dbFleet.Mass = Mass;
dbFleet.Cloak = Cloak;
dbFleet.Scan = Scan;
dbFleet.PenScan = PenScan;
dbFleet.Task = Task;
dbFleet.Mining = Mining;
dbFleet.Sweep = Sweep;
dbFleet.Laying = Laying;
dbFleet.Terraforming = Terraforming;
dbFleet.Unarmed = Unarmed;
dbFleet.Scout = Scout;
dbFleet.Warship = Warship;
dbFleet.Utility = Utility;
}
}

View File

@ -0,0 +1,77 @@
using System;
using System.Diagnostics.CodeAnalysis;
using CsvHelper.Configuration;
using CsvHelper;
using System.Globalization;
using Splat;
using StarsAssistant.Services;
using Avalonia.Animation;
namespace StarsAssistant.CSV;
public class FleetLoader
{
/// <summary>
/// Reference to the game metadata, retrieved by DI
/// </summary>
protected Services.Game Game = Locator.Current.GetService<Services.Game>()!;
/// <summary>
/// CSV Configuration to use for importing Planet files.
/// </summary>
protected CsvConfiguration CsvConfig;
/// <summary>
/// Construction
/// </summary>
public FleetLoader()
{
CreateConfig();
}
/// <summary>
/// Creates the CSV configuration for planets.
/// </summary>
[MemberNotNull(nameof(CsvConfig))]
protected void CreateConfig()
{
CsvConfig = CsvConfiguration.FromAttributes<Fleet>(CultureInfo.InvariantCulture);
CsvConfig.Delimiter = "\t";
CsvConfig.Escape = '\0';
CsvConfig.MissingFieldFound = null;
}
/// <summary>
/// Import the fleet file for the given Race, all other records will be ignored.
/// Since we can't update existing records, we will delete all applicable ones
/// before inserting new Fleets.
/// </summary>
/// <param name="race">Import File</param>
public void ImportForRace(Model.Race race)
{
using var db = Locator.Current.GetService<Model.StarsDatabase>()!;
using var reader = new StreamReader(Game.FleetFileForRace(race), System.Text.Encoding.Latin1);
using var csv = new CsvReader(reader, CsvConfig);
var oldFleetsToDelete = from flt in db.Fleet
where flt.OwnerFileId == race.PlayerFileId
select flt;
db.RemoveRange(oldFleetsToDelete);
List<CSV.Fleet> records = csv.GetRecords<Fleet>().ToList();
var fleetsForPlayer = from flt in records
where flt.OwnerFileId == race.PlayerFileId
select flt;
foreach (var csvFleet in fleetsForPlayer)
{
Model.Fleet dbFleet = new();
csvFleet.UpdateDbFleet(dbFleet);
dbFleet.OwnerId = race.Name;
db.Add(dbFleet);
}
db.SaveChanges();
}
}

View File

@ -215,7 +215,7 @@ public class Planet
public int? DriverWarp { get; set; }
[Index(32)]
public string? RouteTarget { get; set; }
public string RouteTarget { get; set; } = String.Empty;
[Index(33)]
public int? GateRange { get; set; }
@ -231,7 +231,7 @@ public class Planet
/// must already be set, DB/EF Handling has to be done by the caller, we'll take
/// care of none PK properties only.
/// </summary>
/// <param name="dbPlanet"></param>
/// <param name="dbPlanet">record to fill</param>
public void UpdateDbPlanet(Model.Planet dbPlanet)
{
if (dbPlanet == null)

View File

@ -1,10 +1,15 @@
using System;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
namespace StarsAssistant.Model;
public class Fleet
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int Id { get; set; }
#region Persistant propeties (from Stars)
public string FleetName { get; set; } = String.Empty;
@ -31,7 +36,9 @@ public class Fleet
public int Fuel { get; set; }
public int OwnerPlayerNumber { get; set; }
public string OwnerId { get; set; } = String.Empty;
public int OwnerFileId { get; set; }
public int ETA { get; set; }
@ -66,4 +73,10 @@ public class Fleet
public int Bomber { get; set; }
#endregion
#region Relationships
public Race? Owner { get; set; }
#endregion
}

View File

@ -83,7 +83,9 @@ public class Race
#region Relationships
public ICollection<Planet> Planets { get; } = new List<Planet>();
public ICollection<Planet> Planets { get; set; } = [];
public ICollection<Fleet> Fleets { get; set; } = [];
#endregion

View File

@ -29,15 +29,18 @@ public class StarsDatabase(string DbPath) : DbContext
#endregion
#region IStarsDatabase Implementation
public DbContext DbContext => this;
#region DbSets
/// <summary>
/// List of all Planets read.
/// </summary>
public DbSet<Planet> Planet { get; set; }
/// <summary>
/// List of all Fleets read.
/// </summary>
public DbSet<Fleet> Fleet { get; set; }
/// <summary>
/// Lists of all defined races.
/// </summary>

View File

@ -89,6 +89,13 @@ public class Game
/// <returns>Fully qualified file path.</returns>
public string PlanetFileForRace (Race r) => Path.Combine(GamePath, $"{BaseName}.p{r.PlayerFileId}");
/// <summary>
/// Get the name of a planet file for a given race.
/// </summary>
/// <param name="r">The race to load.</param>
/// <returns>Fully qualified file path.</returns>
public string FleetFileForRace (Race r) => Path.Combine(GamePath, $"{BaseName}.f{r.PlayerFileId}");
/// <summary>
/// Save this record in the database. Uses the service locator to access the
/// database unless you specify an instance. This is needed during initial
@ -176,8 +183,12 @@ public class Game
db.Add(r);
db.SaveChanges();
var loader = new CSV.PlanetLoader();
loader.ImportForRace(Services.Game.Player);
var planetLoader = new CSV.PlanetLoader();
planetLoader.ImportForRace(Services.Game.Player);
var fleetLoader = new CSV.FleetLoader();
fleetLoader.ImportForRace(Services.Game.Player);
}
}