🚨 Encapsulate collections... #199

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

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

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

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

@ -10,13 +10,13 @@ namespace Data
{ {
public async Task<MasterOfCeremonies> LoadApp() 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)"); Player player1 = new("Alice(Old Stub)"), player2 = new("Bob(Old Stub)"), player3 = new("Clyde(Old Stub)");
await gr.GlobalPlayerManager.Add(player1); await mc.GlobalPlayerManager.Add(player1);
await gr.GlobalPlayerManager.Add(player2); await mc.GlobalPlayerManager.Add(player2);
await gr.GlobalPlayerManager.Add(player3); await mc.GlobalPlayerManager.Add(player3);
List<Die> monopolyDice = new(); List<Die> monopolyDice = new();
@ -63,26 +63,26 @@ namespace Data
dndDice.Add(new NumberDie(d20Faces[0], d20Faces[1..])); dndDice.Add(new NumberDie(d20Faces[0], d20Faces[1..]));
await gr.DiceGroupManager.Add(new KeyValuePair<string, IEnumerable<Die>>(dndName, dndDice.AsEnumerable())); await mc.DiceGroupManager.Add(new DiceGroup(dndName, dndDice));
await gr.DiceGroupManager.Add(new KeyValuePair<string, IEnumerable<Die>>(monopolyName, monopolyDice.AsEnumerable())); await mc.DiceGroupManager.Add(new DiceGroup(monopolyName, monopolyDice));
string game1 = "Forgotten Realms", game2 = "4e", game3 = "The Coopers"; string game1 = "Forgotten Realms", game2 = "4e", game3 = "The Coopers";
await gr.GameManager.Add(new(game1, new PlayerManager(), dndDice.AsEnumerable())); await mc.GameManager.Add(new(game1, new PlayerManager(), dndDice.AsEnumerable()));
await gr.GameManager.Add(new(game2, new PlayerManager(), dndDice.AsEnumerable())); await mc.GameManager.Add(new(game2, new PlayerManager(), dndDice.AsEnumerable()));
await gr.GameManager.Add(new(game3, new PlayerManager(), monopolyDice.AsEnumerable())); await mc.GameManager.Add(new(game3, new PlayerManager(), monopolyDice.AsEnumerable()));
await (await gr.GameManager.GetOneByName(game1)).PlayerManager.Add(player1); await (await mc.GameManager.GetOneByName(game1)).PlayerManager.Add(player1);
await (await gr.GameManager.GetOneByName(game1)).PlayerManager.Add(player2); await (await mc.GameManager.GetOneByName(game1)).PlayerManager.Add(player2);
await (await gr.GameManager.GetOneByName(game2)).PlayerManager.Add(player1); await (await mc.GameManager.GetOneByName(game2)).PlayerManager.Add(player1);
await (await gr.GameManager.GetOneByName(game2)).PlayerManager.Add(player2); await (await mc.GameManager.GetOneByName(game2)).PlayerManager.Add(player2);
await (await gr.GameManager.GetOneByName(game2)).PlayerManager.Add(player3); await (await mc.GameManager.GetOneByName(game2)).PlayerManager.Add(player3);
await (await gr.GameManager.GetOneByName(game3)).PlayerManager.Add(player1); await (await mc.GameManager.GetOneByName(game3)).PlayerManager.Add(player1);
await (await gr.GameManager.GetOneByName(game3)).PlayerManager.Add(player3); 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++) 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;
using System.Collections.Generic; using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq; using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
namespace Model.Dice 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"); throw new ArgumentNullException(nameof(toAdd), "param should not be null or empty");
} }
if (diceGroups.Contains(toAdd)) 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); 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(); 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 : // les groupes de dés nommés :
// ils sont case-sensistive, mais "mon jeu" == "mon jeu " == " mon jeu" // 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"); 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"); throw new ArgumentNullException(nameof(toRemove), "param should not be null");
} }
else else
{ {
diceGroups.Remove(toRemove.Key); diceGroups.Remove(toRemove);
} }
} }
/// <summary> /// <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> /// </summary>
/// <param name="before">original couple</param> /// <param name="before">original couple</param>
/// <param name="after">new couple</param> /// <param name="after">new couple</param>
/// <returns></returns> /// <returns></returns>
/// <exception cref="ArgumentException"></exception> /// <exception cref="ArgumentException"></exception>
/// <exception cref="ArgumentNullException"></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 // 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)); 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"); throw new ArgumentNullException(nameof(before), "dice group name should not be null or empty");
} }
diceGroups.Remove(before.Key); Remove(before);
Add(after); Add(after);
return Task.FromResult(after); return Task.FromResult(after);

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

