Merge pull request '👔 Complete #14 create-game-class' (#57) from create-game-class into main
continuous-integration/drone/push Build is passing Details

Reviewed-on: #57
pull/58/head
Alexis Drai 2 years ago
commit 021d47e07f

@ -15,12 +15,7 @@ namespace Data
public GameRunner LoadApp()
{
// this doesn't do much for now, because the classes aren't coded
List<Game> games = new()
{
new Game("a"),
new Game("b"),
new Game("c")
};
List<Game> games = new();
PlayerManager gpm = new();
gpm.Add(new Player("Alice"));

@ -1,10 +1,22 @@
using System.Collections.Generic;
using System;
using System.Collections.Generic;
using Model.Dice.Faces;
namespace Model.Dice
{
public class Die
{
private IEnumerable<AbstractDieFace> faces;
private static readonly Random random = new Random();
private List<AbstractDieFace> faces;
public AbstractDieFace Throw()
{
// next(x, y) --> [x, y[
return faces[random.Next(0, faces.Count)];
// replace with better algo later
}
}
}

@ -1,10 +1,13 @@
using System.Collections.Generic;
using Model.Players;
using System.Collections.Generic;
namespace Model.Dice
{
public class FavGroup
{
private IEnumerable<Die> dice;
public IEnumerable<Die> Dice { get; private set; }
public string Name { get; private set; }
}
}

@ -1,20 +1,175 @@
using System;
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;
using System.Threading.Tasks;
namespace Model.Games
{
public class Game
{
public string Name { get; private set; }
/// <summary>
/// the name of the game 😎
/// </summary>
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;
/// <summary>
/// whether this game is new or not
/// </summary>
public bool IsFirstTurn { get; private set; } = false;
/// <summary>
/// the turns that have been done so far
/// </summary>
private readonly List<Turn> turns;
/// </summary>
/// get a READ ONLY enumerable of all turns belonging to this game
/// </summary>
/// <returns>a readonly enumerable of all this game's turns</returns>
public IEnumerable<Turn> GetHistory() => turns.AsEnumerable();
private readonly IEnumerable<Turn> turns = new List<Turn>();
/// <summary>
/// the game's player manager, doing CRUD on players and switching whose turn it is
/// </summary>
private readonly PlayerManager playerManager;
public Game(string name)
/// <summary>
/// the group of dice used for this game
/// </summary>
private readonly FavGroup favGroup;
/// <summary>
/// constructs a Game with its own history of Turns.
/// If <paramref name="turns"/> is null, starts a new history
/// </summary>
/// <param name="name">the name of the game 😎</param>
/// <param name="turns">the turns that have been done so far</param>
/// <param name="playerManager">the game's player manager, doing CRUD on players and switching whose turn it is</param>
/// <param name="favGroup">the group of dice used for this game</param>
public Game(string name, PlayerManager playerManager, FavGroup favGroup, IEnumerable<Turn> turns)
{
Name = name;
this.turns = turns.ToList() ?? new List<Turn>();
this.playerManager = playerManager;
this.favGroup = favGroup;
}
/// <summary>
/// constructs a Game with no history of turns.
/// </summary>
/// <param name="name">the name of the game 😎</param>
/// <param name="playerManager">the game's player manager, doing CRUD on players and switching whose turn it is</param>
/// <param name="favGroup">the group of dice used for this game</param>
public Game(string name, PlayerManager playerManager, FavGroup favGroup)
: this(name, playerManager, favGroup, null)
{ }
/// <summary>
/// performs a Turn, marks this Game as "started", and logs that Turn
/// </summary>
/// <param name="player">the player whose turn it is</param>
public void PerformTurn(Player player)
{
if (IsFirstTurn) { IsFirstTurn = false; } // only true one time (on the first turn...)
Turn turn = Turn.CreateWithDefaultTime(
new Player(player),
ThrowAll() //using a copy so that next line doesn't "change history"
);
turns.Add(turn);
}
/// <summary>
/// finds whose turn it is
/// </summary>
/// <returns>the Player whose turn it is</returns>
public Player GetWhoPlaysNow()
{
return playerManager.WhoPlaysNow(IsFirstTurn);
}
/// <summary>
/// throws all the Dice in FavGroup and returns a list of their Faces
/// </summary>
/// <returns>list of AbstractDieFaces after a throw</returns>
private List<AbstractDieFace> ThrowAll()
{
List<AbstractDieFace> faces = new();
foreach (Die die in favGroup.Dice)
{
faces.Add(die.Throw());
}
return faces;
}
/// <summary>
/// asks the PlayerManager to prepare the next Player
/// </summary>
/// <param name="currentPlayer">the Player whose turn it was</param>
public void PrepareNextPlayer(Player currentPlayer)
{
playerManager.PrepareNextPlayer(currentPlayer);
}
public Player AddPlayerToGame(Player player)
{
return playerManager.Add(player);
}
public IEnumerable<Player> GetPlayersFromGame()
{
return playerManager.GetAll();
}
public Player UpdatePlayerInGame(Player oldPlayer, Player newPlayer)
{
return playerManager.Update(oldPlayer, newPlayer);
}
public void RemovePlayerFromGame(Player player)
{
playerManager.Remove(player);
}
/// <summary>
/// represents a Game in string format
/// </summary>
/// <returns>a Game in string format</returns>
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(),
playerManager.WhoPlaysNow(IsFirstTurn));
foreach (Turn turn in this.turns)
{
sb.Append("\t" + turn.ToString());
}
return sb.ToString();
}
}
}

