using Model.Dice; using Model.Dice.Faces; using Model.Players; using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Numerics; using System.Text; namespace Model.Games { public class Game { /// /// the name of the game 😎 /// public string Name { get { return name; } set // GameRunner will need to take care of forbidding // (or allowing) having two Games with the same name etc. { if (string.IsNullOrWhiteSpace(value)) { throw new ArgumentException("param should not be null or blank", nameof(value)); } name = value; } } private string name; /// /// references the position in list of the current player, for a given game. /// private int nextIndex; /// /// the turns that have been done so far /// private readonly List turns; /// /// get a READ ONLY enumerable of all turns belonging to this game /// /// a readonly enumerable of all this game's turns public IEnumerable GetHistory() => turns.AsEnumerable(); /// /// the game's player manager, doing CRUD on players and switching whose turn it is /// private readonly IManager playerManager; /// /// the group of dice used for this game /// public IEnumerable> Dice => dice; private readonly IEnumerable> dice; /// /// constructs a Game with its own history of Turns. /// If is null, starts a new history /// /// the name of the game 😎 /// the turns that have been done so far /// the game's player manager, doing CRUD on players and switching whose turn it is /// the group of dice used for this game public Game(string name, IManager playerManager, IEnumerable> dice, IEnumerable turns) { Name = name; this.turns = turns is null ? new List() : turns.ToList(); this.playerManager = playerManager; this.dice = dice; this.nextIndex = 0; } /// /// constructs a Game with no history of turns. /// /// the name of the game 😎 /// the game's player manager, doing CRUD on players and switching whose turn it is /// the group of dice used for this game public Game(string name, IManager playerManager, IEnumerable> dice) : this(name, playerManager, dice, null) { } /// /// performs a Turn, marks this Game as "started", and logs that Turn /// /// the player whose turn it is public void PerformTurn(Player player) { Turn turn = Turn.CreateWithDefaultTime( player, ThrowAll() ); if(AddTurn(turn) == null) { // log an error onc we have a logger ? Debug.WriteLine("tried to add two identical turns: " + turn); } } private Turn AddTurn(Turn turn) { if (!(turns.Contains(turn))) { turns.Add(turn); return turn; } return null; } /// /// finds and returns the player whose turn it is /// /// /// public Player GetWhoPlaysNow() { if (!playerManager.GetAll().Any()) { throw new MemberAccessException("you are exploring an empty collection\nthis should not have happened"); } return playerManager.GetAll().ElementAt(nextIndex); } /// /// this feels very dirty /// /// the current player /// /// /// public void PrepareNextPlayer(Player current) { if (!playerManager.GetAll().Any()) { throw new MemberAccessException("you are exploring an empty collection\nthis should not have happened"); } if (current == null) { throw new ArgumentNullException(nameof(current), "param should not be null"); } if (!playerManager.GetAll().Contains(current)) { throw new ArgumentException("param could not be found in this collection\n did you forget to add it?", nameof(current)); } if (playerManager.GetAll().Last() == current) { // if we've reached the last player, we need the index to loop back around nextIndex = 0; } else { // else we can just move up by one from the current index nextIndex++; } } /// /// throws all the Dice in FavGroup and returns a list of their Faces /// /// list of AbstractDieFaces after a throw private Dictionary, AbstractDieFace> ThrowAll() { Dictionary, AbstractDieFace> faces = new(); foreach (AbstractDie die in dice) { faces.Add(die, die.GetRandomFace()); } return faces; } public Player AddPlayerToGame(Player player) { return playerManager.Add(player); } public IEnumerable GetPlayersFromGame() { return playerManager.GetAll(); } public Player UpdatePlayerInGame(Player oldPlayer, Player newPlayer) { return playerManager.Update(oldPlayer, newPlayer); } public void RemovePlayerFromGame(Player player) { playerManager.Remove(player); } /// /// 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 GetPlayersFromGame()) { 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(); } } }