🚨 Encapsulate collections... #199

Merged
alexis.drai merged 1 commits from apply-fixes-following-interview into main 2 years ago

@ -7,13 +7,12 @@ using Model.Games;
using Model.Players;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Diagnostics;
using System.Drawing;
using System.Linq;
using System.Numerics;
using System.Text;
using System.Threading.Tasks;
using System.Xml.Linq;
namespace App
{
@ -33,7 +32,7 @@ namespace App
catch (Exception ex)
{
logger.Warn(ex);
masterOfCeremonies = new(new PlayerManager(), new DiceGroupManager(), null);
masterOfCeremonies = new(new PlayerManager(), new DiceGroupManager(), new GameManager());
}
try
@ -154,7 +153,7 @@ namespace App
newGroupDice.Add(die);
}
}
await masterOfCeremonies.DiceGroupManager.Add(new KeyValuePair<string, IEnumerable<Die>>(newGroupName, newGroupDice));
await masterOfCeremonies.DiceGroupManager.Add(new DiceGroup(newGroupName, newGroupDice));
break;
case "p":
@ -256,7 +255,7 @@ namespace App
private static async Task ShowDice(MasterOfCeremonies masterOfCeremonies)
{
foreach ((string name, IEnumerable<Die> dice) in await masterOfCeremonies.DiceGroupManager.GetAll())
foreach ((string name, ReadOnlyCollection<Die> dice) in await masterOfCeremonies.DiceGroupManager.GetAll())
{
Console.WriteLine($"{name} -- {dice}"); // maybe code a quick and dirty DieToString()
}
@ -370,7 +369,7 @@ namespace App
menuChoiceDice = Console.ReadLine();
if (!menuChoiceDice.Equals("ok"))
{
IEnumerable<Die> chosenDice = (await masterOfCeremonies.DiceGroupManager.GetOneByName(menuChoiceDice)).Value;
IEnumerable<Die> chosenDice = (await masterOfCeremonies.DiceGroupManager.GetOneByName(menuChoiceDice)).Dice;
foreach (Die die in chosenDice)
{
result.Add(die);

@ -1,6 +1,7 @@
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.ChangeTracking;
using Model;
using System.Collections.ObjectModel;
namespace Data.EF.Players
{
@ -73,11 +74,11 @@ namespace Data.EF.Players
return (PlayerEntity)ee.Entity;
}
public async Task<IEnumerable<PlayerEntity>> GetAll()
public async Task<ReadOnlyCollection<PlayerEntity>> GetAll()
{
List<PlayerEntity> players = new();
await Task.Run(() => players.AddRange(db.PlayerEntity));
return players.AsEnumerable();
return new ReadOnlyCollection<PlayerEntity>(players);
}
/// <summary>

@ -1,6 +1,7 @@
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.ChangeTracking;
using Model;
using System.Collections.ObjectModel;
namespace Data.EF.Players
{
@ -73,11 +74,11 @@ namespace Data.EF.Players
return (PlayerEntity)ee.Entity;
}
public async Task<IEnumerable<PlayerEntity>> GetAll()
public async Task<ReadOnlyCollection<PlayerEntity>> GetAll()
{
List<PlayerEntity> players = new();
await Task.Run(() => players.AddRange(db.PlayerEntity));
return players.AsEnumerable();
return new ReadOnlyCollection<PlayerEntity>(players);
}
/// <summary>

@ -10,13 +10,13 @@ namespace Data
{
public async Task<MasterOfCeremonies> LoadApp()
{
MasterOfCeremonies gr = new(new PlayerManager(), new DiceGroupManager(), new GameManager());
MasterOfCeremonies mc = new(new PlayerManager(), new DiceGroupManager(), new GameManager());
Player player1 = new("Alice(Old Stub)"), player2 = new("Bob(Old Stub)"), player3 = new("Clyde(Old Stub)");
await gr.GlobalPlayerManager.Add(player1);
await gr.GlobalPlayerManager.Add(player2);
await gr.GlobalPlayerManager.Add(player3);
await mc.GlobalPlayerManager.Add(player1);
await mc.GlobalPlayerManager.Add(player2);
await mc.GlobalPlayerManager.Add(player3);
List<Die> monopolyDice = new();
@ -63,26 +63,26 @@ namespace Data
dndDice.Add(new NumberDie(d20Faces[0], d20Faces[1..]));
await gr.DiceGroupManager.Add(new KeyValuePair<string, IEnumerable<Die>>(dndName, dndDice.AsEnumerable()));
await gr.DiceGroupManager.Add(new KeyValuePair<string, IEnumerable<Die>>(monopolyName, monopolyDice.AsEnumerable()));
await mc.DiceGroupManager.Add(new DiceGroup(dndName, dndDice));
await mc.DiceGroupManager.Add(new DiceGroup(monopolyName, monopolyDice));
string game1 = "Forgotten Realms", game2 = "4e", game3 = "The Coopers";
await gr.GameManager.Add(new(game1, new PlayerManager(), dndDice.AsEnumerable()));
await gr.GameManager.Add(new(game2, new PlayerManager(), dndDice.AsEnumerable()));
await gr.GameManager.Add(new(game3, new PlayerManager(), monopolyDice.AsEnumerable()));
await mc.GameManager.Add(new(game1, new PlayerManager(), dndDice.AsEnumerable()));
await mc.GameManager.Add(new(game2, new PlayerManager(), dndDice.AsEnumerable()));
await mc.GameManager.Add(new(game3, new PlayerManager(), monopolyDice.AsEnumerable()));
await (await gr.GameManager.GetOneByName(game1)).PlayerManager.Add(player1);
await (await gr.GameManager.GetOneByName(game1)).PlayerManager.Add(player2);
await (await mc.GameManager.GetOneByName(game1)).PlayerManager.Add(player1);
await (await mc.GameManager.GetOneByName(game1)).PlayerManager.Add(player2);
await (await gr.GameManager.GetOneByName(game2)).PlayerManager.Add(player1);
await (await gr.GameManager.GetOneByName(game2)).PlayerManager.Add(player2);
await (await gr.GameManager.GetOneByName(game2)).PlayerManager.Add(player3);
await (await mc.GameManager.GetOneByName(game2)).PlayerManager.Add(player1);
await (await mc.GameManager.GetOneByName(game2)).PlayerManager.Add(player2);
await (await mc.GameManager.GetOneByName(game2)).PlayerManager.Add(player3);
await (await gr.GameManager.GetOneByName(game3)).PlayerManager.Add(player1);
await (await gr.GameManager.GetOneByName(game3)).PlayerManager.Add(player3);
await (await mc.GameManager.GetOneByName(game3)).PlayerManager.Add(player1);
await (await mc.GameManager.GetOneByName(game3)).PlayerManager.Add(player3);
foreach (Game game in gr.GameManager.GetAll()?.Result)
foreach (Game game in mc.GameManager.GetAll()?.Result)
{
for (int i = 0; i < 10; i++)
{
@ -92,7 +92,7 @@ namespace Data
}
}
return gr;
return mc;
}
}
}

@ -0,0 +1,45 @@
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
namespace Model.Dice
{
public sealed class DiceGroup : IEquatable<DiceGroup>
{
public string Name { get; private set; }
public ReadOnlyCollection<Die> Dice => new(dice);
private readonly List<Die> dice = new();
public DiceGroup(string name, IEnumerable<Die> dice)
{
Name = name;
this.dice.AddRange(dice);
}
public bool Equals(DiceGroup other)
{
return Name == other.Name && Dice.SequenceEqual(other.Dice);
}
public override bool Equals(object obj)
{
if (obj is null) return false; // is null
if (ReferenceEquals(obj, this)) return true; // is me
if (!obj.GetType().Equals(GetType())) return false; // is different type
return Equals(obj as DiceGroup); // is not me, is not null, is same type : send up
}
public override int GetHashCode()
{
return HashCode.Combine(Name, dice);
}
public void Deconstruct(out string name, out ReadOnlyCollection<Die> dice)
{
dice = Dice;
name = Name;
}
}
}

@ -1,40 +1,41 @@
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Threading.Tasks;
namespace Model.Dice
{
public class DiceGroupManager : IManager<KeyValuePair<string, IEnumerable<Die>>>
public class DiceGroupManager : IManager<DiceGroup>
{
private readonly Dictionary<string, IEnumerable<Die>> diceGroups = new();
private readonly List<DiceGroup> diceGroups = new();
public Task<KeyValuePair<string, IEnumerable<Die>>> Add(KeyValuePair<string, IEnumerable<Die>> toAdd)
public Task<DiceGroup> Add(DiceGroup toAdd)
{
if (string.IsNullOrWhiteSpace(toAdd.Key))
if (string.IsNullOrWhiteSpace(toAdd.Name))
{
throw new ArgumentNullException(nameof(toAdd), "param should not be null or empty");
}
if (diceGroups.Contains(toAdd))
{
throw new ArgumentException("this username is already taken", nameof(toAdd));
throw new ArgumentException("this dice group already exists", nameof(toAdd));
}
diceGroups.Add(toAdd.Key.Trim(), toAdd.Value);
diceGroups.Add(new(toAdd.Name.Trim(), toAdd.Dice));
return Task.FromResult(toAdd);
}
public Task<IEnumerable<KeyValuePair<string, IEnumerable<Die>>>> GetAll()
public Task<ReadOnlyCollection<DiceGroup>> GetAll()
{
return Task.FromResult(diceGroups.AsEnumerable());
return Task.FromResult(new ReadOnlyCollection<DiceGroup>(diceGroups));
}
public Task<KeyValuePair<string, IEnumerable<Die>>> GetOneByID(Guid ID)
public Task<DiceGroup> GetOneByID(Guid ID)
{
throw new NotImplementedException();
}
public Task<KeyValuePair<string, IEnumerable<Die>>> GetOneByName(string name)
public Task<DiceGroup> GetOneByName(string name)
{
// les groupes de dés nommés :
// ils sont case-sensistive, mais "mon jeu" == "mon jeu " == " mon jeu"
@ -42,41 +43,41 @@ namespace Model.Dice
{
throw new ArgumentNullException(nameof(name), "param should not be null or empty");
}
return Task.FromResult(new KeyValuePair<string, IEnumerable<Die>>(name, diceGroups[name]));
return Task.FromResult(diceGroups.First(diceGroup => diceGroup.Name.Equals(name.Trim())));
}
public void Remove(KeyValuePair<string, IEnumerable<Die>> toRemove)
public void Remove(DiceGroup toRemove)
{
if (toRemove.Key is null)
if (toRemove.Name is null)
{
throw new ArgumentNullException(nameof(toRemove), "param should not be null");
}
else
{
diceGroups.Remove(toRemove.Key);
diceGroups.Remove(toRemove);
}
}
/// <summary>
/// updates a (string, IEnumerable-of-Die) couple. only the name can be updated
/// updates a (string, ReadOnlyCollection-of-Die) couple. only the name can be updated
/// </summary>
/// <param name="before">original couple</param>
/// <param name="after">new couple</param>
/// <returns></returns>
/// <exception cref="ArgumentException"></exception>
/// <exception cref="ArgumentNullException"></exception>
public Task<KeyValuePair<string, IEnumerable<Die>>> Update(KeyValuePair<string, IEnumerable<Die>> before, KeyValuePair<string, IEnumerable<Die>> after)
public Task<DiceGroup> Update(DiceGroup before, DiceGroup after)
{
// pas autorisé de changer les dés, juste le nom
if (!before.Value.Equals(after.Value))
if (!before.Dice.Equals(after.Dice))
{
throw new ArgumentException("the group of dice cannot be updated, only the name", nameof(before));
}
if (string.IsNullOrWhiteSpace(before.Key) || string.IsNullOrWhiteSpace(after.Key))
if (string.IsNullOrWhiteSpace(before.Name) || string.IsNullOrWhiteSpace(after.Name))
{
throw new ArgumentNullException(nameof(before), "dice group name should not be null or empty");
}
diceGroups.Remove(before.Key);
Remove(before);
Add(after);
return Task.FromResult(after);

@ -1,13 +1,14 @@
using Model.Dice.Faces;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
namespace Model.Dice
{
public abstract class Die
{
public IEnumerable<Face> Faces => faces;
public ReadOnlyCollection<Face> Faces => new(faces);
protected static readonly Random rnd = new();
@ -20,7 +21,7 @@ namespace Model.Dice
public virtual Face GetRandomFace()
{
int faceIndex = rnd.Next(0, Faces.Count());
int faceIndex = rnd.Next(0, Faces.Count);
return Faces.ElementAt(faceIndex);
}
}

@ -3,8 +3,8 @@ using Model.Dice.Faces;
using Model.Players;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Model.Games
@ -35,18 +35,18 @@ namespace Model.Games
/// <summary>
/// references the position in list of the current player, for a given game.
/// </summary>
private int nextIndex;
private int nextIndex = 0;
/// <summary>
/// the turns that have been done so far
/// </summary>
private readonly List<Turn> turns;
private readonly List<Turn> turns = new();
/// </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();
public ReadOnlyCollection<Turn> GetHistory() => new(turns);
/// <summary>
/// the game's player manager, doing CRUD on players and switching whose turn it is
@ -56,8 +56,8 @@ namespace Model.Games
/// <summary>
/// the group of dice used for this game
/// </summary>
public IEnumerable<Die> Dice => dice;
private readonly IEnumerable<Die> dice;
public ReadOnlyCollection<Die> Dice => new(dice);
private readonly List<Die> dice = new();
/// <summary>
/// constructs a Game with its own history of Turns.
@ -71,19 +71,19 @@ namespace Model.Games
{
Name = name;
PlayerManager = playerManager;
this.turns = turns is null ? new List<Turn>() : turns.ToList();
this.dice = dice;
this.nextIndex = 0;
this.dice.AddRange(dice);
this.turns.AddRange(turns);
}
/// <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, IManager<Player> playerManager, IEnumerable<Die> dice)
: this(name, playerManager, dice, null)
: this(name, playerManager, dice, new List<Turn>())
{ }
/// <summary>
@ -144,16 +144,8 @@ namespace Model.Games
{
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++;
}
nextIndex = (nextIndex + 1) % players.Count();
}
/// <summary>

@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Threading.Tasks;
@ -10,18 +11,14 @@ namespace Model.Games
/// <summary>
/// the games managed by this instance
/// </summary>
private readonly List<Game> games;
private readonly List<Game> games = new();
public GameManager()
{
games = new();
}
/// <summary>
/// gets an unmodifiable collection of the games
/// </summary>
/// <returns>unmodifiable collection of the games</returns>
public Task<IEnumerable<Game>> GetAll() => Task.FromResult(games.AsEnumerable());
public Task<ReadOnlyCollection<Game>> GetAll() => Task.FromResult(new ReadOnlyCollection<Game>(games));
/// <summary>
/// finds the game with that name and returns it

@ -8,10 +8,10 @@ namespace Model.Games
public class MasterOfCeremonies
{
public IManager<Player> GlobalPlayerManager { get; private set; }
public IManager<KeyValuePair<string, IEnumerable<Die>>> DiceGroupManager { get; private set; }
public IManager<DiceGroup> DiceGroupManager { get; private set; }
public IManager<Game> GameManager { get; private set; }
public MasterOfCeremonies(IManager<Player> globalPlayerManager, IManager<KeyValuePair<string, IEnumerable<Die>>> globalDiceGroupManager, IManager<Game> gameManager)
public MasterOfCeremonies(IManager<Player> globalPlayerManager, IManager<DiceGroup> globalDiceGroupManager, IManager<Game> gameManager)
{
GlobalPlayerManager = globalPlayerManager;
DiceGroupManager = globalDiceGroupManager;

@ -3,8 +3,8 @@ using Model.Dice.Faces;
using Model.Players;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Text;
namespace Model.Games
{
@ -28,7 +28,7 @@ namespace Model.Games
/// <summary>
/// the collection of Face that were rolled
/// </summary>
public IEnumerable<KeyValuePair<Die, Face>> DiceNFaces => diceNFaces.AsEnumerable();
public ReadOnlyDictionary<Die, Face> DiceNFaces => new(diceNFaces);
private readonly Dictionary<Die, Face> diceNFaces;
/// <summary>
@ -37,24 +37,7 @@ namespace Model.Games
/// <param name="when">date and time of the turn</param>
/// <param name="player">player who played the turn</param>
/// <param name="faces">faces that were rolled</param>
private Turn(DateTime when, Player player, Dictionary<Die, Face> diceNFaces)
{
When = when;
Player = player;
this.diceNFaces = diceNFaces;
}
/// <summary>
/// creates a Turn with a specified time, passed as a parameter.
/// <br/>
/// whatever the DateTimeKind of <paramref name="when"/> might be,
/// it will become UTC during construction
/// </summary>
/// <param name="when">date and time of the turn</param>
/// <param name="player">player who played the turn</param>
/// <param name="faces">faces that were rolled</param>
/// <returns>a new Turn object</returns>
public static Turn CreateWithSpecifiedTime(DateTime when, Player player, Dictionary<Die, Face> diceNFaces)
private Turn(DateTime when, Player player, IEnumerable<KeyValuePair<Die, Face>> diceNFaces)
{
if (player is null)
{
@ -64,7 +47,7 @@ namespace Model.Games
{
throw new ArgumentNullException(nameof(diceNFaces), "param should not be null");
}
if (diceNFaces.Count == 0)
if (!diceNFaces.Any())
{
throw new ArgumentException("param should not be null", nameof(diceNFaces));
}
@ -73,6 +56,23 @@ namespace Model.Games
when = when.ToUniversalTime();
}
When = when;
Player = player;
this.diceNFaces = diceNFaces.ToDictionary(kvp => kvp.Key, kvp => kvp.Value);
}
/// <summary>
/// creates a Turn with a specified time, passed as a parameter.
/// <br/>
/// whatever the DateTimeKind of <paramref name="when"/> might be,
/// it will become UTC during construction
/// </summary>
/// <param name="when">date and time of the turn</param>
/// <param name="player">player who played the turn</param>
/// <param name="faces">faces that were rolled</param>
/// <returns>a new Turn object</returns>
public static Turn CreateWithSpecifiedTime(DateTime when, Player player, IEnumerable<KeyValuePair<Die, Face>> diceNFaces)
{
return new Turn(when, player, diceNFaces);
}
@ -82,7 +82,7 @@ namespace Model.Games
/// <param name="player">player who played the turn</param>
/// <param name="faces">faces that were rolled</param>
/// <returns>a new Turn object</returns>
public static Turn CreateWithDefaultTime(Player player, Dictionary<Die, Face> diceNFaces)
public static Turn CreateWithDefaultTime(Player player, IEnumerable<KeyValuePair<Die, Face>> diceNFaces)
{
return CreateWithSpecifiedTime(DateTime.UtcNow, player, diceNFaces);
}
@ -93,15 +93,16 @@ namespace Model.Games
||
!(Player.Equals(other.Player)
&& When.Equals(other.When)
&& DiceNFaces.Count() == other.DiceNFaces.Count()))
&& DiceNFaces.Count == other.DiceNFaces.Count))
{
return false;
}
for (int i = 0; i < DiceNFaces.Count(); i++)
// 🤮
for (int i = 0; i < DiceNFaces.Count; i++)
{
if (DiceNFaces.ElementAt(i).Key.Faces.Count()
!= other.DiceNFaces.ElementAt(i).Key.Faces.Count())
if (DiceNFaces.ElementAt(i).Key.Faces.Count
!= other.DiceNFaces.ElementAt(i).Key.Faces.Count)
{
return false;
}
@ -112,7 +113,7 @@ namespace Model.Games
return false;
}
for (int j = 0; j < DiceNFaces.ElementAt(i).Key.Faces.Count(); j++)
for (int j = 0; j < DiceNFaces.ElementAt(i).Key.Faces.Count; j++)
{
if (!other.DiceNFaces.ElementAt(i).Key.Faces.ElementAt(j).StringValue
.Equals(DiceNFaces.ElementAt(i).Key.Faces.ElementAt(j).StringValue))
@ -135,16 +136,7 @@ namespace Model.Games
public override int GetHashCode()
{
int hash = Player.GetHashCode() + When.GetHashCode();
foreach (KeyValuePair<Die, Face> kvp in DiceNFaces)
{
hash = hash * 31 + kvp.Value.StringValue.GetHashCode();
foreach (Face face in kvp.Key.Faces)
{
hash = hash * 19 + face.StringValue.GetHashCode();
}
}
return hash;
return When.GetHashCode();
}
}
}

@ -1,5 +1,5 @@
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Threading.Tasks;
namespace Model
@ -12,7 +12,7 @@ namespace Model
public Task<T> GetOneByID(Guid ID);
public Task<IEnumerable<T>> GetAll();
public Task<ReadOnlyCollection<T>> GetAll();
public Task<T> Update(T before, T after);

@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Threading.Tasks;
@ -10,12 +11,8 @@ namespace Model.Players
/// <summary>
/// a collection of the players that this manager is in charge of
/// </summary>
private readonly List<Player> players;
private readonly List<Player> players = new();
public PlayerManager()
{
players = new();
}
/// <summary>
/// add a new player
/// </summary>
@ -60,7 +57,7 @@ namespace Model.Players
/// so that the only way to modify the collection of players is to use this class's methods
/// </summary>
/// <returns>a readonly enumerable of all this manager's players</returns>
public Task<IEnumerable<Player>> GetAll() => Task.FromResult(players.AsEnumerable());
public Task<ReadOnlyCollection<Player>> GetAll() => Task.FromResult(new ReadOnlyCollection<Player>(players));
/// <summary>
/// update a player from <paramref name="before"/> to <paramref name="after"/>

@ -78,7 +78,7 @@ namespace Tests.Data_UTs.Games
Turn expected = Turn.CreateWithSpecifiedTime(
datetime1,
playerEntity.ToModel(),
new()
new Dictionary<Die, Face>()
{
{(numDieEntity as NumberDieEntity).ToModel(), (numFace1Entity as NumberFaceEntity).ToModel() },
{(clrDieEntity as ColorDieEntity).ToModel(), (clrFace2Entity as ColorFaceEntity).ToModel() },
@ -138,7 +138,7 @@ namespace Tests.Data_UTs.Games
Turn.CreateWithSpecifiedTime(
datetime1,
new("Aardvark"),
new()
new Dictionary<Die, Face>()
{
{(numDieEntity as NumberDieEntity).ToModel(), (numFace2Entity as NumberFaceEntity).ToModel() },
{(clrDieEntity as ColorDieEntity).ToModel(), (clrFace2Entity as ColorFaceEntity).ToModel() },
@ -147,7 +147,7 @@ namespace Tests.Data_UTs.Games
Turn.CreateWithSpecifiedTime(
datetime2,
new("Chloe"),
new()
new Dictionary<Die, Face>()
{
{(clrDieEntity as ColorDieEntity).ToModel(), (clrFace1Entity as ColorFaceEntity).ToModel() },
{(imgDieEntity as ImageDieEntity).ToModel(), (imgFace1Entity as ImageFaceEntity).ToModel() }
@ -169,7 +169,8 @@ namespace Tests.Data_UTs.Games
Turn model = Turn.CreateWithSpecifiedTime(
datetime1,
playerEntity.ToModel(),
new()
new Dictionary<Die, Face>()
{
{(numDieEntity as NumberDieEntity).ToModel(), (numFace2Entity as NumberFaceEntity).ToModel() },
{(clrDieEntity as ColorDieEntity).ToModel(), (clrFace2Entity as ColorFaceEntity).ToModel() },
@ -211,7 +212,7 @@ namespace Tests.Data_UTs.Games
Turn.CreateWithSpecifiedTime(
datetime2,
new("Mimi"),
new()
new Dictionary<Die, Face>()
{
{(numDieEntity as NumberDieEntity).ToModel(), (numFace2Entity as NumberFaceEntity).ToModel() },
{(clrDieEntity as ColorDieEntity).ToModel(), (clrFace2Entity as ColorFaceEntity).ToModel() },
@ -220,7 +221,7 @@ namespace Tests.Data_UTs.Games
Turn.CreateWithSpecifiedTime(
datetime1,
new("blaaargh"),
new()
new Dictionary<Die, Face>()
{
{(clrDieEntity as ColorDieEntity).ToModel(), (clrFace1Entity as ColorFaceEntity).ToModel() },
{(imgDieEntity as ImageDieEntity).ToModel(), (imgFace1Entity as ImageFaceEntity).ToModel() }

@ -90,7 +90,7 @@ namespace Tests.Data_UTs.Players
db.Database.EnsureCreated();
mgr = new(db);
Assert.Equal(expectedName, (await mgr.GetOneByName(expectedName)).Name);
Assert.Equal(expectedCount, (await mgr.GetAll()).Count());
Assert.Equal(expectedCount, (await mgr.GetAll()).Count);
}
}

@ -188,9 +188,9 @@ namespace Tests.Model_UTs.Games
Game newGame = new(newName, oldGame.PlayerManager, oldGame.Dice);
// Act
int expectedSize = (await gm.GetAll()).Count();
int expectedSize = (await gm.GetAll()).Count;
await gm.Update(oldGame, newGame);
int actualSize = (await gm.GetAll()).Count();
int actualSize = (await gm.GetAll()).Count;
// Assert
Assert.NotEqual(oldName, newName);
@ -208,12 +208,12 @@ namespace Tests.Model_UTs.Games
// Arrange
IManager<Game> gm = stubGameRunner.GameManager;
int expectedSize = (await gm.GetAll()).Count();
int expectedSize = (await gm.GetAll()).Count;
Game oldGame = (await gm.GetAll()).First();
// Act
void action() => gm.Update(oldGame, new(badName, oldGame.PlayerManager, oldGame.Dice));
int actualSize = (await gm.GetAll()).Count();
int actualSize = (await gm.GetAll()).Count;
// Assert
Assert.Throws<ArgumentException>(action); // thrown by constructor
@ -226,12 +226,12 @@ namespace Tests.Model_UTs.Games
{
// Arrange
IManager<Game> gm = stubGameRunner.GameManager;
int expectedSize = (await gm.GetAll()).Count();
int expectedSize = (await gm.GetAll()).Count;
Game oldGame = (await gm.GetAll()).First();
// Act
async Task actionAsync() => await gm.Update(oldGame, null);
int actualSize = (await gm.GetAll()).Count();
int actualSize = (await gm.GetAll()).Count;
// Assert
await Assert.ThrowsAsync<ArgumentNullException>(actionAsync); // thrown by constructor
@ -244,12 +244,12 @@ namespace Tests.Model_UTs.Games
{
// Arrange
IManager<Game> gm = stubGameRunner.GameManager;
int expectedSize = (await gm.GetAll()).Count();
int expectedSize = (await gm.GetAll()).Count;
Game oldGame = (await gm.GetAll()).First();
// Act
async Task actionAsync() => await gm.Update(null, new("newgamename", oldGame.PlayerManager, oldGame.Dice));
int actualSize = (await gm.GetAll()).Count();
int actualSize = (await gm.GetAll()).Count;
// Assert
await Assert.ThrowsAsync<ArgumentNullException>(actionAsync); // thrown by constructor
@ -265,12 +265,12 @@ namespace Tests.Model_UTs.Games
{
// Arrange
IManager<Game> gm = stubGameRunner.GameManager;
int expectedSize = (await gm.GetAll()).Count();
int expectedSize = (await gm.GetAll()).Count;
Game oldGame = (await gm.GetAll()).First();
// Act
void action() => gm.Update(new(badName, oldGame.PlayerManager, oldGame.Dice), new("valid", oldGame.PlayerManager, oldGame.Dice));
int actualSize = (await gm.GetAll()).Count();
int actualSize = (await gm.GetAll()).Count;
// Assert
Assert.Throws<ArgumentException>(action); // thrown by constructor

@ -5,7 +5,6 @@ using Model.Games;
using Model.Players;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Threading.Tasks;
using Xunit;
@ -21,9 +20,9 @@ namespace Tests.Model_UTs.Games
private readonly IEnumerable<Die> DICE_1, DICE_2;
public GameTest()
{
IEnumerable<KeyValuePair<string, IEnumerable<Die>>> diceGroups = stubMasterOfCeremonies.DiceGroupManager.GetAll()?.Result;
DICE_1 = diceGroups.First().Value;
DICE_2 = diceGroups.Last().Value;
IEnumerable<DiceGroup> diceGroups = stubMasterOfCeremonies.DiceGroupManager.GetAll()?.Result;
DICE_1 = diceGroups.First().Dice;
DICE_2 = diceGroups.Last().Dice;
}
[Fact]
@ -81,8 +80,8 @@ namespace Tests.Model_UTs.Games
public async Task TestGetHistory()
{
// Arrange
Dictionary<Die, Face> diceNFaces =
(Dictionary<Die, Face>)(await stubMasterOfCeremonies.GameManager.GetAll())
IEnumerable<KeyValuePair<Die, Face>> diceNFaces =
(await stubMasterOfCeremonies.GameManager.GetAll())
.First()
.GetHistory()
.First().DiceNFaces;
@ -143,7 +142,7 @@ namespace Tests.Model_UTs.Games
}
// Act
int actual = game.GetHistory().Count();
int actual = game.GetHistory().Count;
int expected = n;
// Assert

@ -22,9 +22,9 @@ namespace Tests.Model_UTs.Games
Game game = (await masterOfCeremonies.GameManager.GetAll()).First();
// Act
int turnsBefore = game.GetHistory().Count();
int turnsBefore = game.GetHistory().Count;
await MasterOfCeremonies.PlayGame(game);
int turnsAfter = game.GetHistory().Count();
int turnsAfter = game.GetHistory().Count;
// Assert
Assert.Equal(turnsBefore + 1, turnsAfter);

@ -5,6 +5,7 @@ using Model.Games;
using Model.Players;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using Xunit;
@ -14,14 +15,14 @@ namespace Tests.Model_UTs.Games
{
private readonly MasterOfCeremonies stubMasterOfCeremonies = new Stub().LoadApp()?.Result;
Dictionary<Die, Face> DICE_N_FACES_1, DICE_N_FACES_2;
private readonly ReadOnlyDictionary<Die, Face> DICE_N_FACES_1;
private readonly ReadOnlyDictionary<Die, Face> DICE_N_FACES_2;
public TurnTest()
{
DICE_N_FACES_1 = (Dictionary<Die, Face>)stubMasterOfCeremonies.GameManager.GetAll()?.Result.First().GetHistory().First().DiceNFaces;
DICE_N_FACES_2 = (Dictionary<Die, Face>)stubMasterOfCeremonies.GameManager.GetAll()?.Result.Last().GetHistory().Last().DiceNFaces;
DICE_N_FACES_1 = stubMasterOfCeremonies.GameManager.GetAll()?.Result.First().GetHistory().First().DiceNFaces;
DICE_N_FACES_2 = stubMasterOfCeremonies.GameManager.GetAll()?.Result.Last().GetHistory().Last().DiceNFaces;
}
[Fact]
@ -93,10 +94,9 @@ namespace Tests.Model_UTs.Games
// Arrange
DateTime dateTime = new(year: 2018, month: 06, day: 15, hour: 16, minute: 30, second: 0, kind: DateTimeKind.Utc);
Player player = new("Chucky");
DICE_N_FACES_1.Clear();
// Act
void action() => Turn.CreateWithSpecifiedTime(dateTime, player, DICE_N_FACES_1);
void action() => Turn.CreateWithSpecifiedTime(dateTime, player, new Dictionary<Die, Face>());
// Assert
Assert.Throws<ArgumentException>(action);

@ -204,7 +204,7 @@ namespace Tests.Model_UTs.Players
// Assert
Assert.DoesNotContain(oldPlayer, await playerManager.GetAll());
Assert.Contains(newPlayer, await playerManager.GetAll());
Assert.True((await playerManager.GetAll()).Count() == 1);
Assert.True((await playerManager.GetAll()).Count == 1);
}
[Theory]
@ -239,12 +239,12 @@ namespace Tests.Model_UTs.Players
PlayerManager playerManager = new();
Player oldPlayer = new("Ni!");
await playerManager.Add(oldPlayer);
int size1 = (await playerManager.GetAll()).Count();
int size1 = (await playerManager.GetAll()).Count;
// Act
Assert.Contains(oldPlayer, await playerManager.GetAll());
async Task actionAsync() => await playerManager.Update(oldPlayer, new Player(badName));// this is really testing the Player class...
int size2 = (await playerManager.GetAll()).Count();
int size2 = (await playerManager.GetAll()).Count;
// Assert
await Assert.ThrowsAsync<ArgumentException>(actionAsync); // thrown by Player constructor
@ -259,12 +259,12 @@ namespace Tests.Model_UTs.Players
PlayerManager playerManager = new();
Player oldPlayer = new("Ni!");
await playerManager.Add(oldPlayer);
int size1 = (await playerManager.GetAll()).Count();
int size1 = (await playerManager.GetAll()).Count;
// Act
Assert.Contains(oldPlayer, await playerManager.GetAll());
async Task actionAsync() => await playerManager.Update(oldPlayer, null);
int size2 = (await playerManager.GetAll()).Count();
int size2 = (await playerManager.GetAll()).Count;
// Assert
await Assert.ThrowsAsync<ArgumentNullException>(actionAsync); // thrown by Update()
@ -280,11 +280,11 @@ namespace Tests.Model_UTs.Players
Player newPlayer = new("Kevin");
Player oldPlayer = new("Ursula");
await playerManager.Add(oldPlayer);
int size1 = (await playerManager.GetAll()).Count();
int size1 = (await playerManager.GetAll()).Count;
// Act
async Task actionAsync() => await playerManager.Update(null, newPlayer);
int size2 = (await playerManager.GetAll()).Count();
int size2 = (await playerManager.GetAll()).Count;
// Assert
await Assert.ThrowsAsync<ArgumentNullException>(actionAsync); // thrown by Update()
@ -302,11 +302,11 @@ namespace Tests.Model_UTs.Players
PlayerManager playerManager = new();
Player oldPlayer = new("Ursula");
await playerManager.Add(oldPlayer);
int size1 = (await playerManager.GetAll()).Count();
int size1 = (await playerManager.GetAll()).Count;
// Act
async Task actionAsync() => await playerManager.Update(new Player(name), new Player("Vicky"));
int size2 = (await playerManager.GetAll()).Count();
int size2 = (await playerManager.GetAll()).Count;
// Assert
await Assert.ThrowsAsync<ArgumentException>(actionAsync); // thrown by Player constructor

@ -71,5 +71,51 @@ namespace Tests.Utils_UTs
Assert.Equal(expected, actual);
}
public static IEnumerable<object[]> EmptyList()
{
yield return new object[] { new List<string>() };
}
[Theory]
[InlineData(null)]
[MemberData(nameof(EmptyList))]
public void TestGetDictFromListsWhenKeysNullOrEmptyThenNew(List<string> strings)
{
// Arrange
int int1 = 5;
int int2 = 12;
Dictionary<string, int> expected = new();
List<int> ints = new() { int1, int2 };
// Act
Dictionary<string, int> actual = Enumerables.GetDictFromLists(strings, ints);
// Assert
Assert.Equal(expected, actual);
}
[Theory]
[InlineData(null)]
[MemberData(nameof(EmptyList))]
public void TestGetDictFromListsWhenValuesNullOrEmptyThenNew(List<string> stringsB)
{
// Arrange
string str1 = "blah";
string str2 = "blahblah";
Dictionary<string, string> expected = new();
List<string> strings = new() { str1, str2 };
// Act
Dictionary<string, string> actual = Enumerables.GetDictFromLists(strings, stringsB);
// Assert
Assert.Equal(expected, actual);
}
}
}

@ -5,15 +5,23 @@
public static Dictionary<K, V> GetDictFromLists<K, V>(List<K> keys, List<V> values)
{
return keys.Zip(values, (k, v) => new { k, v })
.ToDictionary(x => x.k, x => x.v);
if (keys == null || values == null || keys.Count == 0 || values.Count == 0)
{
return new Dictionary<K, V>();
}
return keys.Zip(
values,
(key, value) => new { key, value })
.ToDictionary(kvp => kvp.key, kvp => kvp.value
);
}
public static Dictionary<K, V> FeedListsToDict<K, V>(Dictionary<K, V> kvps, List<K> keys, List<V> values)
{
foreach (var kv in GetDictFromLists(keys, values))
foreach (KeyValuePair<K, V> kvp in GetDictFromLists(keys, values))
{
kvps.Add(kv.Key, kv.Value);
kvps.Add(kvp.Key, kvp.Value);
}
return kvps;
}

Loading…
Cancel
Save