diff --git a/Sources/App/App.csproj b/Sources/App/App.csproj index 3f594df..4d04cc8 100644 --- a/Sources/App/App.csproj +++ b/Sources/App/App.csproj @@ -6,11 +6,19 @@ $(MSBuildProjectDirectory) + + + Content + PreserveNewest + + + all runtime; build; native; contentfiles; analyzers; buildtransitive + diff --git a/Sources/App/NLog.config b/Sources/App/NLog.config new file mode 100644 index 0000000..9d5ffca --- /dev/null +++ b/Sources/App/NLog.config @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Sources/App/Program.cs b/Sources/App/Program.cs index bd66be8..b2f3ffb 100644 --- a/Sources/App/Program.cs +++ b/Sources/App/Program.cs @@ -10,12 +10,17 @@ using System.Collections.Generic; using System.Diagnostics; using System.Drawing; using System.Linq; +using System.Numerics; +using System.Text; using System.Threading.Tasks; +using System.Xml.Linq; namespace App { internal static class Program { + private static NLog.Logger logger = NLog.LogManager.GetCurrentClassLogger(); + static async Task Main(string[] args) { // MODEL stuff @@ -27,8 +32,7 @@ namespace App } catch (Exception ex) { - Console.WriteLine(ex.Message); - Console.WriteLine(ex.StackTrace); + logger.Warn(ex); masterOfCeremonies = new(new PlayerManager(), new DiceGroupManager(), null); } @@ -43,22 +47,18 @@ namespace App PlayerDbManager playerDbManager = new(db); IEnumerable entities = await playerDbManager.GetAll(); - - Debug.WriteLine("Loading players"); - foreach (PlayerEntity entity in entities) { try { // persist them as models ! await masterOfCeremonies.GlobalPlayerManager.Add(entity.ToModel()); - Debug.WriteLine($"{entity.ID} -- {entity.Name}"); } - catch (Exception ex) { Debug.WriteLine($"{ex.Message}\n... Never mind"); } + catch (Exception ex) { Console.WriteLine($"{ex.Message}\n... Never mind"); } } } } - catch (Exception ex) { Debug.WriteLine($"{ex.Message}\n... Couldn't use the database"); } + catch (Exception ex) { Console.WriteLine($"{ex.Message}\n... Couldn't use the database"); } string menuChoice = "nothing"; @@ -186,22 +186,21 @@ namespace App // create a PlayerDbManager (and inject it with the DB) PlayerDbManager playerDbManager = new(db); - Debug.WriteLine("Saving players"); - foreach (Player model in models) { try // to persist them { // as entities ! PlayerEntity entity = model.ToEntity(); await playerDbManager.Add(entity); - Debug.WriteLine($"{entity.ID} -- {entity.Name}"); } // what if there's already a player with that name? Exception (see PlayerEntity's annotations) - catch (ArgumentException ex) { Debug.WriteLine($"{ex.Message}\n... Never mind"); } + catch (ArgumentException ex) { Console.WriteLine($"{ex.Message}\n... Never mind"); } } } + // flushing and closing NLog before quitting completely + NLog.LogManager.Shutdown(); } - catch (Exception ex) { Debug.WriteLine($"{ex.Message}\n... Couldn't use the database"); } + catch (Exception ex) { Console.WriteLine($"{ex.Message}\n... Couldn't use the database"); } } private static async Task Play(MasterOfCeremonies masterOfCeremonies, string name) @@ -210,7 +209,7 @@ namespace App while (menuChoicePlay != "q") { Game game = await masterOfCeremonies.GameManager.GetOneByName(name); - Console.WriteLine($"{game.GetWhoPlaysNow()}'s turn\n" + + Console.WriteLine($"{PlayerToString(await game.GetWhoPlaysNow())}'s turn\n" + "q... quit\n" + "h... show history\n" + "s... save\n" + @@ -221,17 +220,14 @@ namespace App case "q": break; case "h": - foreach (Turn turn in game.GetHistory()) - { - Console.WriteLine(turn); - } + foreach (Turn turn in game.GetHistory()) { Console.WriteLine(TurnToString(turn)); } break; case "s": await masterOfCeremonies.GameManager.Add(game); break; default: await MasterOfCeremonies.PlayGame(game); - Console.WriteLine(game.GetHistory().Last()); + Console.WriteLine(TurnToString(game.GetHistory().Last())); break; } } @@ -243,7 +239,7 @@ namespace App Console.WriteLine("which of these games?\n(choose by name)\n>"); foreach (Game game in await masterOfCeremonies.GameManager.GetAll()) { - Console.WriteLine(game); + Console.WriteLine(GameToString(game)); } name = Console.ReadLine(); return name; @@ -254,7 +250,7 @@ namespace App Console.WriteLine("Look at all them players!"); foreach (Player player in await masterOfCeremonies.GlobalPlayerManager.GetAll()) { - Console.WriteLine(player); + Console.WriteLine(PlayerToString(player)); } } @@ -262,7 +258,7 @@ namespace App { foreach ((string name, IEnumerable dice) in await masterOfCeremonies.DiceGroupManager.GetAll()) { - Console.WriteLine($"{name} -- {dice}"); + Console.WriteLine($"{name} -- {dice}"); // maybe code a quick and dirty DieToString() } } @@ -335,11 +331,13 @@ namespace App catch (ArgumentNullException ex) { Console.WriteLine(ex.Message); + logger.Warn(ex); } catch (UriFormatException ex) { Console.WriteLine("that URI was not valid"); Console.WriteLine(ex.Message); + logger.Warn(ex); } } } @@ -356,7 +354,7 @@ namespace App if (menuChoice.Equals("ok") && count == 0) { Console.WriteLine("create at least one valid face"); - menuChoice = ""; // persiste en dehors du scope de cette fonction + menuChoice = ""; // persists outside the scope of this function } } @@ -396,7 +394,7 @@ namespace App Player player = new(menuChoicePlayers); if (!(await masterOfCeremonies.GlobalPlayerManager.GetAll()).Contains(player)) { - // if the player didn't exist, now it does... this is temporary + // if the player didn't exist, now it does... await masterOfCeremonies.GlobalPlayerManager.Add(player); } // almost no checks, this is temporary @@ -404,12 +402,57 @@ namespace App { await result.Add(player); } - catch (ArgumentException ex) { Debug.WriteLine($"{ex.Message}\n... Never mind"); } + catch (ArgumentException ex) { Console.WriteLine($"{ex.Message}\n... Never mind"); } } } return result; } + private static string TurnToString(Turn turn) + { + string[] datetime = turn.When.ToString("s", System.Globalization.CultureInfo.InvariantCulture).Split("T"); + string date = datetime[0]; + string time = datetime[1]; + + StringBuilder sb = new(); + + sb.AppendFormat("{0} {1} -- {2} rolled:", + date, + time, + PlayerToString(turn.Player)); + foreach (KeyValuePair kvp in turn.DiceNFaces) + { + sb.Append(" " + kvp.Value.StringValue); + } + + return sb.ToString(); + } + + private async static Task GameToString(Game game) + { + StringBuilder sb = new(); + sb.Append($"Game: {game.Name}"); + + sb.Append("\nPlayers:"); + foreach (Player player in game.PlayerManager.GetAll()?.Result) + { + sb.Append($" {PlayerToString(player)}"); + } + + sb.Append($"\nNext: {PlayerToString(await game.GetWhoPlaysNow())}"); + + sb.Append("\nLog:\n"); + foreach (Turn turn in game.GetHistory()) + { + sb.Append($"\t{TurnToString(turn)}\n"); + } + return sb.ToString(); + } + + private static string PlayerToString(Player player) + { + return player.Name; + } } } \ No newline at end of file diff --git a/Sources/Data/Data.csproj b/Sources/Data/Data.csproj index a96003f..af3c9e2 100644 --- a/Sources/Data/Data.csproj +++ b/Sources/Data/Data.csproj @@ -13,6 +13,7 @@ all runtime; build; native; contentfiles; analyzers; buildtransitive + diff --git a/Sources/Data/EF/Players/PlayerDBManager.cs b/Sources/Data/EF/Players/PlayerDBManager.cs index 99b9ab8..ab80257 100644 --- a/Sources/Data/EF/Players/PlayerDBManager.cs +++ b/Sources/Data/EF/Players/PlayerDBManager.cs @@ -6,13 +6,17 @@ namespace Data.EF.Players { public sealed class PlayerDbManager : IManager { + private static readonly NLog.Logger logger = NLog.LogManager.GetCurrentClassLogger(); + private readonly DiceAppDbContext db; public PlayerDbManager(DiceAppDbContext db) { if (db is null) { - throw new ArgumentNullException(nameof(db), "param should not be null"); + ArgumentNullException ex = new(nameof(db), "param should not be null"); + logger.Error(ex, "attempted to construct PlayerDbManager with a null context"); + throw ex; } this.db = db; } @@ -27,11 +31,15 @@ namespace Data.EF.Players { if (entity is null) { - throw new ArgumentNullException(nameof(entity), "param should not be null"); + ArgumentNullException ex = new(nameof(entity), "param should not be null"); + logger.Warn(ex); + throw ex; } if (string.IsNullOrWhiteSpace(entity.Name)) { - throw new ArgumentException("Name property should not be null or whitespace", nameof(entity)); + ArgumentException ex = new("Name property should not be null or whitespace", nameof(entity)); + logger.Warn(ex); + throw ex; } entity.Name = entity.Name.Trim(); } @@ -49,7 +57,9 @@ namespace Data.EF.Players if (db.PlayerEntity.Where(entity => entity.Name == toAdd.Name).Any()) { - throw new ArgumentException("this username is already taken", nameof(toAdd)); + ArgumentException ex = new("this username is already taken", nameof(toAdd)); + logger.Warn(ex); + throw ex; } return InternalAdd(toAdd); @@ -59,6 +69,7 @@ namespace Data.EF.Players { EntityEntry ee = await db.PlayerEntity.AddAsync(toAdd); await db.SaveChangesAsync(); + logger.Info("Added {0}", ee.Entity.ToString()); return (PlayerEntity)ee.Entity; } @@ -116,6 +127,7 @@ namespace Data.EF.Players if (isPresent) { db.PlayerEntity.Remove(toRemove); + logger.Info("Removed {0}", toRemove.ToString()); db.SaveChanges(); } } @@ -139,11 +151,12 @@ namespace Data.EF.Players if (before.ID != after.ID) { - throw new ArgumentException("ID cannot be updated", nameof(after)); + ArgumentException ex = new("ID cannot be updated", nameof(after)); + logger.Warn(ex); + throw ex; } return InternalUpdate(before, after); - } private async Task InternalUpdate(PlayerEntity before, PlayerEntity after) diff --git a/Sources/Data/EF/Players/PlayerDbManager.cs b/Sources/Data/EF/Players/PlayerDbManager.cs index 99b9ab8..ab80257 100644 --- a/Sources/Data/EF/Players/PlayerDbManager.cs +++ b/Sources/Data/EF/Players/PlayerDbManager.cs @@ -6,13 +6,17 @@ namespace Data.EF.Players { public sealed class PlayerDbManager : IManager { + private static readonly NLog.Logger logger = NLog.LogManager.GetCurrentClassLogger(); + private readonly DiceAppDbContext db; public PlayerDbManager(DiceAppDbContext db) { if (db is null) { - throw new ArgumentNullException(nameof(db), "param should not be null"); + ArgumentNullException ex = new(nameof(db), "param should not be null"); + logger.Error(ex, "attempted to construct PlayerDbManager with a null context"); + throw ex; } this.db = db; } @@ -27,11 +31,15 @@ namespace Data.EF.Players { if (entity is null) { - throw new ArgumentNullException(nameof(entity), "param should not be null"); + ArgumentNullException ex = new(nameof(entity), "param should not be null"); + logger.Warn(ex); + throw ex; } if (string.IsNullOrWhiteSpace(entity.Name)) { - throw new ArgumentException("Name property should not be null or whitespace", nameof(entity)); + ArgumentException ex = new("Name property should not be null or whitespace", nameof(entity)); + logger.Warn(ex); + throw ex; } entity.Name = entity.Name.Trim(); } @@ -49,7 +57,9 @@ namespace Data.EF.Players if (db.PlayerEntity.Where(entity => entity.Name == toAdd.Name).Any()) { - throw new ArgumentException("this username is already taken", nameof(toAdd)); + ArgumentException ex = new("this username is already taken", nameof(toAdd)); + logger.Warn(ex); + throw ex; } return InternalAdd(toAdd); @@ -59,6 +69,7 @@ namespace Data.EF.Players { EntityEntry ee = await db.PlayerEntity.AddAsync(toAdd); await db.SaveChangesAsync(); + logger.Info("Added {0}", ee.Entity.ToString()); return (PlayerEntity)ee.Entity; } @@ -116,6 +127,7 @@ namespace Data.EF.Players if (isPresent) { db.PlayerEntity.Remove(toRemove); + logger.Info("Removed {0}", toRemove.ToString()); db.SaveChanges(); } } @@ -139,11 +151,12 @@ namespace Data.EF.Players if (before.ID != after.ID) { - throw new ArgumentException("ID cannot be updated", nameof(after)); + ArgumentException ex = new("ID cannot be updated", nameof(after)); + logger.Warn(ex); + throw ex; } return InternalUpdate(before, after); - } private async Task InternalUpdate(PlayerEntity before, PlayerEntity after) diff --git a/Sources/DiceApp.sln b/Sources/DiceApp.sln index e9e8a18..1879c6a 100644 --- a/Sources/DiceApp.sln +++ b/Sources/DiceApp.sln @@ -11,7 +11,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Data", "Data\Data.csproj", "{E9683741-E603-4ED3-8088-4099D67FCA6D}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Utils", "Utils\Utils\Utils.csproj", "{9300910D-9D32-4C79-8868-67D0ED56E2F3}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Utils", "Utils\Utils\Utils.csproj", "{9300910D-9D32-4C79-8868-67D0ED56E2F3}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution diff --git a/Sources/DiceAppConsole.sln b/Sources/DiceAppConsole.sln index b9d9678..7496da5 100644 --- a/Sources/DiceAppConsole.sln +++ b/Sources/DiceAppConsole.sln @@ -16,7 +16,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Data", "Data\Data.csproj", "{E9683741-E603-4ED3-8088-4099D67FCA6D}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Utils", "Utils\Utils\Utils.csproj", "{9300910D-9D32-4C79-8868-67D0ED56E2F3}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Utils", "Utils\Utils\Utils.csproj", "{9300910D-9D32-4C79-8868-67D0ED56E2F3}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution diff --git a/Sources/Model/Games/Game.cs b/Sources/Model/Games/Game.cs index 6f9ae7d..a49fd3b 100644 --- a/Sources/Model/Games/Game.cs +++ b/Sources/Model/Games/Game.cs @@ -169,31 +169,5 @@ namespace Model.Games } return faces; } - - /// - /// represents a Game in string format - /// - /// a Game in string format - public override string ToString() - { - StringBuilder sb = new(); - sb.Append($"Game: {Name}"); - - sb.Append("\nPlayers:"); - foreach (Player player in PlayerManager.GetAll()?.Result) - { - sb.Append($" {player.ToString()}"); - } - - sb.Append($"\nNext: {GetWhoPlaysNow()}"); - - sb.Append("\nLog:\n"); - foreach (Turn turn in this.turns) - { - sb.Append($"\t{turn.ToString()}\n"); - } - - return sb.ToString(); - } } } diff --git a/Sources/Model/Games/Turn.cs b/Sources/Model/Games/Turn.cs index e45df9a..c6a118f 100644 --- a/Sources/Model/Games/Turn.cs +++ b/Sources/Model/Games/Turn.cs @@ -87,30 +87,6 @@ namespace Model.Games return CreateWithSpecifiedTime(DateTime.UtcNow, player, diceNFaces); } - /// - /// represents a turn in string format - /// - /// a turn in string format - public override string ToString() - { - string[] datetime = When.ToString("s", System.Globalization.CultureInfo.InvariantCulture).Split("T"); - string date = datetime[0]; - string time = datetime[1]; - - StringBuilder sb = new(); - - sb.AppendFormat("{0} {1} -- {2} rolled:", - date, - time, - Player.ToString()); - foreach (Face face in this.diceNFaces.Values) - { - sb.Append(" " + face.StringValue); - } - - return sb.ToString(); - } - public bool Equals(Turn other) { return Player.Equals(other.Player) diff --git a/Sources/Model/Model.csproj b/Sources/Model/Model.csproj index dbc1517..8a46421 100644 --- a/Sources/Model/Model.csproj +++ b/Sources/Model/Model.csproj @@ -4,4 +4,8 @@ net6.0 + + + + diff --git a/Sources/Model/Players/Player.cs b/Sources/Model/Players/Player.cs index 86d214f..477cb99 100644 --- a/Sources/Model/Players/Player.cs +++ b/Sources/Model/Players/Player.cs @@ -30,11 +30,6 @@ namespace Model.Players : this(player?.Name) // passes the player's name if player exists, else null { } - public override string ToString() - { - return Name; - } - public bool Equals(Player other) { return other is not null && Name.ToUpper() == other.Name.ToUpper(); // equality is case insensitive diff --git a/Sources/Tests/Model_UTs/Games/GameTest.cs b/Sources/Tests/Model_UTs/Games/GameTest.cs index 39a9d30..95cb95c 100644 --- a/Sources/Tests/Model_UTs/Games/GameTest.cs +++ b/Sources/Tests/Model_UTs/Games/GameTest.cs @@ -142,8 +142,6 @@ namespace Tests.Model_UTs.Games await game.PrepareNextPlayer(currentPlayer); } - Debug.WriteLine(game); - // Act int actual = game.GetHistory().Count(); int expected = n; diff --git a/Sources/Tests/Model_UTs/Players/PlayerTest.cs b/Sources/Tests/Model_UTs/Players/PlayerTest.cs index ca244d0..5e03d36 100644 --- a/Sources/Tests/Model_UTs/Players/PlayerTest.cs +++ b/Sources/Tests/Model_UTs/Players/PlayerTest.cs @@ -65,20 +65,6 @@ namespace Tests.Model_UTs.Players Assert.Throws(action); } - [Fact] - public void TestToStringCorrectName() - { - // Arrange - string expected = "Bob"; - Player player = new(expected); - - // Act - string actual = player.ToString(); - - // Assert - Assert.Equal(expected, actual); - } - [Fact] public void TestEqualsFalseIfNotPlayer() {