reworked app startup
This commit is contained in:
@ -16,30 +16,58 @@ public partial class CSVDataLoader : IEnableLogger
|
||||
/// </summary>
|
||||
protected Services.Game Game = Locator.Current.GetService<Services.Game>()!;
|
||||
|
||||
/// <summary>
|
||||
/// Regex to match fs watcher results to Stars file types.
|
||||
/// </summary>
|
||||
/// <returns>Precompiled RegEx</returns>
|
||||
[GeneratedRegex(@".*\.(?<type>[pf])(?<player>\d)+$")]
|
||||
private static partial Regex MyRegex();
|
||||
|
||||
/// <summary>
|
||||
/// RegEx Instance to match Stars file types.
|
||||
/// </summary>
|
||||
protected Regex FileTypeRegEx = MyRegex();
|
||||
|
||||
/// <summary>
|
||||
/// Instance of the FSWatcher, to which we subscribe.
|
||||
/// </summary>
|
||||
protected IObservable<FileSystemEventArgs> Watcher;
|
||||
|
||||
/// <summary>
|
||||
/// Active subscription to FsWatcher.
|
||||
/// </summary>
|
||||
protected IDisposable? Subscription;
|
||||
|
||||
/// <summary>
|
||||
/// Construct the instance and prepare our FS Watcher.
|
||||
/// </summary>
|
||||
public CSVDataLoader()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public void StartPlanetCSVWatcher()
|
||||
{
|
||||
// string[] filters = { "*.p*", "*.f*", "*.map" };
|
||||
|
||||
var watcher = FsWatcher
|
||||
Watcher = FsWatcher
|
||||
.ObserveFileSystem(Game.GamePath, [ Game.PlanetFileSearchPattern ])
|
||||
.ThrottleAndDistinct(2, RxApp.TaskpoolScheduler)
|
||||
.Log(this, $"{DateTime.Now.ToLongTimeString()} FsEvent", fsEvent => $"{fsEvent.FullPath} {fsEvent.ChangeType}")
|
||||
.ObserveOn(RxApp.TaskpoolScheduler);
|
||||
|
||||
watcher.Subscribe(fsEvent => this.LoadPlanetFile(fsEvent.FullPath));
|
||||
}
|
||||
|
||||
protected void LoadPlanetFile(string fileName)
|
||||
/// <summary>
|
||||
/// Start the CSV watcher, and capture our disposable, so that we can shut
|
||||
/// down the watcher if needed.
|
||||
/// </summary>
|
||||
public void StartCSVWatcher()
|
||||
{
|
||||
if (Subscription != null)
|
||||
throw new InvalidOperationException("CSV Watcher is active, can't start it again.");
|
||||
|
||||
Subscription = Watcher.Subscribe(fsEvent => this.LoadFile(fsEvent.FullPath));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Subscription to File Processing, called by our subscription to the watcher.
|
||||
/// </summary>
|
||||
/// <param name="fileName">The File to process</param>
|
||||
protected void LoadFile(string fileName)
|
||||
{
|
||||
Match m = FileTypeRegEx.Match(fileName);
|
||||
if (! m.Success)
|
||||
@ -50,9 +78,18 @@ public partial class CSVDataLoader : IEnableLogger
|
||||
|
||||
string type = m.Groups["type"].Value;
|
||||
string player = m.Groups["player"].Value;
|
||||
|
||||
this.Log().Debug($"Got file type {type} for player {player}");
|
||||
var loader = new CSV.PlanetLoader();
|
||||
loader.ImportForRace(Services.Game.Player);
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case "p":
|
||||
var loader = new CSV.PlanetLoader();
|
||||
loader.ImportForRace(Services.Game.Player);
|
||||
break;
|
||||
|
||||
default:
|
||||
this.Log().Warn($"Planet loader got unknown file type ${type}. Ignoring file.");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,6 @@
|
||||
using System.Reflection.PortableExecutable;
|
||||
using Splat;
|
||||
using StarsAssistant.Model;
|
||||
|
||||
namespace StarsAssistant.Services;
|
||||
|
||||
@ -22,28 +23,28 @@ public class Game
|
||||
}
|
||||
|
||||
/// <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
|
||||
/// game creation, where the services are not yet established.
|
||||
/// Helper to construct the game from a command line.
|
||||
/// </summary>
|
||||
/// <param name="db">Optional DB instance if services are yet unavailable.</param>
|
||||
public void SaveToDatabase(Model.StarsDatabase? db = null)
|
||||
/// <param name="args">The command line to parse.</param>
|
||||
public Game(string[]? args)
|
||||
{
|
||||
db ??= Locator.Current.GetService<Model.StarsDatabase>()!;
|
||||
|
||||
Model.Game? dbGame = db.Game.FirstOrDefault();
|
||||
if (dbGame == null)
|
||||
{
|
||||
dbGame = new Model.Game();
|
||||
db.Add(dbGame);
|
||||
db.SaveChanges();
|
||||
}
|
||||
dbGame.GamePath = GamePath;
|
||||
dbGame.BaseName = BaseName;
|
||||
db.Update(dbGame);
|
||||
db.SaveChanges();
|
||||
}
|
||||
GamePath = "/home/torben/Nextcloud/Documents/Stars!/Games/goingth/";
|
||||
BaseName = "GOINGTH";
|
||||
string dbPath = DatabaseFileName;
|
||||
|
||||
using StarsDatabase starsDB = new(dbPath);
|
||||
if (Path.Exists(dbPath))
|
||||
{
|
||||
Model.Game dbGame = starsDB.Game.First();
|
||||
}
|
||||
else
|
||||
{
|
||||
starsDB.Database.EnsureCreated();
|
||||
SaveToDatabase(starsDB);
|
||||
__doCreateTestData = true;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The base path in which all game files reside.
|
||||
/// </summary>
|
||||
@ -68,9 +69,9 @@ public class Game
|
||||
/// <summary>
|
||||
/// Internal helper to lazily load the current player from the DB.
|
||||
/// </summary>
|
||||
private readonly static Lazy<Model.Race>LazyPlayer = new ( () => {
|
||||
using var db = Locator.Current.GetService<Model.StarsDatabase>()!;
|
||||
Model.Race result = db.Race
|
||||
private readonly static Lazy<Race>LazyPlayer = new ( () => {
|
||||
using var db = Locator.Current.GetService<StarsDatabase>()!;
|
||||
Race result = db.Race
|
||||
.Where(r => r.PlayerRace == true)
|
||||
.First();
|
||||
return result;
|
||||
@ -79,13 +80,99 @@ public class Game
|
||||
/// <summary>
|
||||
/// Get the Race object for the current player, lazy initialized.
|
||||
/// </summary>
|
||||
public static Model.Race Player => LazyPlayer.Value;
|
||||
public static Race Player => LazyPlayer.Value;
|
||||
|
||||
/// <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 PlanetFileForRace (Model.Race r) => Path.Combine(GamePath, $"{BaseName}.p{r.PlayerFileId}");
|
||||
public string PlanetFileForRace (Race r) => Path.Combine(GamePath, $"{BaseName}.p{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
|
||||
/// game creation, where the services are not yet established.
|
||||
/// </summary>
|
||||
/// <param name="db">Optional DB instance if services are yet unavailable.</param>
|
||||
public void SaveToDatabase(StarsDatabase? db = null)
|
||||
{
|
||||
db ??= Locator.Current.GetService<StarsDatabase>()!;
|
||||
|
||||
Model.Game? dbGame = db.Game.FirstOrDefault();
|
||||
if (dbGame == null)
|
||||
{
|
||||
dbGame = new Model.Game();
|
||||
db.Add(dbGame);
|
||||
db.SaveChanges();
|
||||
}
|
||||
dbGame.GamePath = GamePath;
|
||||
dbGame.BaseName = BaseName;
|
||||
db.Update(dbGame);
|
||||
db.SaveChanges();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Registers all services depending on this Game, in the order required.
|
||||
/// This is called once the framework is initialized but before the main
|
||||
/// window is active and has its models.
|
||||
/// </summary>
|
||||
public void RegisterServicesForGame()
|
||||
{
|
||||
Locator.CurrentMutable.RegisterConstant(this, typeof(Services.Game));
|
||||
Locator.CurrentMutable.RegisterConstant(new CSVDataLoader(), typeof(CSVDataLoader));
|
||||
Locator.CurrentMutable.Register(() => new StarsDatabase(DatabaseFileName), typeof(StarsDatabase));
|
||||
|
||||
// TESTING HELPER
|
||||
if (__doCreateTestData)
|
||||
__createTestData();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Starts all required background servies, so that we are in normal UI
|
||||
/// operation mode. This is called after the UI is up and running.
|
||||
/// </summary>
|
||||
public void StartBackgroundServices()
|
||||
{
|
||||
CSVDataLoader csvloader = Locator.Current.GetService<Services.CSVDataLoader>()!;
|
||||
csvloader.StartCSVWatcher();
|
||||
}
|
||||
|
||||
|
||||
private bool __doCreateTestData = false;
|
||||
|
||||
/// <summary>
|
||||
/// TESTING HELPER
|
||||
/// </summary>
|
||||
private void __createTestData ()
|
||||
{
|
||||
using var db = Locator.Current.GetService<StarsDatabase>()!;
|
||||
|
||||
// Note: This sample requires the database to be created before running.
|
||||
// Console.WriteLine($"Database path: {db.DbPath}.");
|
||||
|
||||
Race r = new()
|
||||
{
|
||||
Name = "Atlantis",
|
||||
PlayerRace = true,
|
||||
PlayerFileId = 1,
|
||||
ColonistsPerResource = 1000,
|
||||
GrowthRatePercent = 19,
|
||||
PRT = PRT.Other,
|
||||
HasOBRM = true,
|
||||
FactoryCost3 = false,
|
||||
FactoryNumberPer10k = 8,
|
||||
FactoryResCost = 8,
|
||||
FactoryResPer10 = 15,
|
||||
MineResCost = 3,
|
||||
MineMineralsPer10 = 10,
|
||||
MineNumberPer10k = 10
|
||||
};
|
||||
db.Add(r);
|
||||
db.SaveChanges();
|
||||
|
||||
var loader = new CSV.PlanetLoader();
|
||||
loader.ImportForRace(Services.Game.Player);
|
||||
}
|
||||
|
||||
}
|
||||
|
Reference in New Issue
Block a user