// public static IConfiguration Configuration { get; set; } public static void Main(string[] args) { string workingDir = Path.GetDirectoryName(System.Reflection.Assembly.GetEntryAssembly().Location); if (args.Any(a => a.ToLowerInvariant().StartsWith("-help") || a.ToLowerInvariant().StartsWith("-?"))) { // Print help Console.WriteLine("??? NEEDS HELP TEXT"); // Exit early return; } var configBuilder = new ConfigurationBuilder().SetBasePath(Directory.GetCurrentDirectory()); configBuilder.AddJsonFile(Path.Combine(workingDir, "appsettings.json"), true, true); var config = configBuilder.Build(); string defaultUnitXML = Path.Combine(workingDir, config["Default_Unit_Xml"] ?? "DefaultUnit.xml"); string defaultEngineXML = Path.Combine(workingDir, config["Default_GameEngine_Xml"] ?? "DefaultGameEngine.xml"); GameState gameState = GameStateStreamUtilities.LoadFromXml(defaultEngineXML); Console.WriteLine($"GameEngine [{gameState.Id}] from {gameState.SourceFile} loaded successfully."); Console.WriteLine(); ConsoleReadoutUtilities.GenerateGameEngineReadout(gameState).ForEach(l => Console.WriteLine(l)); }
public static void RecordExchangeReport(GameState gameState, string originalSourceFile, ILogger logger) { var destFileName = Path.GetFileNameWithoutExtension(originalSourceFile) + $".ExchangeResults.{gameState.Exchange}" + Path.GetExtension(originalSourceFile); var destFileFullName = Path.Combine( Path.GetDirectoryName(Assembly.GetEntryAssembly().Location), destFileName); gameState.SourceFile = destFileFullName; logger.LogInformation($" - Exchange {gameState.Exchange} completed report saving to:" + $"\n {gameState.SourceFile}"); GameStateStreamUtilities.SaveToFile(gameState.SourceFile, gameState); }
public static void RecordVolleyReport(GameState gameState, string originalSourceFile, string destinationFolder, ILogger logger) { var destFileName = $"Game-{gameState.Id}.{Path.GetFileNameWithoutExtension(originalSourceFile)}.VolleyResults.E{gameState.Exchange}V{gameState.Volley}" + Path.GetExtension(originalSourceFile); destFileName = destFileName.Replace($"Game-{gameState.Id}.Game-{gameState.Id}.", $"Game-{gameState.Id}."); var destFileFullName = Path.Combine( destinationFolder, destFileName); gameState.SourceFile = destFileFullName; logger.LogInformation($" - Volley {gameState.Volley} interim report saving to:" + $"\n {gameState.SourceFile}"); GameStateStreamUtilities.SaveToFile(gameState.SourceFile, gameState); }
public void GameEngineFileSerializeDeserializeTest() { GameState ge = new GameState() { Id = 99, Exchange = 99, Volley = 99, Turn = 99 }; var stream = new MemoryStream(); GameStateStreamUtilities.SaveToStream(stream, ge); var newGE = GameStateStreamUtilities.LoadFromStream(stream); Assert.AreEqual(newGE.Id, ge.Id); Assert.AreEqual(newGE.Exchange, ge.Exchange); Assert.AreEqual(newGE.Volley, ge.Volley); Assert.AreEqual(newGE.Turn, ge.Turn); }
public void TestCloning() { // GameEngine uses a "cheat" and routes its clone method through a serialize/deserialize operation: GameState ge = new GameState() { Id = 99, Exchange = 99, Volley = 99, Turn = 99 }; GameState newGE = GameStateStreamUtilities.CloneGameState(ge); newGE.Id = 0; newGE.Volley = 0; Assert.AreNotEqual(newGE.Id, ge.Id); Assert.AreNotEqual(newGE.Volley, ge.Volley); Assert.AreEqual(newGE.Exchange, ge.Exchange); Assert.AreEqual(newGE.Turn, ge.Turn); BeamBatterySystem b1 = new BeamBatterySystem() { Arcs = "FP,F,FS", Rating = 2 }; ScreenSystem d1 = new ScreenSystem() { StatusString = "Operational" }; HullSystem h1 = new HullSystem() { HullType = HullTypeProperty.Average }; var b2 = b1.Clone() as ArcWeaponSystem; var d2 = d1.Clone() as DefenseSystem; var h2 = h1.Clone() as HullSystem; h1.HullType = HullTypeProperty.Strong; var h1a = h1.Clone() as HullSystem; h1a.HullType = HullTypeProperty.Super; var h2a = h2.Clone() as HullSystem; var a1 = new ArmorSystem() { TotalArmor = "4,5", RemainingArmor = "4,5" }; DefenseSystem a2 = (DefenseSystem)a1.Clone(); ((ArmorSystem)a2).TotalArmor = "5,5"; ((ArmorSystem)a2).RemainingArmor = "4,4"; var a2a = a1.Clone() as DefenseSystem; b2.Arcs = "AP, P, FP"; d2.StatusString = "Damaged"; Console.WriteLine($"B1 is a {b1.GetType().FullName} and its clone B2 is a {b2.GetType().FullName}"); Assert.AreEqual(b1.GetType(), b2.GetType()); Console.WriteLine($"D1 is a {d1.GetType().FullName} and its clone D2 is a {d2.GetType().FullName}"); Console.WriteLine($"H1 is a {h1.GetType().FullName} and its clone H2 is a {h2.GetType().FullName}"); Console.WriteLine($"A1 is a {a1.GetType().FullName} and its clone A2 is a {a2.GetType().FullName}"); Console.WriteLine($"Changing H1's HullType and then making a clone H1a, which is also a {h1a.GetType().FullName}"); Console.WriteLine($"Making a clone of H2 H2a, which is also a {h2a.GetType().FullName}"); Console.WriteLine($"B1 arcs : [{b1.Arcs}]"); Console.WriteLine($"B2 arcs : [{b2.Arcs}]"); Console.WriteLine($"D1 status: [{d1.StatusString}]"); Console.WriteLine($"D2 status: [{d2.StatusString}]"); Console.WriteLine($"H1 type : [{h1.HullType}]"); Console.WriteLine($"H1a type : [{h1a.HullType}]"); Console.WriteLine($"H2 type : [{h2.HullType}]"); Console.WriteLine($"H2a type : [{h2a.HullType}]"); Console.WriteLine($"A1 totalArmor : [{a1.TotalArmor}]"); Console.WriteLine($"A2 totalArmor : [{((ArmorSystem)a2).TotalArmor}] (Cloned as DefenseSystem, cast to ArmorSystem)"); // Ensure cloning results in no type changes Assert.AreEqual(d1.GetType(), d2.GetType()); Assert.AreEqual(h1.GetType(), h2.GetType()); Assert.AreEqual(a1.GetType(), a2.GetType()); // Ensure cloning results in separate references Assert.AreNotEqual(h1.HullType, h1a.HullType); Assert.AreNotEqual(h1.HullType, h2.HullType); Assert.AreNotEqual(b1.Arcs, b2.Arcs); Assert.AreNotEqual(a1.TotalArmor, ((ArmorSystem)a2).TotalArmor); // Ensure cloning results in identical values unless changed Assert.AreEqual(h2.HullType, h2a.HullType); }
public static void Main(string[] args) { // TODO: add ability to pass an arbitrary GameEngineXML path argument instead of using default string workingDir = Path.GetDirectoryName(System.Reflection.Assembly.GetEntryAssembly().Location); var configBuilder = new ConfigurationBuilder().SetBasePath(Directory.GetCurrentDirectory()); configBuilder.AddJsonFile(Path.Combine(workingDir, "appsettings.json"), true, true); foreach (var jsonConfig in args.Where(a => a.EndsWith(".json"))) { configBuilder.AddJsonFile(jsonConfig); } // Woohoo Dependency Injection! var services = new ServiceCollection() .AddLogging() .AddSingleton <IDiceUtility, DiceNotationUtility>() .AddSingleton(configBuilder.Build()) .BuildServiceProvider(); services.GetService <ILoggerFactory>() .AddConsole() .AddDebug(); var logger = services.GetLogger("VolleyResolver"); logger.LogInformation("Service Collection initialized successfully"); IConfigurationRoot config = services.GetService <IConfigurationRoot>(); if (args.Any(a => a.ToLowerInvariant().StartsWith("-help") || a.ToLowerInvariant().StartsWith("-?"))) { // Print help logger.LogInformation("??? NEEDS HELP TEXT"); // Exit early return; } // TODO: adapt this so it can take args on the commandline for input-XML and output-XML locations // TODO: adapt this so it can take unit-data XML files / dirs on the commandline and use them to flesh out Player/Ship entries string defaultUnitXML = Path.Combine(workingDir, config["Default_Unit_Xml"] ?? "DefaultUnit.xml"); string defaultEngineXML = Path.Combine(workingDir, config["Default_GameEngine_Xml"] ?? "DefaultGameEngine.xml"); string destinationFolder = config["GameEngine_Xml_OutPath"] ?? workingDir; int volleysPerExchange = DefaultVolleysPerExchange; var vPEStr = config["Volleys_Per_Exchange"]; if (!int.TryParse(vPEStr, out volleysPerExchange)) { volleysPerExchange = DefaultVolleysPerExchange; } GameState gameState = GameStateStreamUtilities.LoadFromXml(defaultEngineXML); var originalSource = defaultEngineXML; gameState.SourceFile = originalSource; logger.LogInformation($"GameEngine [{gameState.Id}] from {gameState.SourceFile} loaded successfully."); logger.LogInformation("Begin Volley Resolution!"); for (int v = gameState.Volley; v <= volleysPerExchange; v++) { logger.LogInformation("***"); logger.LogInformation($"EXCHANGE {gameState.Exchange}, VOLLEY {v}"); PrintDistanceGraph(gameState, logger); gameState = VolleyResolutionEngine.ResolveVolley(gameState, v, gameState.SourceFile, services); PrintDistanceGraph(gameState, logger); VolleyResolutionEngine.RecordVolleyReport(gameState, originalSource, destinationFolder, logger); } // Set up for a new Exchange by clearing out this Exchange's scripting gameState.SourceFile = originalSource; VolleyResolutionEngine.RecordExchangeReport(gameState, originalSource, logger); var oldFile = new FileInfo(originalSource); var oldFileName = oldFile.Name; var oldFileExt = oldFile.Extension; var oldFilePath = oldFile.DirectoryName; var newFileName = $"E{gameState.Exchange + 1}-{oldFileName}".Replace($"E{gameState.Exchange}", string.Empty); var newFile = new FileInfo(Path.Combine(oldFilePath, newFileName)); logger.LogInformation("***"); logger.LogInformation($"Exchange {gameState.Exchange} resolution completed! " + $"\n Saving resulting state back to enable Exchange {gameState.Exchange + 1} scripting:" + $"\n {newFile.FullName}"); gameState.Exchange++; gameState.Volley = 1; gameState.ClearOrders(); gameState.SourceFile = newFile.FullName; // Dispose the serviceCollection to cause all included services to dispose; // Among other possible finalization effects, this *should* flush the logger. // (Does this need to be done BEFORE SaveToFile() is done? (services as IDisposable)?.Dispose(); GameStateStreamUtilities.SaveToFile(newFile.FullName, gameState); }