From c7bc473572a610837a3a530c530f76579f761289 Mon Sep 17 00:00:00 2001 From: Martin Berg Alstad <600878@stud.hvl.no> Date: Tue, 18 Jul 2023 17:09:27 +0200 Subject: [PATCH] Split up methods in controllers, added tests for GameService, refactored GameGroup name to Game and directory Game to GameStuff --- .../Controllers/GameControllerTests.cs | 2 +- BackendTests/Game/Items/DiceCupTests.cs | 4 +- BackendTests/Game/Items/DiceTests.cs | 2 +- BackendTests/Services/ActionServiceTests.cs | 13 +-- BackendTests/Services/GameServiceTests.cs | 100 ++++++++++++++++++ .../{GameGroupTests.cs => GameTests.cs} | 91 ++++++++-------- .../Services/WebSocketServiceTests.cs | 60 +---------- BackendTests/TestUtils/Players.cs | 4 +- .../ClientApp/src/pages/lobby.tsx | 2 +- .../ClientApp/src/types/types.d.ts | 2 +- .../Controllers/GameController.cs | 28 ++++- .../Controllers/GenericController.cs | 36 +++---- .../Exceptions/GameNotFoundException.cs | 6 ++ .../{Game => GameStuff}/Actions.cs | 2 +- .../{Game => GameStuff}/Character.cs | 2 +- .../{Game => GameStuff}/Items/Box.cs | 2 +- .../{Game => GameStuff}/Items/Dice.cs | 2 +- .../{Game => GameStuff}/Items/DiceCup.cs | 2 +- .../{Game => GameStuff}/Items/Pellet.cs | 2 +- .../{Game => GameStuff}/Items/Player.cs | 2 +- .../{Game => GameStuff}/Positions.cs | 2 +- .../{Game => GameStuff}/Rules.cs | 4 +- pac-man-board-game/Services/ActionService.cs | 8 +- .../Services/{GameGroup.cs => Game.cs} | 8 +- pac-man-board-game/Services/GameService.cs | 21 +++- 25 files changed, 243 insertions(+), 164 deletions(-) create mode 100644 BackendTests/Services/GameServiceTests.cs rename BackendTests/Services/{GameGroupTests.cs => GameTests.cs} (64%) create mode 100644 pac-man-board-game/Exceptions/GameNotFoundException.cs rename pac-man-board-game/{Game => GameStuff}/Actions.cs (93%) rename pac-man-board-game/{Game => GameStuff}/Character.cs (97%) rename pac-man-board-game/{Game => GameStuff}/Items/Box.cs (97%) rename pac-man-board-game/{Game => GameStuff}/Items/Dice.cs (83%) rename pac-man-board-game/{Game => GameStuff}/Items/DiceCup.cs (90%) rename pac-man-board-game/{Game => GameStuff}/Items/Pellet.cs (95%) rename pac-man-board-game/{Game => GameStuff}/Items/Player.cs (97%) rename pac-man-board-game/{Game => GameStuff}/Positions.cs (98%) rename pac-man-board-game/{Game => GameStuff}/Rules.cs (84%) rename pac-man-board-game/Services/{GameGroup.cs => Game.cs} (92%) diff --git a/BackendTests/Controllers/GameControllerTests.cs b/BackendTests/Controllers/GameControllerTests.cs index 28ff4c2..64b75e0 100644 --- a/BackendTests/Controllers/GameControllerTests.cs +++ b/BackendTests/Controllers/GameControllerTests.cs @@ -5,7 +5,7 @@ using System.Text.Json; using Microsoft.Extensions.Logging; using NSubstitute; using pacMan.Controllers; -using pacMan.Game; +using pacMan.GameStuff; using pacMan.Services; using pacMan.Utils; diff --git a/BackendTests/Game/Items/DiceCupTests.cs b/BackendTests/Game/Items/DiceCupTests.cs index a2a74ae..577b492 100644 --- a/BackendTests/Game/Items/DiceCupTests.cs +++ b/BackendTests/Game/Items/DiceCupTests.cs @@ -1,4 +1,4 @@ -using pacMan.Game.Items; +using pacMan.GameStuff.Items; namespace BackendTests.Game.Items; @@ -11,7 +11,7 @@ public class DiceCupTests var roll = diceCup.Roll; Assert.That(roll, Has.Count.EqualTo(2)); } - + [Test] public void Roll_ReturnsNumbersInRange1To6() { diff --git a/BackendTests/Game/Items/DiceTests.cs b/BackendTests/Game/Items/DiceTests.cs index 060da91..7938e32 100644 --- a/BackendTests/Game/Items/DiceTests.cs +++ b/BackendTests/Game/Items/DiceTests.cs @@ -1,4 +1,4 @@ -using pacMan.Game.Items; +using pacMan.GameStuff.Items; namespace BackendTests.Game.Items; diff --git a/BackendTests/Services/ActionServiceTests.cs b/BackendTests/Services/ActionServiceTests.cs index beaac86..00bb70a 100644 --- a/BackendTests/Services/ActionServiceTests.cs +++ b/BackendTests/Services/ActionServiceTests.cs @@ -2,8 +2,8 @@ using System.Text.Json; using BackendTests.TestUtils; using Microsoft.Extensions.Logging; using NSubstitute; -using pacMan.Game; -using pacMan.Game.Items; +using pacMan.GameStuff; +using pacMan.GameStuff.Items; using pacMan.Services; namespace BackendTests.Services; @@ -171,7 +171,8 @@ public class ActionServiceTests [Test] public void Ready_TwoReady() { - var group = new GameGroup(new Queue()) { Players = { _blackPlayer, _whitePlayer } }; + var group = new pacMan.Services.Game(new Queue()) + { Players = { _blackPlayer, _whitePlayer } }; _service.Group = group; _service.Player = _blackPlayer; @@ -194,7 +195,7 @@ public class ActionServiceTests [Test] public void FindNextPlayer_NoPlayers() { - _service.Group = new GameGroup(new Queue()); + _service.Group = new pacMan.Services.Game(new Queue()); Assert.Throws(() => _service.FindNextPlayer()); } @@ -202,7 +203,7 @@ public class ActionServiceTests public void FindNextPlayer_OnePlayer() { _service.Group = - new GameGroup(new Queue( + new pacMan.Services.Game(new Queue( new[] { new DirectionalPosition { At = new Position { X = 3, Y = 3 }, Direction = Direction.Up } })) { Players = { _whitePlayer } }; @@ -213,7 +214,7 @@ public class ActionServiceTests [Test] public void FindNextPlayer_TwoPlayers() { - _service.Group = new GameGroup(new Queue( + _service.Group = new pacMan.Services.Game(new Queue( new[] { new DirectionalPosition { At = new Position { X = 3, Y = 3 }, Direction = Direction.Up }, diff --git a/BackendTests/Services/GameServiceTests.cs b/BackendTests/Services/GameServiceTests.cs new file mode 100644 index 0000000..56438e5 --- /dev/null +++ b/BackendTests/Services/GameServiceTests.cs @@ -0,0 +1,100 @@ +using BackendTests.TestUtils; +using Microsoft.Extensions.Logging; +using NSubstitute; +using pacMan.Exceptions; +using pacMan.GameStuff; +using pacMan.Services; + +namespace BackendTests.Services; + +public class GameServiceTests +{ + private readonly DirectionalPosition _spawn3By3Up = new() + { At = new Position { X = 3, Y = 3 }, Direction = Direction.Up }; + + private GameService _service = null!; + private Queue _spawns = null!; + + [SetUp] + public void SetUp() + { + _service = new GameService(Substitute.For>()); + _spawns = new Queue(new[] + { + _spawn3By3Up, + new DirectionalPosition { At = new Position { X = 7, Y = 7 }, Direction = Direction.Down }, + new DirectionalPosition { At = new Position { X = 7, Y = 7 }, Direction = Direction.Down }, + new DirectionalPosition { At = new Position { X = 7, Y = 7 }, Direction = Direction.Down } + }); + } + + #region JoinbyId(Guid id) + + [Test] + public void JoinById_WhenIdNotExists() + { + var player = Players.Create("white"); + _service.AddPlayer(player, _spawns); + + Assert.Throws(() => _service.JoinById(Guid.NewGuid(), player)); + } + + [Test] + public void JoinById_WhenIdExists() + { + var player = Players.Create("white"); + var group = _service.AddPlayer(player, _spawns); + + var player2 = Players.Create("black"); + var result = _service.JoinById(group.Id, player2); + + Assert.Multiple(() => + { + Assert.That(result, Is.EqualTo(group)); + Assert.That(group.Players, Has.Count.EqualTo(2)); + Assert.That(_service.Games, Has.Count.EqualTo(1)); + }); + } + + #endregion + + #region AddPlayer(IPlayer) + + [Test] + public void AddPlayer_ToEmptyGroup() + { + var player = Players.Create("white"); + var group = _service.AddPlayer(player, _spawns); + + Assert.Multiple(() => + { + Assert.That(group.Players, Has.Count.EqualTo(1)); + Assert.That(group.NextPlayer, Is.EqualTo(player)); + Assert.That(_service.Games, Has.Count.EqualTo(1)); + }); + } + + [Test] + public void AddPlayer_ToFullGroup() + { + for (var i = 0; i < 4; i++) + { + var player = Players.Create(i.ToString()); + _service.AddPlayer(player, _spawns); + } + + var player5 = Players.Create("white"); + + var group = _service.AddPlayer(player5, new Queue(new[] { _spawn3By3Up })); + + Assert.Multiple(() => + { + Assert.That(group.Players, Has.Count.EqualTo(1)); + Assert.That(group.NextPlayer, Is.EqualTo(player5)); + Assert.That(_service.Games, Has.Count.EqualTo(2)); + Assert.That(_service.Games.First(), Has.Count.EqualTo(Rules.MaxPlayers)); + }); + } + + #endregion +} diff --git a/BackendTests/Services/GameGroupTests.cs b/BackendTests/Services/GameTests.cs similarity index 64% rename from BackendTests/Services/GameGroupTests.cs rename to BackendTests/Services/GameTests.cs index cd4ddc3..2de0ebf 100644 --- a/BackendTests/Services/GameGroupTests.cs +++ b/BackendTests/Services/GameTests.cs @@ -1,13 +1,12 @@ using BackendTests.TestUtils; using pacMan.Exceptions; -using pacMan.Game; -using pacMan.Game.Items; -using pacMan.Services; +using pacMan.GameStuff; +using pacMan.GameStuff.Items; using pacMan.Utils; namespace BackendTests.Services; -public class GameGroupTests +public class GameTests { private readonly DirectionalPosition _spawn3By3Up = new() { At = new Position { X = 3, Y = 3 }, Direction = Direction.Up }; @@ -22,7 +21,7 @@ public class GameGroupTests { At = new Position { X = 7, Y = 7 }, Direction = Direction.Right }; private IPlayer _bluePlayer = null!; - private GameGroup _gameGroup = null!; + private pacMan.Services.Game _game = null!; private IPlayer _greenPlayer = null!; private IPlayer _purplePlayer = null!; private IPlayer _redPlayer = null!; @@ -36,7 +35,7 @@ public class GameGroupTests _spawns = new Queue( new[] { _spawn3By3Up, _spawn7By7Left, _spawn7By7Down, _spawn7By7Right }); - _gameGroup = new GameGroup(_spawns); + _game = new pacMan.Services.Game(_spawns); _redPlayer = Players.Create("red"); _bluePlayer = Players.Create("blue"); _yellowPlayer = Players.Create("yellow"); @@ -46,10 +45,10 @@ public class GameGroupTests private void AddFullParty() { - _gameGroup.AddPlayer(_bluePlayer); - _gameGroup.AddPlayer(_redPlayer); - _gameGroup.AddPlayer(_yellowPlayer); - _gameGroup.AddPlayer(_greenPlayer); + _game.AddPlayer(_bluePlayer); + _game.AddPlayer(_redPlayer); + _game.AddPlayer(_yellowPlayer); + _game.AddPlayer(_greenPlayer); } #region NextPlayer() @@ -57,7 +56,7 @@ public class GameGroupTests [Test] public void NextPlayer_WhenEmpty() { - Assert.Throws(() => _gameGroup.NextPlayer()); + Assert.Throws(() => _game.NextPlayer()); } #endregion @@ -67,7 +66,7 @@ public class GameGroupTests [Test] public void AddPlayer_WhenEmpty() { - var added = _gameGroup.AddPlayer(_redPlayer); + var added = _game.AddPlayer(_redPlayer); Assert.That(added, Is.True); } @@ -76,16 +75,16 @@ public class GameGroupTests Assert.Multiple(() => { AddFullParty(); - Assert.That(_gameGroup.Players.Count, Is.EqualTo(Rules.MaxPlayers)); - Assert.That(_gameGroup.AddPlayer(_purplePlayer), Is.False); + Assert.That(_game.Players.Count, Is.EqualTo(Rules.MaxPlayers)); + Assert.That(_game.AddPlayer(_purplePlayer), Is.False); }); [Test] public void AddPlayer_WhenNameExists() { var redClone = Players.Clone(_redPlayer); - _gameGroup.AddPlayer(_redPlayer); - var added = _gameGroup.AddPlayer(redClone); + _game.AddPlayer(_redPlayer); + var added = _game.AddPlayer(redClone); Assert.That(added, Is.True); } @@ -93,14 +92,14 @@ public class GameGroupTests public void AddPlayer_WhenStateIsNotWaitingForPlayers() { _redPlayer.State = State.InGame; - _gameGroup.AddPlayer(_redPlayer); + _game.AddPlayer(_redPlayer); Assert.That(_redPlayer.State, Is.EqualTo(State.WaitingForPlayers)); } [Test] public void AddPlayer_AddSpawnPosition() { - _gameGroup.AddPlayer(_redPlayer); + _game.AddPlayer(_redPlayer); Assert.That(_redPlayer.PacMan.SpawnPosition, Is.Not.Null); Assert.That(_redPlayer.PacMan.SpawnPosition, Is.EqualTo(_spawn3By3Up)); } @@ -108,16 +107,16 @@ public class GameGroupTests [Test] public void AddPlayer_WhenGameHasStarted() { - _gameGroup.AddPlayer(_redPlayer); - _gameGroup.AddPlayer(_bluePlayer); + _game.AddPlayer(_redPlayer); + _game.AddPlayer(_bluePlayer); - _gameGroup.SetReady(_redPlayer); - _gameGroup.SetReady(_bluePlayer); - _gameGroup.SetAllInGame(); - - Assert.That(_gameGroup.AddPlayer(_greenPlayer), Is.False); + _game.SetReady(_redPlayer); + _game.SetReady(_bluePlayer); + _game.SetAllInGame(); + + Assert.That(_game.AddPlayer(_greenPlayer), Is.False); } - + #endregion #region Sendtoall(ArraySegment segment) @@ -125,7 +124,7 @@ public class GameGroupTests [Test] public void SendToAll_WhenConnectionsIsNull() { - Assert.DoesNotThrow(() => _gameGroup.SendToAll(new { }.ToArraySegment())); + Assert.DoesNotThrow(() => _game.SendToAll(new { }.ToArraySegment())); } [Test] @@ -134,10 +133,10 @@ public class GameGroupTests var counter = 0; async Task Send(ArraySegment segment) => await Task.Run(() => counter++); - _gameGroup.Connections += Send; - _gameGroup.Connections += Send; + _game.Connections += Send; + _game.Connections += Send; - _gameGroup.SendToAll(new { }.ToArraySegment()); + _game.SendToAll(new { }.ToArraySegment()); // TODO timeout after n amount of time while (counter < 2) { } @@ -152,10 +151,10 @@ public class GameGroupTests [Test] public void SetReady_ReturnsAllPlayers() { - _gameGroup.AddPlayer(_redPlayer); - _gameGroup.AddPlayer(_bluePlayer); + _game.AddPlayer(_redPlayer); + _game.AddPlayer(_bluePlayer); - var players = _gameGroup.SetReady(_redPlayer).ToList(); + var players = _game.SetReady(_redPlayer).ToList(); Assert.Multiple(() => { @@ -168,11 +167,11 @@ public class GameGroupTests [Test] public void SetReady_SetsStateToReady() { - _gameGroup.AddPlayer(_redPlayer); + _game.AddPlayer(_redPlayer); Assert.That(_redPlayer.State, Is.Not.EqualTo(State.Ready)); - _gameGroup.SetReady(_redPlayer); + _game.SetReady(_redPlayer); Assert.That(_redPlayer.State, Is.EqualTo(State.Ready)); } @@ -180,7 +179,7 @@ public class GameGroupTests [Test] public void SetReady_WhenPlayerIsNotInPlayers() { - Assert.Throws(() => _gameGroup.SetReady(_redPlayer)); + Assert.Throws(() => _game.SetReady(_redPlayer)); } #endregion @@ -191,15 +190,15 @@ public class GameGroupTests public void SetAllInGame_SetsStateToInGame() { AddFullParty(); - _gameGroup.Players.ForEach(player => player.State = State.Ready); - Assert.That(_gameGroup.Players, Has.All.Property(nameof(IPlayer.State)).EqualTo(State.Ready)); + _game.Players.ForEach(player => player.State = State.Ready); + Assert.That(_game.Players, Has.All.Property(nameof(IPlayer.State)).EqualTo(State.Ready)); - var allInGame = _gameGroup.SetAllInGame(); + var allInGame = _game.SetAllInGame(); Assert.Multiple(() => { Assert.That(allInGame, Is.True); - Assert.That(_gameGroup.Players, Has.All.Property(nameof(IPlayer.State)).EqualTo(State.InGame)); + Assert.That(_game.Players, Has.All.Property(nameof(IPlayer.State)).EqualTo(State.InGame)); }); } @@ -207,15 +206,15 @@ public class GameGroupTests public void SetAllInGame_SetStateToInGame_WhenNotAllReady() { AddFullParty(); - var allInGame = _gameGroup.SetAllInGame(); + var allInGame = _game.SetAllInGame(); Assert.That(allInGame, Is.False); } [Test] public void SetAllInGame_WhenPlayersIsEmpty() { - _gameGroup.SetAllInGame(); - Assert.That(_gameGroup.Players, Is.Empty); + _game.SetAllInGame(); + Assert.That(_game.Players, Is.Empty); } #endregion @@ -226,15 +225,15 @@ public class GameGroupTests public void IsGameStarted_AllWaiting() { AddFullParty(); - Assert.That(_gameGroup.IsGameStarted, Is.False); + Assert.That(_game.IsGameStarted, Is.False); } [Test] public void IsGameStarted_AllInGame() { AddFullParty(); - _gameGroup.Players.ForEach(player => player.State = State.InGame); - Assert.That(_gameGroup.IsGameStarted, Is.True); + _game.Players.ForEach(player => player.State = State.InGame); + Assert.That(_game.IsGameStarted, Is.True); } #endregion diff --git a/BackendTests/Services/WebSocketServiceTests.cs b/BackendTests/Services/WebSocketServiceTests.cs index 7844f49..2c740f0 100644 --- a/BackendTests/Services/WebSocketServiceTests.cs +++ b/BackendTests/Services/WebSocketServiceTests.cs @@ -1,8 +1,7 @@ using System.Net.WebSockets; -using BackendTests.TestUtils; using Microsoft.Extensions.Logging; using NSubstitute; -using pacMan.Game; +using pacMan.Interfaces; using pacMan.Services; using pacMan.Utils; @@ -10,25 +9,12 @@ namespace BackendTests.Services; public class WebSocketServiceTests { - private readonly DirectionalPosition _spawn3By3Up = new() - { At = new Position { X = 3, Y = 3 }, Direction = Direction.Up }; - - private GameService _service = null!; - - private Queue _spawns = null!; - + private IWebSocketService _service = null!; [SetUp] public void SetUp() { - _service = new GameService(Substitute.For>()); - _spawns = new Queue(new[] - { - _spawn3By3Up, - new DirectionalPosition { At = new Position { X = 7, Y = 7 }, Direction = Direction.Down }, - new DirectionalPosition { At = new Position { X = 7, Y = 7 }, Direction = Direction.Down }, - new DirectionalPosition { At = new Position { X = 7, Y = 7 }, Direction = Direction.Down } - }); + _service = new WebSocketService(Substitute.For>()); } #region Send(Websocket, ArraySegment) @@ -140,44 +126,4 @@ public class WebSocketServiceTests } #endregion - - #region AddPlayer(IPlayer) - - [Test] - public void AddPlayer_ToEmptyGroup() - { - var player = Players.Create("white"); - var group = _service.AddPlayer(player, _spawns); - - Assert.Multiple(() => - { - Assert.That(group.Players, Has.Count.EqualTo(1)); - Assert.That(group.NextPlayer, Is.EqualTo(player)); - Assert.That(_service.Games, Has.Count.EqualTo(1)); - }); - } - - [Test] - public void AddPlayer_ToFullGroup() - { - for (var i = 0; i < 4; i++) - { - var player = Players.Create(i.ToString()); - _service.AddPlayer(player, _spawns); - } - - var player5 = Players.Create("white"); - - var group = _service.AddPlayer(player5, new Queue(new[] { _spawn3By3Up })); - - Assert.Multiple(() => - { - Assert.That(group.Players, Has.Count.EqualTo(1)); - Assert.That(group.NextPlayer, Is.EqualTo(player5)); - Assert.That(_service.Games, Has.Count.EqualTo(2)); - Assert.That(_service.Games.First(), Has.Count.EqualTo(Rules.MaxPlayers)); - }); - } - - #endregion } diff --git a/BackendTests/TestUtils/Players.cs b/BackendTests/TestUtils/Players.cs index 5a80657..5c68b9f 100644 --- a/BackendTests/TestUtils/Players.cs +++ b/BackendTests/TestUtils/Players.cs @@ -1,5 +1,5 @@ -using pacMan.Game; -using pacMan.Game.Items; +using pacMan.GameStuff; +using pacMan.GameStuff.Items; namespace BackendTests.TestUtils; diff --git a/pac-man-board-game/ClientApp/src/pages/lobby.tsx b/pac-man-board-game/ClientApp/src/pages/lobby.tsx index e40d483..e75917c 100644 --- a/pac-man-board-game/ClientApp/src/pages/lobby.tsx +++ b/pac-man-board-game/ClientApp/src/pages/lobby.tsx @@ -4,7 +4,7 @@ import {Button} from "../components/Button"; const fetchAtom = atom(async () => { const response = await fetch(import.meta.env.VITE_API_HTTP + "/allGames"); - return await response.json() as GameGroup[]; + return await response.json() as Game[]; }); const LobbyPage: Component = () => ( diff --git a/pac-man-board-game/ClientApp/src/types/types.d.ts b/pac-man-board-game/ClientApp/src/types/types.d.ts index 47cd8e1..dc92b0c 100644 --- a/pac-man-board-game/ClientApp/src/types/types.d.ts +++ b/pac-man-board-game/ClientApp/src/types/types.d.ts @@ -35,7 +35,7 @@ type Path = { Direction: import("../game/direction").Direction } -type GameGroup = { +type Game = { readonly id: string, readonly count: number, readonly isGameStarted: boolean, diff --git a/pac-man-board-game/Controllers/GameController.cs b/pac-man-board-game/Controllers/GameController.cs index a0b276c..b93a266 100644 --- a/pac-man-board-game/Controllers/GameController.cs +++ b/pac-man-board-game/Controllers/GameController.cs @@ -1,6 +1,6 @@ using System.Net.WebSockets; using Microsoft.AspNetCore.Mvc; -using pacMan.Game; +using pacMan.GameStuff; using pacMan.Services; using pacMan.Utils; @@ -11,19 +11,23 @@ namespace pacMan.Controllers; public class GameController : GenericController // TODO reconnect using player id { private readonly IActionService _actionService; + private readonly GameService _gameService; public GameController(ILogger logger, GameService gameService, IActionService actionService) : - base(logger, gameService) => + base(logger, gameService) + { + _gameService = gameService; _actionService = actionService; + } [HttpGet("connect")] public override async Task Accept() => await base.Accept(); [HttpGet("allGames")] - public IEnumerable GetAllGames() + public IEnumerable GetAllGames() { Logger.Log(LogLevel.Information, "Returning all games"); - return GameService.Games; + return _gameService.Games; } @@ -38,9 +42,23 @@ public class GameController : GenericController // TODO reconnect using player i return action.ToArraySegment(); } + protected override void Send(ArraySegment segment) => _gameService.SendToAll(segment); + + protected override Task Echo() + { + _gameService.Connections += WsServiceOnFire; + return base.Echo(); + } + protected override void Disconnect() { - base.Disconnect(); + _gameService.Connections -= WsServiceOnFire; _actionService.Disconnect(); } + + private async Task WsServiceOnFire(ArraySegment segment) + { + if (WebSocket == null) return; + await GameService.Send(WebSocket, segment); + } } diff --git a/pac-man-board-game/Controllers/GenericController.cs b/pac-man-board-game/Controllers/GenericController.cs index 0ecfbb6..2c5f9e0 100644 --- a/pac-man-board-game/Controllers/GenericController.cs +++ b/pac-man-board-game/Controllers/GenericController.cs @@ -1,17 +1,17 @@ using System.Net.WebSockets; using Microsoft.AspNetCore.Mvc; -using pacMan.Services; +using pacMan.Interfaces; namespace pacMan.Controllers; -public abstract class GenericController : ControllerBase // TODO only use WebSocketService in this class +public abstract class GenericController : ControllerBase { private const int BufferSize = 1024 * 4; - protected readonly GameService GameService; + protected readonly IWebSocketService GameService; protected readonly ILogger Logger; - private WebSocket? _webSocket; + protected WebSocket? WebSocket; - protected GenericController(ILogger logger, GameService gameService) + protected GenericController(ILogger logger, IWebSocketService gameService) { Logger = logger; GameService = gameService; @@ -24,8 +24,7 @@ public abstract class GenericController : ControllerBase // TODO only use WebSoc { using var webSocket = await HttpContext.WebSockets.AcceptWebSocketAsync(); Logger.Log(LogLevel.Information, "WebSocket connection established to {}", HttpContext.Connection.Id); - _webSocket = webSocket; - GameService.Connections += WsServiceOnFire; + WebSocket = webSocket; await Echo(); } else @@ -34,32 +33,25 @@ public abstract class GenericController : ControllerBase // TODO only use WebSoc } } - private async Task WsServiceOnFire(ArraySegment segment) - { - if (_webSocket == null) return; - await GameService.Send(_webSocket, segment); - } - - protected virtual async Task Echo() { - if (_webSocket == null) return; + if (WebSocket == null) return; try { WebSocketReceiveResult? result; do { var buffer = new byte[BufferSize]; - result = await GameService.Receive(_webSocket, buffer); + result = await GameService.Receive(WebSocket, buffer); if (result.CloseStatus.HasValue) break; var segment = Run(result, buffer); - GameService.SendToAll(segment); + Send(segment); } while (true); - await GameService.Close(_webSocket, result.CloseStatus.Value, result.CloseStatusDescription); + await GameService.Close(WebSocket, result.CloseStatus.Value, result.CloseStatusDescription); } catch (WebSocketException e) { @@ -69,7 +61,13 @@ public abstract class GenericController : ControllerBase // TODO only use WebSoc Disconnect(); } + protected virtual async void Send(ArraySegment segment) + { + if (WebSocket == null) return; + await GameService.Send(WebSocket, segment); + } + protected abstract ArraySegment Run(WebSocketReceiveResult result, byte[] data); - protected virtual void Disconnect() => GameService.Connections -= WsServiceOnFire; + protected virtual void Disconnect() { } } diff --git a/pac-man-board-game/Exceptions/GameNotFoundException.cs b/pac-man-board-game/Exceptions/GameNotFoundException.cs new file mode 100644 index 0000000..62b3cc2 --- /dev/null +++ b/pac-man-board-game/Exceptions/GameNotFoundException.cs @@ -0,0 +1,6 @@ +namespace pacMan.Exceptions; + +public class GameNotFoundException : Exception +{ + public GameNotFoundException(string message = "Game not found") : base(message) { } +} diff --git a/pac-man-board-game/Game/Actions.cs b/pac-man-board-game/GameStuff/Actions.cs similarity index 93% rename from pac-man-board-game/Game/Actions.cs rename to pac-man-board-game/GameStuff/Actions.cs index a93fef0..c0575af 100644 --- a/pac-man-board-game/Game/Actions.cs +++ b/pac-man-board-game/GameStuff/Actions.cs @@ -1,6 +1,6 @@ using System.Text.Json; -namespace pacMan.Game; +namespace pacMan.GameStuff; public enum GameAction { diff --git a/pac-man-board-game/Game/Character.cs b/pac-man-board-game/GameStuff/Character.cs similarity index 97% rename from pac-man-board-game/Game/Character.cs rename to pac-man-board-game/GameStuff/Character.cs index ae251c9..40031c5 100644 --- a/pac-man-board-game/Game/Character.cs +++ b/pac-man-board-game/GameStuff/Character.cs @@ -1,4 +1,4 @@ -namespace pacMan.Game; +namespace pacMan.GameStuff; public class Character : IEquatable { diff --git a/pac-man-board-game/Game/Items/Box.cs b/pac-man-board-game/GameStuff/Items/Box.cs similarity index 97% rename from pac-man-board-game/Game/Items/Box.cs rename to pac-man-board-game/GameStuff/Items/Box.cs index 1b05ab9..87c0808 100644 --- a/pac-man-board-game/Game/Items/Box.cs +++ b/pac-man-board-game/GameStuff/Items/Box.cs @@ -1,4 +1,4 @@ -namespace pacMan.Game.Items; +namespace pacMan.GameStuff.Items; public class Box : IEquatable { diff --git a/pac-man-board-game/Game/Items/Dice.cs b/pac-man-board-game/GameStuff/Items/Dice.cs similarity index 83% rename from pac-man-board-game/Game/Items/Dice.cs rename to pac-man-board-game/GameStuff/Items/Dice.cs index e70adf8..1ea4648 100644 --- a/pac-man-board-game/Game/Items/Dice.cs +++ b/pac-man-board-game/GameStuff/Items/Dice.cs @@ -1,4 +1,4 @@ -namespace pacMan.Game.Items; +namespace pacMan.GameStuff.Items; public interface IDice { diff --git a/pac-man-board-game/Game/Items/DiceCup.cs b/pac-man-board-game/GameStuff/Items/DiceCup.cs similarity index 90% rename from pac-man-board-game/Game/Items/DiceCup.cs rename to pac-man-board-game/GameStuff/Items/DiceCup.cs index cc4e25d..7692f0a 100644 --- a/pac-man-board-game/Game/Items/DiceCup.cs +++ b/pac-man-board-game/GameStuff/Items/DiceCup.cs @@ -1,4 +1,4 @@ -namespace pacMan.Game.Items; +namespace pacMan.GameStuff.Items; public interface IDiceCup { diff --git a/pac-man-board-game/Game/Items/Pellet.cs b/pac-man-board-game/GameStuff/Items/Pellet.cs similarity index 95% rename from pac-man-board-game/Game/Items/Pellet.cs rename to pac-man-board-game/GameStuff/Items/Pellet.cs index ed01bac..1bc27ef 100644 --- a/pac-man-board-game/Game/Items/Pellet.cs +++ b/pac-man-board-game/GameStuff/Items/Pellet.cs @@ -1,4 +1,4 @@ -namespace pacMan.Game.Items; +namespace pacMan.GameStuff.Items; public interface IPellet { diff --git a/pac-man-board-game/Game/Items/Player.cs b/pac-man-board-game/GameStuff/Items/Player.cs similarity index 97% rename from pac-man-board-game/Game/Items/Player.cs rename to pac-man-board-game/GameStuff/Items/Player.cs index b7e1286..2cc298a 100644 --- a/pac-man-board-game/Game/Items/Player.cs +++ b/pac-man-board-game/GameStuff/Items/Player.cs @@ -1,4 +1,4 @@ -namespace pacMan.Game.Items; +namespace pacMan.GameStuff.Items; public interface IPlayer { diff --git a/pac-man-board-game/Game/Positions.cs b/pac-man-board-game/GameStuff/Positions.cs similarity index 98% rename from pac-man-board-game/Game/Positions.cs rename to pac-man-board-game/GameStuff/Positions.cs index 5b87162..2a8cc91 100644 --- a/pac-man-board-game/Game/Positions.cs +++ b/pac-man-board-game/GameStuff/Positions.cs @@ -1,4 +1,4 @@ -namespace pacMan.Game; +namespace pacMan.GameStuff; public class MovePath : IEquatable { diff --git a/pac-man-board-game/Game/Rules.cs b/pac-man-board-game/GameStuff/Rules.cs similarity index 84% rename from pac-man-board-game/Game/Rules.cs rename to pac-man-board-game/GameStuff/Rules.cs index 3a4e7ae..45d8154 100644 --- a/pac-man-board-game/Game/Rules.cs +++ b/pac-man-board-game/GameStuff/Rules.cs @@ -1,4 +1,4 @@ -namespace pacMan.Game; +namespace pacMan.GameStuff; public class Rules { @@ -6,4 +6,4 @@ public class Rules public const int MaxPlayers = 4; public const int NumGhosts = 2; public const int BoardSize = 10; -} \ No newline at end of file +} diff --git a/pac-man-board-game/Services/ActionService.cs b/pac-man-board-game/Services/ActionService.cs index bc66c3c..a9d15a6 100644 --- a/pac-man-board-game/Services/ActionService.cs +++ b/pac-man-board-game/Services/ActionService.cs @@ -1,14 +1,14 @@ using System.Text.Json; using Microsoft.CSharp.RuntimeBinder; -using pacMan.Game; -using pacMan.Game.Items; +using pacMan.GameStuff; +using pacMan.GameStuff.Items; namespace pacMan.Services; public interface IActionService { IPlayer Player { set; } - GameGroup Group { set; } + Game Group { set; } void DoAction(ActionMessage message); List RollDice(); List SetPlayerInfo(ActionMessage message); @@ -30,7 +30,7 @@ public class ActionService : IActionService _gameService = gameService; } - public GameGroup? Group { get; set; } + public Game? Group { get; set; } public IPlayer? Player { get; set; } diff --git a/pac-man-board-game/Services/GameGroup.cs b/pac-man-board-game/Services/Game.cs similarity index 92% rename from pac-man-board-game/Services/GameGroup.cs rename to pac-man-board-game/Services/Game.cs index fc625d3..9dcd9cb 100644 --- a/pac-man-board-game/Services/GameGroup.cs +++ b/pac-man-board-game/Services/Game.cs @@ -1,16 +1,16 @@ using System.Text.Json.Serialization; using pacMan.Exceptions; -using pacMan.Game; -using pacMan.Game.Items; +using pacMan.GameStuff; +using pacMan.GameStuff.Items; namespace pacMan.Services; -public class GameGroup // TODO handle disconnects and reconnects +public class Game // TODO handle disconnects and reconnects { private readonly Random _random = new(); private int _currentPlayerIndex; - public GameGroup(Queue spawns) => Spawns = spawns; + public Game(Queue spawns) => Spawns = spawns; [JsonInclude] public Guid Id { get; } = Guid.NewGuid(); diff --git a/pac-man-board-game/Services/GameService.cs b/pac-man-board-game/Services/GameService.cs index 6ecdd58..84a4619 100644 --- a/pac-man-board-game/Services/GameService.cs +++ b/pac-man-board-game/Services/GameService.cs @@ -1,5 +1,6 @@ -using pacMan.Game; -using pacMan.Game.Items; +using pacMan.Exceptions; +using pacMan.GameStuff; +using pacMan.GameStuff.Items; namespace pacMan.Services; @@ -7,7 +8,7 @@ public class GameService : WebSocketService { public GameService(ILogger logger) : base(logger) { } - public SynchronizedCollection Games { get; } = new(); + public SynchronizedCollection Games { get; } = new(); public event Func, Task>? Connections; // TODO remove and use GameGroup @@ -16,7 +17,7 @@ public class GameService : WebSocketService Connections?.Invoke(segment); } - public GameGroup AddPlayer(IPlayer player, Queue spawns) + public Game AddPlayer(IPlayer player, Queue spawns) { var index = 0; try @@ -25,11 +26,21 @@ public class GameService : WebSocketService } catch (ArgumentOutOfRangeException) { - var game = new GameGroup(spawns); + var game = new Game(spawns); game.AddPlayer(player); Games.Add(game); } return Games[index]; } + + public Game JoinById(Guid id, IPlayer player) + { + var game = Games.FirstOrDefault(g => g.Id == id) ?? throw new GameNotFoundException(); + var added = game.AddPlayer(player); + + if (!added) throw new ArgumentException("Game is full"); + + return game; + } }