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