diff --git a/BackendTests/Services/ActionServiceTests.cs b/BackendTests/Services/ActionServiceTests.cs index 6533bdb..ae3b42e 100644 --- a/BackendTests/Services/ActionServiceTests.cs +++ b/BackendTests/Services/ActionServiceTests.cs @@ -51,7 +51,9 @@ public class ActionServiceTests new(new[] { new DirectionalPosition { At = new Position { X = 3, Y = 3 }, Direction = Direction.Up }, - new() { At = new Position { X = 7, Y = 7 }, Direction = Direction.Down } + new() { At = new Position { X = 7, Y = 7 }, Direction = Direction.Down }, + new() { At = new Position { X = 5, Y = 5 }, Direction = Direction.Left }, + new() { At = new Position { X = 9, Y = 9 }, Direction = Direction.Right } }); #region RollDice() @@ -75,7 +77,7 @@ public class ActionServiceTests public void PlayerInfo_DataIsNull() { var message = new ActionMessage { Action = GameAction.PlayerInfo, Data = "null" }; - Assert.Throws(() => _service.SetPlayerInfo(message)); + Assert.Throws(() => _service.SetPlayerInfo(message)); message.Data = null; Assert.Throws(() => _service.SetPlayerInfo(message)); } @@ -142,14 +144,18 @@ public class ActionServiceTests _service.SetPlayerInfo(_blackMessage); var result = _service.Ready(); - - Assert.That(result.GetType().GetProperty("Starter"), Is.Null); + if (result is ReadyData r1) + Assert.That(r1.AllReady, Is.False); + else + Assert.Fail("Result should be ReadyData"); _service.SetPlayerInfo(_redMessage); result = _service.Ready(); - - Assert.That(result.GetType().GetProperty("Starter"), Is.Null); + if (result is ReadyData r2) + Assert.That(r2.AllReady, Is.False); + else + Assert.Fail("Result should be ReadyData"); } [Test] @@ -159,7 +165,8 @@ public class ActionServiceTests var result = _service.Ready(); // If selected the state is changed to InGame _whitePlayer.State = State.InGame; - Assert.That(result.GetType().GetProperty("Starter")?.GetValue(result), Is.EqualTo(_whitePlayer.Name)); + var players = result.GetType().GetProperty("Players")?.GetValue(result) as IEnumerable; + Assert.That(players?.First().Name, Is.EqualTo(_whitePlayer.Name)); } [Test] @@ -171,14 +178,14 @@ public class ActionServiceTests var result = _service.Ready(); - Assert.That(result.GetType().GetProperty("Starter"), Is.Null); + Assert.That(result.GetType().GetProperty("AllReady")?.GetValue(result), Is.EqualTo(false)); _service.Player = _whitePlayer; result = _service.Ready(); - Assert.That(result.GetType().GetProperty("Starter")?.GetValue(result), - Is.EqualTo(_whitePlayer.Name).Or.EqualTo(_blackPlayer.Name)); + var players = result.GetType().GetProperty("Players")?.GetValue(result) as IEnumerable; + Assert.That(players?.First().Name, Is.EqualTo(_blackPlayer.Name).Or.EqualTo(_whitePlayer.Name)); } #endregion @@ -186,15 +193,38 @@ public class ActionServiceTests #region FindNextPlayer() [Test] - public void FindNexPlayer_OnePlayer() + public void FindNextPlayer_NoPlayers() { - Assert.Fail(); + _service.Group = new GameGroup(new Queue()); + Assert.Throws(() => _service.FindNextPlayer()); } - + [Test] - public void FindNexPlayer_TwoPlayers() + public void FindNextPlayer_OnePlayer() { - Assert.Fail(); + _service.Group = + new GameGroup(new Queue( + new[] { new DirectionalPosition { At = new Position { X = 3, Y = 3 }, Direction = Direction.Up } })) + { Players = { _whitePlayer } }; + + var name = _service.FindNextPlayer(); + Assert.That(name, Is.EqualTo(_whitePlayer.Name)); + } + + [Test] + public void FindNextPlayer_TwoPlayers() + { + _service.Group = new GameGroup(new Queue( + new[] + { + new DirectionalPosition { At = new Position { X = 3, Y = 3 }, Direction = Direction.Up }, + new DirectionalPosition { At = new Position { X = 7, Y = 7 }, Direction = Direction.Down } + })) { Players = { _whitePlayer, _blackPlayer } }; + + var first = _service.FindNextPlayer(); + Assert.That(first, Is.EqualTo(_blackPlayer.Name)); + var second = _service.FindNextPlayer(); + Assert.That(second, Is.EqualTo(_whitePlayer.Name)); } #endregion diff --git a/BackendTests/Services/GameGroupTests.cs b/BackendTests/Services/GameGroupTests.cs index ca2e425..cd4ddc3 100644 --- a/BackendTests/Services/GameGroupTests.cs +++ b/BackendTests/Services/GameGroupTests.cs @@ -52,6 +52,16 @@ public class GameGroupTests _gameGroup.AddPlayer(_greenPlayer); } + #region NextPlayer() + + [Test] + public void NextPlayer_WhenEmpty() + { + Assert.Throws(() => _gameGroup.NextPlayer()); + } + + #endregion + #region AddPlayer(IPlayer player) [Test] @@ -95,6 +105,19 @@ public class GameGroupTests Assert.That(_redPlayer.PacMan.SpawnPosition, Is.EqualTo(_spawn3By3Up)); } + [Test] + public void AddPlayer_WhenGameHasStarted() + { + _gameGroup.AddPlayer(_redPlayer); + _gameGroup.AddPlayer(_bluePlayer); + + _gameGroup.SetReady(_redPlayer); + _gameGroup.SetReady(_bluePlayer); + _gameGroup.SetAllInGame(); + + Assert.That(_gameGroup.AddPlayer(_greenPlayer), Is.False); + } + #endregion #region Sendtoall(ArraySegment segment) @@ -205,7 +228,7 @@ public class GameGroupTests AddFullParty(); Assert.That(_gameGroup.IsGameStarted, Is.False); } - + [Test] public void IsGameStarted_AllInGame() { diff --git a/pac-man-board-game/Services/ActionService.cs b/pac-man-board-game/Services/ActionService.cs index 5fb6c31..92af00a 100644 --- a/pac-man-board-game/Services/ActionService.cs +++ b/pac-man-board-game/Services/ActionService.cs @@ -14,6 +14,7 @@ public interface IActionService List RollDice(); List SetPlayerInfo(ActionMessage message); object Ready(); + string FindNextPlayer(); } public class ActionService : IActionService @@ -84,7 +85,7 @@ public class ActionService : IActionService Group.Shuffle(); var allReady = players.All(p => p.State == State.Ready); if (allReady) Group.SetAllInGame(); - data = new { AllReady = allReady, Players = players }; + data = new ReadyData { AllReady = allReady, Players = players }; } else { @@ -94,11 +95,17 @@ public class ActionService : IActionService return data; } - public string FindNextPlayer() => Group?.NextPlayer.Name ?? "Error: No group found"; + public string FindNextPlayer() => Group?.NextPlayer().Name ?? "Error: No group found"; } -public class PlayerInfoData +public struct PlayerInfoData { public required Player Player { get; set; } public required Queue Spawns { get; set; } } + +public struct ReadyData +{ + public required bool AllReady { get; set; } + public required IEnumerable Players { get; set; } +} diff --git a/pac-man-board-game/Services/GameGroup.cs b/pac-man-board-game/Services/GameGroup.cs index 611f1a3..db8193d 100644 --- a/pac-man-board-game/Services/GameGroup.cs +++ b/pac-man-board-game/Services/GameGroup.cs @@ -17,21 +17,25 @@ public class GameGroup : IEnumerable // TODO handle disconnects and rec public int Count => Players.Count; - public IPlayer NextPlayer - { - get - { - _currentPlayerIndex = (_currentPlayerIndex + 1) % Count; - return Players[_currentPlayerIndex]; - } - } - public bool IsGameStarted => Count > 0 && Players.All(player => player.State is State.InGame or State.Disconnected); public IEnumerator GetEnumerator() => Players.GetEnumerator(); IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); + public IPlayer NextPlayer() + { + try + { + _currentPlayerIndex = (_currentPlayerIndex + 1) % Count; + } + catch (DivideByZeroException) + { + throw new InvalidOperationException("There are no players in the game group."); + } + return Players[_currentPlayerIndex]; + } + public void Shuffle() => Players.Sort((_, _) => _random.Next(-1, 2)); public event Func, Task>? Connections;