using Model.Dice; using Model.Dice.Faces; using Model.Players; using System; using System.Collections.Generic; 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 = 0; /// /// 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.ToList() ?? new List(); this.playerManager = playerManager; this.dice = dice; } /// /// 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( new Player(player), //using a copy so that next lines can't "change history" ThrowAll() ); turns.Add(turn); nextIndex++; } /// /// 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.AppendFormat("Game: {0}===========\n" + "{1} are playing. {2} is next.\n" + "Log:\n", Name, playerManager.GetAll().ToString(), GetWhoPlaysNow()); foreach (Turn turn in this.turns) { sb.Append("\t" + turn.ToString()); } return sb.ToString(); } } }