@ -7,11 +7,16 @@ namespace Model.Players
public class PlayerManager : IManager<Player>
{
/// <summary>
/// a hashset of the players that this manager is in charge of
/// a collection of the players that this manager is in charge of
/// </summary>
private readonly List<Player> players;
/// <summary>
/// references the position in list of the current player, for a given game.
/// <br/>
/// each player is unique (set), and the hash is based on the player's values (name)
/// ASSUMING that each Game made its own instance of PlayerManager
/// </summary>
private readonly HashSet<Player> players;
public int NextIndex { get; private set; } = 0;
public PlayerManager()
{
@ -24,12 +29,16 @@ namespace Model.Players
/// <returns>added player, or null if <paramref name="toAdd"/> was null</returns>
public Player Add(Player toAdd)
{
if (toAdd != null)
if (toAdd is null)
{
throw new ArgumentNullException(nameof(toAdd), "param should not be null");
}
if (players.Contains(toAdd))
{
players.Add(toAdd);
return toAdd;
throw new ArgumentException("this username is already taken", nameof(toAdd));
}
throw new ArgumentNullException(nameof(toAdd), "param should not be null");
players.Add(toAdd);
return toAdd;
}
/// <summary>
@ -68,6 +77,64 @@ namespace Model.Players
/// <returns>a readonly enumerable of all this manager's players</returns>
public IEnumerable<Player> GetAll() => players.AsEnumerable();
/// <summary>
/// finds and returns the player whose turn it is
/// </summary>
/// <returns></returns>
/// <exception cref="Exception"></exception>
public Player WhoPlaysNow(bool isFirstTurn)
{
if (players.Count == 0)
{
throw new MemberAccessException("you are exploring an empty collection\nthis should not have happened");
}
Player result;
if (isFirstTurn)
{
result = players[0];
}
else
{
result = players[NextIndex];
}
return result;
}
/// <summary>
/// this feels very dirty
/// </summary>
/// <param name="current"></param>
/// <exception cref="Exception"></exception>
/// <exception cref="ArgumentNullException"></exception>
/// <exception cref="ArgumentException"></exception>
public void PrepareNextPlayer(Player current)
{
if (players.Count == 0)
{
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 index, we need to loop back around
NextIndex = 0;
}
else
{
// else we can just move up one from current
NextIndex++;
}
}
/// <summary>
/// update a player from <paramref name="before"/> to <paramref name="after"/>
/// </summary>
@ -101,7 +168,7 @@ namespace Model.Players
{
throw new ArgumentNullException(nameof(toRemove), "param should not be null");
}
// the built-in HashSet.Remove() method will use our redefined Equals(), using Name only
// the built-in Remove() method will use our redefined Equals(), using Name only
players.Remove(toRemove);
}
}

Loading…
Cancel
Save