diff --git a/GameData/Repository/GameRepository.cs b/GameData/Repository/GameRepository.cs index c56fe8a..edf8748 100644 --- a/GameData/Repository/GameRepository.cs +++ b/GameData/Repository/GameRepository.cs @@ -57,6 +57,12 @@ namespace GameData.Repository var gameStateDo = new GameStateDo(gameState.Id, gameState.GameId, gameState.GameName, str, gameState.Counter); var res = await _client.Post(gameStateDo,UrlGameState); + if (res == null) + { + var msg = "error saviong gamestate - save rsult cannot be null - repo not online, or game deleted"; + _log.LogError(msg); + throw new InvalidOperationException(msg); + } var obj = JsonConvert.DeserializeObject(res.GameState, new JsonSerializerSettings() { diff --git a/GameHandler/ExpenseHandler.cs b/GameHandler/ExpenseHandler.cs index 4b7d7b8..1c4a254 100644 --- a/GameHandler/ExpenseHandler.cs +++ b/GameHandler/ExpenseHandler.cs @@ -61,7 +61,7 @@ namespace GameHandler } } - public ExpenseModel CheckThrow(BoardState currentState, PinThrow pinThrow, int[] PlayerIds, ExpenseModel expenseModelToAppend = null) + public async Task CheckThrow(BoardState currentState, PinThrow pinThrow, int[] PlayerIds, ExpenseModel expenseModelToAppend = null) { if (!PlayerIds.Any(_ => _ == pinThrow.PlayerId)) { @@ -71,7 +71,7 @@ namespace GameHandler List memberExpenses = PrepareResult(ref expenseModelToAppend); var triggers = pinThrow.GetExpenseTriggers(currentState); - AssignExpenses(pinThrow.PlayerId, PlayerIds, memberExpenses, triggers); + await AssignExpenses(pinThrow.PlayerId, PlayerIds, memberExpenses, triggers); return expenseModelToAppend with { MemberExpenses = memberExpenses.ToArray() }; } diff --git a/GameHandler/GameService.cs b/GameHandler/GameService.cs index 863daa2..b81bfbb 100644 --- a/GameHandler/GameService.cs +++ b/GameHandler/GameService.cs @@ -114,7 +114,7 @@ namespace GameHandler var throwStateAfterUpdate = _th.Update(lastGameState.ThrowState, pinThrow); var gameModel = _gh.Update(pinThrow, lastGameState.GameModel, boardStateBeforeUpdate, throwStateAfterUpdate); - var expenseModel = _eh.CheckThrow(throwStateAfterUpdate.BoardState, pinThrow, gameModel.PlayerIds, _gameStateHandler.ExpenseModel); + var expenseModel = await _eh.CheckThrow(throwStateAfterUpdate.BoardState, pinThrow, gameModel.PlayerIds, _gameStateHandler.ExpenseModel); var newGameState = lastGameState with { ThrowState = throwStateAfterUpdate, GameModel = gameModel, NextPlayerId = _gh.GetCurrentPlayerId(gameModel) }; @@ -180,14 +180,41 @@ namespace GameHandler public GameState Undo() { - throw new NotImplementedException(); + if (_game == null) + { + throw new InvalidGameStateExcpetion("Game not initialized"); + } + + if (!_isStarted) + { + throw new InvalidGameStateExcpetion("Game not started"); + } + + var previousState = _gameStateHandler.Undo(); + if (previousState != null) + { + return previousState; + } + + return _gameStateHandler?.GameState; } public GameState Redo() { - throw new NotImplementedException(); + if (_game == null) + { + throw new InvalidGameStateExcpetion("Game not initialized"); + } + + if (!_isStarted) + { + throw new InvalidGameStateExcpetion("Game not started"); + } + + return _gameStateHandler.Redo(); + } - + } } diff --git a/GameHandler/GameStateHandler.cs b/GameHandler/GameStateHandler.cs index e11d28e..49a3dc7 100644 --- a/GameHandler/GameStateHandler.cs +++ b/GameHandler/GameStateHandler.cs @@ -24,10 +24,15 @@ namespace GameHandler public class GameStateHandler { private Guid _gameStateId; + private List> gameStates = new List>(); private List> expenseModels = new List>(); private List> memberExpenses = new List>(); + private List> redoableGameStates = new List>(); + private List> redoableExpenseModels = new List>(); + private List> redoableemberExpenses = new List>(); + private IGameRepository _gameRepository; private IExpenseRepository _expenseRepository; @@ -109,9 +114,48 @@ namespace GameHandler await _gameRepository.Save(item.Data); } - public void Undo() + public GameState Redo() { - + if (gameStates.Count == 0) + { + return null; + } + + if (redoableGameStates.Count > 0) + { + var redoId = redoableGameStates.Last().GameStateId; + + gameStates.AddRange(redoableGameStates.Where(_ => _.GameStateId == redoId)); + expenseModels.AddRange(redoableExpenseModels.Where(_ => _.GameStateId == redoId)); + memberExpenses.AddRange(redoableemberExpenses.Where(_ => _.GameStateId == redoId)); + + redoableGameStates.RemoveAll(_ => _.GameStateId == redoId); + redoableExpenseModels.RemoveAll(_ => _.GameStateId == redoId); + redoableemberExpenses.RemoveAll(_ => _.GameStateId == redoId); + } + + _gameStateId = gameStates.Last().GameStateId; + return GameState; + } + + public GameState Undo() + { + if (gameStates.Count <= 1) + { + return null; + } + + redoableGameStates.AddRange(gameStates.Where(_ => _.GameStateId == _gameStateId)); + redoableExpenseModels.AddRange(expenseModels.Where(_ => _.GameStateId == _gameStateId)); + redoableemberExpenses.AddRange(memberExpenses.Where(_ => _.GameStateId == _gameStateId)); + + gameStates.RemoveAll(_ => _.GameStateId == _gameStateId); + expenseModels.RemoveAll(_ => _.GameStateId == _gameStateId); + memberExpenses.RemoveAll(_ => _.GameStateId == _gameStateId); + + _gameStateId = gameStates.Last().GameStateId; + + return GameState; } internal async Task CreateNewGame(string gameName) @@ -123,6 +167,9 @@ namespace GameHandler { var existingGameStates = await _gameRepository.LoadStates(gameId); gameStates.AddRange(existingGameStates.Select(_ => new GameStateHandlerItem(_.Id,_))); + + _gameStateId = gameStates.Last().GameStateId; + return existingGameStates.Last(); } diff --git a/KoogleCli/Program.cs b/KoogleCli/Program.cs index 2a50549..8d170bf 100644 --- a/KoogleCli/Program.cs +++ b/KoogleCli/Program.cs @@ -88,7 +88,7 @@ async Task ShowMainMenu() void ContinueGame() { - StartGameAction("", new Guid("c042f8f0-3f52-48e7-b61e-82a6387af4bb")); + StartGameAction("", new Guid("33869054-811f-49cb-940b-be582ee5d8a5")); } void MasterDataAction() @@ -185,14 +185,14 @@ void StartGameAction(string gameName, Guid gameId) { gameState = _gs.Undo(); Show(gameState); - break; + continue; } if (throwData.Redo) { gameState = _gs.Redo(); Show(gameState); - break; + continue; } var task = _gs.HandleThrow(PinThrow.Create(throwData.Pindata, throwData.Bell, throwData.Sink, throwData.PlayerId));