@ -3,8 +3,8 @@ using Model.Dice.Faces;
using Model.Players; using Model.Players;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq; using System.Linq;
using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
namespace Model.Games namespace Model.Games
@ -35,18 +35,18 @@ namespace Model.Games
/// <summary> /// <summary>
/// references the position in list of the current player, for a given game. /// references the position in list of the current player, for a given game.
/// </summary> /// </summary>
private int nextIndex; private int nextIndex = 0;
/// <summary> /// <summary>
/// the turns that have been done so far /// the turns that have been done so far
/// </summary> /// </summary>
private readonly List<Turn> turns; private readonly List<Turn> turns = new();
/// </summary> /// </summary>
/// get a READ ONLY enumerable of all turns belonging to this game /// get a READ ONLY enumerable of all turns belonging to this game
/// </summary> /// </summary>
/// <returns>a readonly enumerable of all this game's turns</returns> /// <returns>a readonly enumerable of all this game's turns</returns>
public IEnumerable<Turn> GetHistory() => turns.AsEnumerable(); public ReadOnlyCollection<Turn> GetHistory() => new(turns);
/// <summary> /// <summary>
/// the game's player manager, doing CRUD on players and switching whose turn it is /// the game's player manager, doing CRUD on players and switching whose turn it is
@ -56,8 +56,8 @@ namespace Model.Games
/// <summary> /// <summary>
/// the group of dice used for this game /// the group of dice used for this game
/// </summary> /// </summary>
public IEnumerable<Die> Dice => dice; public ReadOnlyCollection<Die> Dice => new(dice);
private readonly IEnumerable<Die> dice; private readonly List<Die> dice = new();
/// <summary> /// <summary>
/// constructs a Game with its own history of Turns. /// constructs a Game with its own history of Turns.
@ -71,19 +71,19 @@ namespace Model.Games
{ {
Name = name; Name = name;
PlayerManager = playerManager; PlayerManager = playerManager;
this.turns = turns is null ? new List<Turn>() : turns.ToList(); this.dice.AddRange(dice);
this.dice = dice; this.turns.AddRange(turns);
this.nextIndex = 0;
} }
/// <summary> /// <summary>
/// constructs a Game with no history of turns. /// constructs a Game with no history of turns.
///
/// </summary> /// </summary>
/// <param name="name">the name of the game 😎</param> /// <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="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> /// <param name="favGroup">the group of dice used for this game</param>
public Game(string name, IManager<Player> playerManager, IEnumerable<Die> dice) public Game(string name, IManager<Player> playerManager, IEnumerable<Die> dice)
: this(name, playerManager, dice, null) : this(name, playerManager, dice, new List<Turn>())
{ } { }
/// <summary> /// <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)); throw new ArgumentException("param could not be found in this collection\n did you forget to add it?", nameof(current));
} }
if (players.Last() == current)
{ nextIndex = (nextIndex + 1) % players.Count();
// 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++;
}
} }
/// <summary> /// <summary>

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

