using Model.Dice; using Model.Dice.Faces; using Model.Players; using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace Model.Games { public class Game { /// /// the name of the game 😎 /// public string Name { get { return name; } set // MasterOfCeremonies 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 /// public IManager PlayerManager { get; private set; } /// /// 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; PlayerManager = playerManager; this.turns = turns is null ? new List() : turns.ToList(); 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() ); AddTurn(turn); } private void AddTurn(Turn turn) { if (!(turns.Contains(turn))) { turns.Add(turn); } } /// /// 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) { IEnumerable players = PlayerManager.GetAll(); if (!players.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 (!players.Contains(current)) { throw new ArgumentException("param could not be found in this collection\n did you forget to add it?", nameof(current)); } if (players.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 ThrowAll() { Dictionary faces = new(); foreach (Die die in dice) { faces.Add(die, die.GetRandomFace()); } 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()) { 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(); } } }