diff --git a/GameData/ApiClient.cs b/GameData/ApiClient.cs index ed03793..bbfffae 100644 --- a/GameData/ApiClient.cs +++ b/GameData/ApiClient.cs @@ -17,11 +17,16 @@ namespace GameData { public sealed class ApiClient : IDisposable { - private class Wrapper + private class WrapperArray { public T[] Data { get; set; } } + private class WrapperSingle + { + public T Data { get; set; } + } + private readonly HttpClient client; private readonly ILogger _logger; private readonly AppSettings _appSettings; @@ -145,13 +150,13 @@ namespace GameData /// /// /// - public T Post(object payload, string serviceUrl, bool suppressExceptions = false) + public async Task Post(object payload, string serviceUrl, bool suppressExceptions = false) { T res = default; try { - var response = client.Send(GetHttpRequestMessage(HttpMethod.Post, serviceUrl, payload)); + var response = await client.SendAsync(GetHttpRequestMessage(HttpMethod.Post, serviceUrl, payload)); if (response.IsSuccessStatusCode) { @@ -162,14 +167,15 @@ namespace GameData using (var jsonTextReader = new JsonTextReader(streamReader)) { var serializer = new JsonSerializer(); - res = serializer.Deserialize(jsonTextReader); + var wrapper = serializer.Deserialize>(jsonTextReader); + res = wrapper.Data; } } } } else { - var errorResult = response.Content.ReadAsStringAsync().Result; + var errorResult = await response.Content.ReadAsStringAsync(); _logger.LogError("error posting to service '{service}' with code '{statuscode}' - Result: '{result}', Payload: '{payload}'", serviceUrl, response.StatusCode, errorResult, JsonConvert.SerializeObject(payload)); } } @@ -227,7 +233,7 @@ namespace GameData public T[] Get(string serviceUrl, bool suppressExceptions = false) { - Wrapper res = default; + WrapperArray res = default; try { @@ -244,14 +250,14 @@ namespace GameData if (typeof(T).Equals(typeof(string))) { content = streamReader.ReadToEnd(); - res = (Wrapper)Convert.ChangeType(content, typeof(T)); + res = (WrapperArray)Convert.ChangeType(content, typeof(T)); } else { using (var jsonTextReader = new JsonTextReader(streamReader)) { var serializer = new JsonSerializer(); - res = serializer.Deserialize>(jsonTextReader); + res = serializer.Deserialize>(jsonTextReader); } } } @@ -275,13 +281,13 @@ namespace GameData return res.Data; } - internal void Put(object payload, string serviceUrl, bool suppressExceptions = false) + internal async Task Put(object payload, string serviceUrl, bool suppressExceptions = false) { T res = default; try { - var response = client.Send(GetHttpRequestMessage(HttpMethod.Post, serviceUrl, payload)); + var response = await client.SendAsync(GetHttpRequestMessage(HttpMethod.Post, serviceUrl, payload)); if (response.IsSuccessStatusCode) { @@ -292,14 +298,15 @@ namespace GameData using (var jsonTextReader = new JsonTextReader(streamReader)) { var serializer = new JsonSerializer(); - res = serializer.Deserialize(jsonTextReader); + var wrapper = serializer.Deserialize>(jsonTextReader); + res = wrapper.Data; } } } } else { - var errorResult = response.Content.ReadAsStringAsync().Result; + var errorResult = await response.Content.ReadAsStringAsync(); _logger.LogError("error posting to service '{service}' with code '{statuscode}' - Result: '{result}', Payload: '{payload}'", serviceUrl, response.StatusCode, errorResult, JsonConvert.SerializeObject(payload)); } } diff --git a/GameData/Dummy/DummyExpenseRepository.cs b/GameData/Dummy/DummyExpenseRepository.cs index c92fc9f..3052624 100644 --- a/GameData/Dummy/DummyExpenseRepository.cs +++ b/GameData/Dummy/DummyExpenseRepository.cs @@ -19,5 +19,10 @@ namespace GameData.Dummy { throw new NotImplementedException(); } + + Task IExpenseRepository.Save(MemberExpense data) + { + throw new NotImplementedException(); + } } } \ No newline at end of file diff --git a/GameData/Dummy/DummyGameRepository.cs b/GameData/Dummy/DummyGameRepository.cs index b439e3a..2dcc793 100644 --- a/GameData/Dummy/DummyGameRepository.cs +++ b/GameData/Dummy/DummyGameRepository.cs @@ -12,14 +12,25 @@ namespace GameData.Dummy { List gameStates = new List(); - public void Save(GameState gameState) + public Task Save(GameState gameState) { gameStates.Add(gameState); + return Task.CompletedTask; } public GameState Load(Guid gameId) { return gameStates.Last(); } + + public Task Update(Game game) + { + throw new NotImplementedException(); + } + + public Task Create(Game game) + { + throw new NotImplementedException(); + } } } diff --git a/GameData/Repository/ExpenseRepository.cs b/GameData/Repository/ExpenseRepository.cs index 3b05699..36fa496 100644 --- a/GameData/Repository/ExpenseRepository.cs +++ b/GameData/Repository/ExpenseRepository.cs @@ -23,7 +23,7 @@ namespace GameData.Repository _log = log; _client = apiClient; - _log?.LogWarning("TESTWARN"); + _log?.LogDebug("creating ExpenseRepository"); } public IEnumerable GetAll() @@ -31,7 +31,7 @@ namespace GameData.Repository return _client.Get(Url); } - public void Save(MemberExpense memberExpense) + public async Task Save(MemberExpense memberExpense) { _memberExpenses.Add(memberExpense); } diff --git a/GameData/Repository/GameRepository.cs b/GameData/Repository/GameRepository.cs index 80b4e5b..b3adbcc 100644 --- a/GameData/Repository/GameRepository.cs +++ b/GameData/Repository/GameRepository.cs @@ -15,7 +15,9 @@ namespace GameData.Repository readonly ILogger _log; private ApiClient _client; - string Url => "items/gamestate"; + string UrlGameState => "items/gamestate"; + string UrlGame => "items/game"; + public GameRepository(ILogger log, ApiClient apiClient) { _log = log; @@ -27,10 +29,20 @@ namespace GameData.Repository throw new NotImplementedException(); } - public void Save(GameState gameState) + public async Task Save(GameState gameState) { var gameStateDo = new GameStateDo(gameState.Id, gameState.GameId, gameState.GameName, gameState); - _client.Post(gameStateDo,Url); + var res = await _client.Post(gameStateDo,UrlGameState); + } + + public async Task Update(Game game) + { + await _client.Put(game, UrlGame); + } + + public async Task Create(Game game) + { + return await _client.Post(game, UrlGame); } } } diff --git a/GameHandler/GameService.cs b/GameHandler/GameService.cs index f7b1d0c..745315e 100644 --- a/GameHandler/GameService.cs +++ b/GameHandler/GameService.cs @@ -28,6 +28,7 @@ namespace GameHandler private ThrowHandler _th; private ExpenseHandler _eh; private GameStateHandler _gameStateHandler; + private Game _game; public GameState GameModel { get => _gameStateHandler.GameState; } @@ -50,12 +51,12 @@ namespace GameHandler static int[] defaultPlayerIds => new[] {1,2,3,4}; - public GameState Start(string gameName = FreeGameHandler.GAMENAME_FREETRAINING) + public async Task Start(string gameName = FreeGameHandler.GAMENAME_FREETRAINING) { - return Start(defaultPlayerIds, new DeathGameSettings(6), gameName); + return await Start(defaultPlayerIds, new DeathGameSettings(6), gameName); } - public GameState Start(int[] playerIds, IGameSettings gameSettings, string gameName = FreeGameHandler.GAMENAME_FREETRAINING) + public async Task Start(int[] playerIds, IGameSettings gameSettings, string gameName = FreeGameHandler.GAMENAME_FREETRAINING) { if (_isStarted) { @@ -64,18 +65,19 @@ namespace GameHandler _isStarted = true; InitGameServiceBehaviour(gameName); - var state = InitGameState(playerIds, gameSettings, gameName); - _gameStateHandler.Add(state); - _gameStateHandler.Add(ExpenseModel.Create()); + var state = await InitGameState(playerIds, gameSettings, gameName); + await _gameStateHandler.Add(state, _game); + await _gameStateHandler.Add(ExpenseModel.Create()); return state; } - private GameState InitGameState(int[] playerIds, IGameSettings gameSettings, string gameName) + private async Task InitGameState(int[] playerIds, IGameSettings gameSettings, string gameName) { var gm = _gh.InitGameModel(playerIds, gameSettings); var throwState = ThrowState.Create(_gh.ThrowMode(), _gh.ThrowsPerRount()); - return GameState.Create(Guid.NewGuid(), gameName, throwState, _gh.GetCurrentPlayerId(gm), gm); + _game = await _gameStateHandler.CreateNewGame(); + return GameState.Create(_game.Id, gameName, throwState, _gh.GetCurrentPlayerId(gm), gm); } private void InitGameServiceBehaviour(string gameName) @@ -95,7 +97,7 @@ namespace GameHandler //_lastState = _lastState with { ExpenseModel = expenseModel }; } - public GameState HandleThrow(PinThrow pinThrow) + public async Task HandleThrow(PinThrow pinThrow) { if (!_isStarted) { @@ -114,8 +116,8 @@ namespace GameHandler var newGameState = lastGameState with { ThrowState = throwStateAfterUpdate, GameModel = gameModel, NextPlayerId = _gh.GetCurrentPlayerId(gameModel) }; - _gameStateHandler.Add(expenseModel); - _gameStateHandler.Add(newGameState); + await _gameStateHandler.Add(expenseModel); + await _gameStateHandler.Add(newGameState, _game); return newGameState; } diff --git a/GameHandler/GameStateHandler.cs b/GameHandler/GameStateHandler.cs index 8ac8dd5..5ecb28d 100644 --- a/GameHandler/GameStateHandler.cs +++ b/GameHandler/GameStateHandler.cs @@ -64,20 +64,20 @@ namespace GameHandler } } - internal void Add(ExpenseModel expenseModel) + internal async Task Add(ExpenseModel expenseModel) { if (ExpenseModel != null) { if (!expenseModel.Equals(ExpenseModel)) { expenseModels.Add(new GameStateHandlerItem(_gameStateId, expenseModel, false)); - Save(); + await Save(); } } else { expenseModels.Add(new GameStateHandlerItem(_gameStateId, expenseModel, false)); - Save(); + await Save(); } @@ -87,34 +87,39 @@ namespace GameHandler } } - internal void Add(GameState newState) + internal async Task Add(GameState newState, Game game) { if (!newState.Equals(GameState)) { _gameStateId = Guid.NewGuid(); gameStates.Add(new GameStateHandlerItem(_gameStateId, newState, false)); - Save(); + await Save(); } } - private void Save() + private async Task Save() { - foreach (var item in gameStates.Where(_ => !_.Saved)) - { - _gameRepository.Save(item.Data); - item.Saved = true; - } + await Task.WhenAll(gameStates.Where(_ => !_.Saved) + .Select(_ => _gameRepository.Save(_.Data))) + .ContinueWith(_ => { + gameStates.ForEach(gs => { gs.Saved = true; }); + }); - foreach (var item in memberExpenses) - { - _expenseRepository.Save(item.Data); - item.Saved = true; - } + await Task.WhenAll(memberExpenses.Where(_ => !_.Saved) + .Select(_ => _expenseRepository.Save(_.Data))) + .ContinueWith(_ => { + memberExpenses.ForEach(me => { me.Saved = true; }); + }); } public void Undo() { } + + internal async Task CreateNewGame() + { + return await _gameRepository.Create(null); + } } } diff --git a/GameModel/Contracts/IExpenseRepository.cs b/GameModel/Contracts/IExpenseRepository.cs index c3e9faa..2a55ee5 100644 --- a/GameModel/Contracts/IExpenseRepository.cs +++ b/GameModel/Contracts/IExpenseRepository.cs @@ -18,6 +18,6 @@ namespace GameModel.Contract }; IEnumerable GetAll(); - void Save(MemberExpense data); + Task Save(MemberExpense data); } } \ No newline at end of file diff --git a/GameModel/Contracts/IGameRepository.cs b/GameModel/Contracts/IGameRepository.cs index c75caf3..ce1feef 100644 --- a/GameModel/Contracts/IGameRepository.cs +++ b/GameModel/Contracts/IGameRepository.cs @@ -8,7 +8,9 @@ namespace GameModel.Contracts { public interface IGameRepository { + Task Create(Game game); GameState Load(Guid gameId); - void Save(GameState gameState); + Task Save(GameState gameState); + Task Update(Game game); } } diff --git a/GameModel/Game.cs b/GameModel/Game.cs new file mode 100644 index 0000000..d51acec --- /dev/null +++ b/GameModel/Game.cs @@ -0,0 +1,16 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace GameModel +{ + public record Game(Guid Id) + { + public static Game Create() + { + return new Game(Guid.NewGuid()); + } + } +} diff --git a/KoogleCli/Program.cs b/KoogleCli/Program.cs index 0ec8964..ef7abe4 100644 --- a/KoogleCli/Program.cs +++ b/KoogleCli/Program.cs @@ -62,7 +62,7 @@ Autofac.IContainer Register() ShowMainMenu(); -void ShowMainMenu() +async Task ShowMainMenu() { do { @@ -126,8 +126,8 @@ void NewGameAction() void StartGameAction(string gameName) { _gs = new GameService(container); - var bs = _gs.Start(new[] { 1,2,3,4}, GetGameSettings(gameName), gameName ); - + var starttask = _gs.Start(new[] { 1, 2, 3, 4 }, GetGameSettings(gameName), gameName); + var bs = starttask.Result; Show(bs); @@ -159,7 +159,8 @@ void StartGameAction(string gameName) break; } - bs = _gs.HandleThrow(PinThrow.Create(throwData.Pindata, throwData.Bell, throwData.Sink, throwData.PlayerId)); + var task = _gs.HandleThrow(PinThrow.Create(throwData.Pindata, throwData.Bell, throwData.Sink, throwData.PlayerId)); + bs = task.Result; Show(bs); } while (true);