diff --git a/Stars Assistant/CSV/Fleet.cs b/Stars Assistant/CSV/Fleet.cs index 4f4b9e7..b758825 100644 --- a/Stars Assistant/CSV/Fleet.cs +++ b/Stars Assistant/CSV/Fleet.cs @@ -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; } + /// + /// 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. + /// + /// record to fill + 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; + + } + } \ No newline at end of file diff --git a/Stars Assistant/CSV/FleetLoader.cs b/Stars Assistant/CSV/FleetLoader.cs new file mode 100644 index 0000000..ee6c8e9 --- /dev/null +++ b/Stars Assistant/CSV/FleetLoader.cs @@ -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 +{ + /// + /// Reference to the game metadata, retrieved by DI + /// + protected Services.Game Game = Locator.Current.GetService()!; + + /// + /// CSV Configuration to use for importing Planet files. + /// + protected CsvConfiguration CsvConfig; + + /// + /// Construction + /// + public FleetLoader() + { + CreateConfig(); + } + + /// + /// Creates the CSV configuration for planets. + /// + [MemberNotNull(nameof(CsvConfig))] + protected void CreateConfig() + { + CsvConfig = CsvConfiguration.FromAttributes(CultureInfo.InvariantCulture); + CsvConfig.Delimiter = "\t"; + CsvConfig.Escape = '\0'; + CsvConfig.MissingFieldFound = null; + } + + /// + /// 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. + /// + /// Import File + public void ImportForRace(Model.Race race) + { + using var db = Locator.Current.GetService()!; + 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 records = csv.GetRecords().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(); + } + +} diff --git a/Stars Assistant/CSV/Planet.cs b/Stars Assistant/CSV/Planet.cs index dc8b9c4..db86afe 100644 --- a/Stars Assistant/CSV/Planet.cs +++ b/Stars Assistant/CSV/Planet.cs @@ -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. /// - /// + /// record to fill public void UpdateDbPlanet(Model.Planet dbPlanet) { if (dbPlanet == null) diff --git a/Stars Assistant/Model/Fleet.cs b/Stars Assistant/Model/Fleet.cs index ee46f59..f2dcf85 100644 --- a/Stars Assistant/Model/Fleet.cs +++ b/Stars Assistant/Model/Fleet.cs @@ -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 } diff --git a/Stars Assistant/Model/Race.cs b/Stars Assistant/Model/Race.cs index 2bdf7b6..0e23297 100644 --- a/Stars Assistant/Model/Race.cs +++ b/Stars Assistant/Model/Race.cs @@ -83,7 +83,9 @@ public class Race #region Relationships - public ICollection Planets { get; } = new List(); + public ICollection Planets { get; set; } = []; + + public ICollection Fleets { get; set; } = []; #endregion diff --git a/Stars Assistant/Model/StarsDatabase.cs b/Stars Assistant/Model/StarsDatabase.cs index 23a5a0a..a7f9761 100644 --- a/Stars Assistant/Model/StarsDatabase.cs +++ b/Stars Assistant/Model/StarsDatabase.cs @@ -29,15 +29,18 @@ public class StarsDatabase(string DbPath) : DbContext #endregion - #region IStarsDatabase Implementation - - public DbContext DbContext => this; + #region DbSets /// /// List of all Planets read. /// public DbSet Planet { get; set; } + /// + /// List of all Fleets read. + /// + public DbSet Fleet { get; set; } + /// /// Lists of all defined races. /// diff --git a/Stars Assistant/Services/Game.cs b/Stars Assistant/Services/Game.cs index 4bae313..ca70861 100644 --- a/Stars Assistant/Services/Game.cs +++ b/Stars Assistant/Services/Game.cs @@ -89,6 +89,13 @@ public class Game /// Fully qualified file path. public string PlanetFileForRace (Race r) => Path.Combine(GamePath, $"{BaseName}.p{r.PlayerFileId}"); + /// + /// Get the name of a planet file for a given race. + /// + /// The race to load. + /// Fully qualified file path. + public string FleetFileForRace (Race r) => Path.Combine(GamePath, $"{BaseName}.f{r.PlayerFileId}"); + /// /// 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); + } }