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();
}
}
}