@ -8,10 +8,10 @@ namespace Model.Games
public class MasterOfCeremonies public class MasterOfCeremonies
{ {
public IManager<Player> GlobalPlayerManager { get; private set; } 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 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; GlobalPlayerManager = globalPlayerManager;
DiceGroupManager = globalDiceGroupManager; DiceGroupManager = globalDiceGroupManager;

@ -3,8 +3,8 @@ using Model.Dice.Faces;
using Model.Players; using Model.Players;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq; using System.Linq;
using System.Text;
namespace Model.Games namespace Model.Games
{ {
@ -28,7 +28,7 @@ namespace Model.Games
/// <summary> /// <summary>
/// the collection of Face that were rolled /// the collection of Face that were rolled
/// </summary> /// </summary>
public IEnumerable<KeyValuePair<Die, Face>> DiceNFaces => diceNFaces.AsEnumerable(); public ReadOnlyDictionary<Die, Face> DiceNFaces => new(diceNFaces);
private readonly Dictionary<Die, Face> diceNFaces; private readonly Dictionary<Die, Face> diceNFaces;
/// <summary> /// <summary>
@ -37,24 +37,7 @@ namespace Model.Games
/// <param name="when">date and time of the turn</param> /// <param name="when">date and time of the turn</param>
/// <param name="player">player who played the turn</param> /// <param name="player">player who played the turn</param>
/// <param name="faces">faces that were rolled</param> /// <param name="faces">faces that were rolled</param>
private Turn(DateTime when, Player player, Dictionary<Die, Face> diceNFaces) private Turn(DateTime when, Player player, IEnumerable<KeyValuePair<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)
{ {
if (player is null) if (player is null)
{ {
@ -64,7 +47,7 @@ namespace Model.Games
{ {
throw new ArgumentNullException(nameof(diceNFaces), "param should not be null"); 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)); throw new ArgumentException("param should not be null", nameof(diceNFaces));
} }
@ -73,6 +56,23 @@ namespace Model.Games
when = when.ToUniversalTime(); 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); return new Turn(when, player, diceNFaces);
} }
@ -82,7 +82,7 @@ namespace Model.Games
/// <param name="player">player who played the turn</param> /// <param name="player">player who played the turn</param>
/// <param name="faces">faces that were rolled</param> /// <param name="faces">faces that were rolled</param>
/// <returns>a new Turn object</returns> /// <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); return CreateWithSpecifiedTime(DateTime.UtcNow, player, diceNFaces);
} }
@ -93,15 +93,16 @@ namespace Model.Games
|| ||
!(Player.Equals(other.Player) !(Player.Equals(other.Player)
&& When.Equals(other.When) && When.Equals(other.When)
&& DiceNFaces.Count() == other.DiceNFaces.Count())) && DiceNFaces.Count == other.DiceNFaces.Count))
{ {
return false; 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() if (DiceNFaces.ElementAt(i).Key.Faces.Count
!= other.DiceNFaces.ElementAt(i).Key.Faces.Count()) != other.DiceNFaces.ElementAt(i).Key.Faces.Count)
{ {
return false; return false;
} }
@ -112,7 +113,7 @@ namespace Model.Games
return false; 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 if (!other.DiceNFaces.ElementAt(i).Key.Faces.ElementAt(j).StringValue
.Equals(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() public override int GetHashCode()
{ {
int hash = Player.GetHashCode() + When.GetHashCode(); return 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;
} }
} }
} }

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

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

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

