using Model.Dice; using Model.Dice.Faces; using Model.Players; using System; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Linq; namespace Model.Games { /// /// a Turn consists of a Player, a DateTime, and a IEnumerable of AbstractDieFace /// Like a turn in some game. /// public sealed class Turn : IEquatable { /// /// the date and time, adjusted to UTC /// public DateTime When { get; private set; } /// /// the Player who rolled the dice /// public Player Player { get; private set; } /// /// the collection of Face that were rolled /// public ReadOnlyDictionary DiceNFaces => new(diceNFaces); private readonly Dictionary diceNFaces; /// /// this private constructor is to be used only by factories /// /// date and time of the turn /// player who played the turn /// faces that were rolled private Turn(DateTime when, Player player, IEnumerable> diceNFaces) { 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.Any()) { throw new ArgumentException("param should not be null", nameof(diceNFaces)); } if (when.Kind != DateTimeKind.Utc) { when = when.ToUniversalTime(); } When = when; Player = player; this.diceNFaces = diceNFaces.ToDictionary(kvp => kvp.Key, kvp => kvp.Value); } /// /// creates a Turn with a specified time, passed as a parameter. ///
/// whatever the DateTimeKind of might be, /// it will become UTC during construction ///
/// date and time of the turn /// player who played the turn /// faces that were rolled /// a new Turn object public static Turn CreateWithSpecifiedTime(DateTime when, Player player, IEnumerable> diceNFaces) { return new Turn(when, player, diceNFaces); } /// /// creates a Turn with a default time, which is "now" in UTC. /// /// player who played the turn /// faces that were rolled /// a new Turn object public static Turn CreateWithDefaultTime(Player player, IEnumerable> diceNFaces) { return CreateWithSpecifiedTime(DateTime.UtcNow, player, diceNFaces); } public bool Equals(Turn other) { if (other is null || !(Player.Equals(other.Player) && When.Equals(other.When) && DiceNFaces.Count == other.DiceNFaces.Count)) { return false; } // 🤮 for (int i = 0; i < DiceNFaces.Count; i++) { if (DiceNFaces.ElementAt(i).Key.Faces.Count != other.DiceNFaces.ElementAt(i).Key.Faces.Count) { return false; } if (!other.DiceNFaces.ElementAt(i).Value.StringValue .Equals(DiceNFaces.ElementAt(i).Value.StringValue)) { return false; } for (int j = 0; j < DiceNFaces.ElementAt(i).Key.Faces.Count; j++) { if (!other.DiceNFaces.ElementAt(i).Key.Faces.ElementAt(j).StringValue .Equals(DiceNFaces.ElementAt(i).Key.Faces.ElementAt(j).StringValue)) { return false; } } } return true; } public override bool Equals(object obj) { if (obj is not Turn) { return false; } return Equals(obj as Turn); } public override int GetHashCode() { return When.GetHashCode(); } } }