using Model.Dice; using Model.Dice.Faces; using Model.Players; using System; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Linq; using System.Threading.Tasks; 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 = 0; /// /// the turns that have been done so far /// private readonly List turns = new(); /// /// get a READ ONLY enumerable of all turns belonging to this game /// /// a readonly enumerable of all this game's turns public ReadOnlyCollection GetHistory() => new(turns); /// /// 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 ReadOnlyCollection Dice => new(dice); private readonly List dice = new(); /// /// 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.dice.AddRange(dice); this.turns.AddRange(turns); } /// /// 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, new List()) { } /// /// 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 async Task GetWhoPlaysNow() { if (!(await PlayerManager.GetAll()).Any()) { throw new MemberAccessException("you are exploring an empty collection\nthis should not have happened"); } return (await PlayerManager.GetAll()).ElementAt(nextIndex); } /// /// this feels very dirty /// /// the current player /// /// /// public async Task PrepareNextPlayer(Player current) { IEnumerable players = await 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)); } nextIndex = (nextIndex + 1) % players.Count(); } /// /// 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; } } }