@ -90,7 +90,7 @@ namespace Tests.Data_UTs.Players
db.Database.EnsureCreated(); db.Database.EnsureCreated();
mgr = new(db); mgr = new(db);
Assert.Equal(expectedName, (await mgr.GetOneByName(expectedName)).Name); 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); Game newGame = new(newName, oldGame.PlayerManager, oldGame.Dice);
// Act // Act
int expectedSize = (await gm.GetAll()).Count(); int expectedSize = (await gm.GetAll()).Count;
await gm.Update(oldGame, newGame); await gm.Update(oldGame, newGame);
int actualSize = (await gm.GetAll()).Count(); int actualSize = (await gm.GetAll()).Count;
// Assert // Assert
Assert.NotEqual(oldName, newName); Assert.NotEqual(oldName, newName);
@ -208,12 +208,12 @@ namespace Tests.Model_UTs.Games
// Arrange // Arrange
IManager<Game> gm = stubGameRunner.GameManager; IManager<Game> gm = stubGameRunner.GameManager;
int expectedSize = (await gm.GetAll()).Count(); int expectedSize = (await gm.GetAll()).Count;
Game oldGame = (await gm.GetAll()).First(); Game oldGame = (await gm.GetAll()).First();
// Act // Act
void action() => gm.Update(oldGame, new(badName, oldGame.PlayerManager, oldGame.Dice)); 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
Assert.Throws<ArgumentException>(action); // thrown by constructor Assert.Throws<ArgumentException>(action); // thrown by constructor
@ -226,12 +226,12 @@ namespace Tests.Model_UTs.Games
{ {
// Arrange // Arrange
IManager<Game> gm = stubGameRunner.GameManager; IManager<Game> gm = stubGameRunner.GameManager;
int expectedSize = (await gm.GetAll()).Count(); int expectedSize = (await gm.GetAll()).Count;
Game oldGame = (await gm.GetAll()).First(); Game oldGame = (await gm.GetAll()).First();
// Act // Act
async Task actionAsync() => await gm.Update(oldGame, null); async Task actionAsync() => await gm.Update(oldGame, null);
int actualSize = (await gm.GetAll()).Count(); int actualSize = (await gm.GetAll()).Count;
// Assert // Assert
await Assert.ThrowsAsync<ArgumentNullException>(actionAsync); // thrown by constructor await Assert.ThrowsAsync<ArgumentNullException>(actionAsync); // thrown by constructor
@ -244,12 +244,12 @@ namespace Tests.Model_UTs.Games
{ {
// Arrange // Arrange
IManager<Game> gm = stubGameRunner.GameManager; IManager<Game> gm = stubGameRunner.GameManager;
int expectedSize = (await gm.GetAll()).Count(); int expectedSize = (await gm.GetAll()).Count;
Game oldGame = (await gm.GetAll()).First(); Game oldGame = (await gm.GetAll()).First();
// Act // Act
async Task actionAsync() => await gm.Update(null, new("newgamename", oldGame.PlayerManager, oldGame.Dice)); 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 // Assert
await Assert.ThrowsAsync<ArgumentNullException>(actionAsync); // thrown by constructor await Assert.ThrowsAsync<ArgumentNullException>(actionAsync); // thrown by constructor
@ -265,12 +265,12 @@ namespace Tests.Model_UTs.Games
{ {
// Arrange // Arrange
IManager<Game> gm = stubGameRunner.GameManager; IManager<Game> gm = stubGameRunner.GameManager;
int expectedSize = (await gm.GetAll()).Count(); int expectedSize = (await gm.GetAll()).Count;
Game oldGame = (await gm.GetAll()).First(); Game oldGame = (await gm.GetAll()).First();
// Act // Act
void action() => gm.Update(new(badName, oldGame.PlayerManager, oldGame.Dice), new("valid", oldGame.PlayerManager, oldGame.Dice)); 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
Assert.Throws<ArgumentException>(action); // thrown by constructor Assert.Throws<ArgumentException>(action); // thrown by constructor

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

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

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

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

@ -71,5 +71,51 @@ namespace Tests.Utils_UTs
Assert.Equal(expected, actual); 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) public static Dictionary<K, V> GetDictFromLists<K, V>(List<K> keys, List<V> values)
{ {
return keys.Zip(values, (k, v) => new { k, v }) if (keys == null || values == null || keys.Count == 0 || values.Count == 0)
.ToDictionary(x => x.k, x => x.v); {
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) 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; return kvps;
} }

Loading…
Cancel
Save