diff --git a/Sources/Data/Stub.cs b/Sources/Data/Stub.cs index 5b68c6a..29f2ef7 100644 --- a/Sources/Data/Stub.cs +++ b/Sources/Data/Stub.cs @@ -21,9 +21,9 @@ namespace Data Player player1 = new("Alice"), player2 = new("Bob"), player3 = new("Clyde"); IManager<(string, IEnumerable>)> globalDieManager = new DieManager(); - - // create at least one fav group in there + // create at least one group in there // ... + IEnumerable> dice1; (_, dice1) = globalDieManager.GetAll().First(); IEnumerable> dice2; diff --git a/Sources/Model/Dice/ColorDie.cs b/Sources/Model/Dice/ColorDie.cs index 6d4ae41..454e4d6 100644 --- a/Sources/Model/Dice/ColorDie.cs +++ b/Sources/Model/Dice/ColorDie.cs @@ -9,7 +9,7 @@ using System.Threading.Tasks; namespace Model.Dice { - public class ColorDie : AbstractDie + public class ColorDie : AbstractDie { public ColorDie(params ColorDieFace[] faces) : base(faces) { diff --git a/Sources/Model/Dice/ImageDie.cs b/Sources/Model/Dice/ImageDie.cs index 3396042..7a8879b 100644 --- a/Sources/Model/Dice/ImageDie.cs +++ b/Sources/Model/Dice/ImageDie.cs @@ -7,7 +7,7 @@ using System.Threading.Tasks; namespace Model.Dice { - public class ImageDie : AbstractDie + public class ImageDie : AbstractDie { public ImageDie(params ImageDieFace[] faces) : base(faces) { diff --git a/Sources/Model/Dice/NumberDie.cs b/Sources/Model/Dice/NumberDie.cs index d1c2dc9..013c5fa 100644 --- a/Sources/Model/Dice/NumberDie.cs +++ b/Sources/Model/Dice/NumberDie.cs @@ -7,7 +7,7 @@ using System.Threading.Tasks; namespace Model.Dice { - public class NumberDie : AbstractDie + public class NumberDie : AbstractDie { public NumberDie(params NumberDieFace[] faces) : base(faces) { diff --git a/Sources/Model/Games/Game.cs b/Sources/Model/Games/Game.cs index 9dd95bf..0134cc4 100644 --- a/Sources/Model/Games/Game.cs +++ b/Sources/Model/Games/Game.cs @@ -91,8 +91,8 @@ namespace Model.Games public void PerformTurn(Player player) { Turn turn = Turn.CreateWithDefaultTime( - new Player(player), - ThrowAll() //using a copy so that next lines can't "change history" + new Player(player), //using a copy so that next lines can't "change history" + ThrowAll() ); turns.Add(turn); nextIndex++; @@ -151,12 +151,12 @@ namespace Model.Games /// throws all the Dice in FavGroup and returns a list of their Faces /// /// list of AbstractDieFaces after a throw - private List ThrowAll() + private Dictionary, AbstractDieFace> ThrowAll() { - List faces = new(); + Dictionary, AbstractDieFace> faces = new(); foreach (AbstractDie die in dice) { - faces.Add(die.GetRandomFace()); + faces.Add(die, die.GetRandomFace()); } return faces; } @@ -165,12 +165,12 @@ namespace Model.Games { return playerManager.Add(player); } - + public IEnumerable GetPlayersFromGame() { return playerManager.GetAll(); } - + public Player UpdatePlayerInGame(Player oldPlayer, Player newPlayer) { return playerManager.Update(oldPlayer, newPlayer); @@ -180,7 +180,7 @@ namespace Model.Games { playerManager.Remove(player); } - + /// /// represents a Game in string format /// diff --git a/Sources/Model/Games/Turn.cs b/Sources/Model/Games/Turn.cs index 8ae0a37..7b2abca 100644 --- a/Sources/Model/Games/Turn.cs +++ b/Sources/Model/Games/Turn.cs @@ -4,6 +4,7 @@ using System.Collections.Generic; using System.Collections.ObjectModel; using System.Linq; using System.Text; +using Model.Dice; using Model.Dice.Faces; using Model.Players; @@ -22,17 +23,17 @@ namespace Model.Games /// /// the date and time, adjusted to UTC /// - public readonly DateTime when; + public DateTime When { get; private set; } /// /// the Player who rolled the dice /// - public readonly Player player; + public Player Player { get; private set; } /// /// the collection of Face that were rolled /// - private readonly IEnumerable faces; + public Dictionary, AbstractDieFace> DiceNFaces { get; } /// /// this private constructor is to be used only by factories @@ -40,11 +41,11 @@ namespace Model.Games /// date and time of the turn /// player who played the turn /// faces that were rolled - private Turn(DateTime when, Player player, IEnumerable faces) + private Turn(DateTime when, Player player, Dictionary, AbstractDieFace> diceNFaces) { - this.when = when; - this.player = player; - this.faces = faces; + When = when; + Player = player; + DiceNFaces = diceNFaces; } /// @@ -57,23 +58,26 @@ namespace Model.Games /// player who played the turn /// faces that were rolled /// a new Turn object - public static Turn CreateWithSpecifiedTime(DateTime when, Player player, IEnumerable faces) + public static Turn CreateWithSpecifiedTime(DateTime when, Player player, Dictionary, AbstractDieFace> diceNFaces) { - - if (faces is null || !faces.Any()) - { - throw new ArgumentException("param should not be null or empty", nameof(faces)); - } if (player is null) { throw new ArgumentNullException(nameof(player), "param should not be null"); } + if (diceNFaces is null) + { + throw new ArgumentNullException(nameof(diceNFaces), "param should not be null"); + } + if (diceNFaces.Count == 0) + { + throw new ArgumentException("param should not be null", nameof(diceNFaces)); + } if (when.Kind != DateTimeKind.Utc) { when = when.ToUniversalTime(); } - return new Turn(when, player, faces); + return new Turn(when, player, diceNFaces); } /// @@ -82,9 +86,9 @@ namespace Model.Games /// player who played the turn /// faces that were rolled /// a new Turn object - public static Turn CreateWithDefaultTime(Player player, IEnumerable faces) + public static Turn CreateWithDefaultTime(Player player, Dictionary, AbstractDieFace> diceNFaces) { - return CreateWithSpecifiedTime(DateTime.UtcNow, player, faces); + return CreateWithSpecifiedTime(DateTime.UtcNow, player, diceNFaces); } /// @@ -93,7 +97,7 @@ namespace Model.Games /// a turn in string format public override string ToString() { - string[] datetime = when.ToString("s", System.Globalization.CultureInfo.InvariantCulture).Split("T"); + string[] datetime = When.ToString("s", System.Globalization.CultureInfo.InvariantCulture).Split("T"); string date = datetime[0]; string time = datetime[1]; @@ -102,9 +106,8 @@ namespace Model.Games sb.AppendFormat("{0} {1} -- {2} rolled:", date, time, - player.ToString()); - - foreach (AbstractDieFace face in faces) + Player.ToString()); + foreach (AbstractDieFace face in DiceNFaces.Values) { sb.Append(" " + face.ToString()); } diff --git a/Sources/Tests/Model_UTs/TurnTest.cs b/Sources/Tests/Model_UTs/TurnTest.cs new file mode 100644 index 0000000..a00ac87 --- /dev/null +++ b/Sources/Tests/Model_UTs/TurnTest.cs @@ -0,0 +1,193 @@ +using Model.Dice; +using Model.Dice.Faces; +using Model.Games; +using Model.Players; +using System; +using System.Collections.Generic; +using System.Diagnostics; +using Xunit; + +namespace Tests.Model_UTs +{ + public class TurnTest + + { + private readonly Dictionary, AbstractDieFace> DICE_N_FACES; + private static readonly AbstractDieFace FACE_ONE = new NumberDieFace(1); + private static readonly AbstractDieFace FACE_TWO = new NumberDieFace(12); + private static readonly AbstractDieFace FACE_THREE = new ImageDieFace(54); + private static readonly AbstractDieFace FACE_FOUR = new ColorDieFace(16548); + + private readonly static NumberDieFace[] FACES1 = new NumberDieFace[] + { + FACE_ONE as NumberDieFace, + new NumberDieFace(2), + new NumberDieFace(3), + new NumberDieFace(4) + }; + + private readonly static NumberDieFace[] FACES2 = new NumberDieFace[] { + new NumberDieFace(9), + new NumberDieFace(10), + new NumberDieFace(11), + FACE_TWO as NumberDieFace, + new NumberDieFace(13), + new NumberDieFace(14) + }; + + private readonly static ImageDieFace[] FACES3 = new ImageDieFace[] { + new ImageDieFace(13), + new ImageDieFace(27), + new ImageDieFace(38), + FACE_THREE as ImageDieFace + }; + + private readonly static ColorDieFace[] FACES4 = new ColorDieFace[] { + new(11651), + new(24651), + FACE_FOUR as ColorDieFace, + new(412) + }; + + + private readonly AbstractDie NUM1 = new NumberDie(FACES1); + private readonly AbstractDie NUM2 = new NumberDie(FACES2); + private readonly AbstractDie IMG1 = new ImageDie(FACES3); + private readonly AbstractDie CLR1 = new ColorDie(FACES4); + + + + public TurnTest() + { + DICE_N_FACES = new() + { + { NUM1, FACE_ONE }, + { NUM2, FACE_TWO }, + { IMG1, FACE_THREE }, + { CLR1, FACE_FOUR } + }; + } + + + + [Fact] + public void TestCreateWithSpecifiedTimeNotUTCThenValid() + { + // Arrange + DateTime dateTime = new(year: 2018, month: 06, day: 15, hour: 16, minute: 30, second: 0, kind: DateTimeKind.Local); + Player player = new("Alice"); + Assert.NotEqual(DateTimeKind.Utc, dateTime.Kind); + + // Act + Turn turn = Turn.CreateWithSpecifiedTime(dateTime, player, DICE_N_FACES); + + // Assert + Assert.Equal(DateTimeKind.Utc, turn.When.Kind); + Assert.Equal(dateTime.ToUniversalTime(), turn.When); + } + + + + [Fact] + public void TestCreateWithSpecifiedTimeUTCThenValid() + { + // Arrange + DateTime dateTime = new(year: 2018, month: 06, day: 15, hour: 16, minute: 30, second: 0, kind: DateTimeKind.Utc); + Player player = new("Bobby"); + Assert.Equal(DateTimeKind.Utc, dateTime.Kind); + + // Act + Turn turn = Turn.CreateWithSpecifiedTime(dateTime, player, DICE_N_FACES); + + // Assert + Assert.Equal(DateTimeKind.Utc, turn.When.Kind); + Assert.Equal(dateTime.ToUniversalTime(), turn.When); + } + + + [Fact] + public void TestCreateWithSpecifiedTimeNullPlayerThenException() + { + // Arrange + DateTime dateTime = new(year: 2018, month: 06, day: 15, hour: 16, minute: 30, second: 0, kind: DateTimeKind.Utc); + + // Act + void action() => Turn.CreateWithSpecifiedTime(dateTime, null, DICE_N_FACES); + + // Assert + Assert.Throws(action); + } + + [Fact] + public void TestCreateWithSpecifiedTimeNullFacesThenException() + { + // Arrange + DateTime dateTime = new(year: 2018, month: 06, day: 15, hour: 16, minute: 30, second: 0, kind: DateTimeKind.Utc); + Player player = new("Chucky"); + + // Act + void action() => Turn.CreateWithSpecifiedTime(dateTime, player, null); + + // Assert + Assert.Throws(action); + } + + + [Fact] + public void TestCreateWithSpecifiedTimeEmptyFacesThenException() + { + // Arrange + DateTime dateTime = new(year: 2018, month: 06, day: 15, hour: 16, minute: 30, second: 0, kind: DateTimeKind.Utc); + Player player = new("Chucky"); + DICE_N_FACES.Clear(); + + // Act + void action() => Turn.CreateWithSpecifiedTime(dateTime, player, DICE_N_FACES); + + // Assert + Assert.Throws(action); + } + + + + [Fact] + public void TestCreateWithDefaultTimeThenValid() + { + // Arrange + Player player = new("Chloe"); + + // Act + Turn turn = Turn.CreateWithDefaultTime(player, DICE_N_FACES); + + // Assert + Assert.Equal(DateTimeKind.Utc, turn.When.Kind); + Assert.Equal(DateTime.Now.ToUniversalTime().Date, turn.When.Date); + // N.B.: might fail between 11:59:59PM and 00:00:00AM + } + + + + [Fact] + public void TestToStringValidIfAllNormal() + { + // Arrange + DateTime dateTime = new(year: 2018, month: 06, day: 15, hour: 16, minute: 30, second: 0, kind: DateTimeKind.Utc); + string name = "Bobby"; + Player player = new(name); + string expected = $"2018-06-15 16:30:00 -- {name} rolled: " + + FACE_ONE.ToString() + " " + + FACE_TWO.ToString() + " " + + FACE_THREE.ToString() + " " + + FACE_FOUR.ToString(); + + Turn turn = Turn.CreateWithSpecifiedTime(dateTime, player, DICE_N_FACES); + + // Act + string actual = turn.ToString(); + Debug.WriteLine(actual); + + // Assert + Assert.Equal(expected, actual); + } + } +}