public async Task <Result <Player, JoinGameError> > JoinGameAsync(GameId gameId, string playerName) { var result = await _gameRepository.GetGameAndVersionAsync(gameId); return(await result.Map <Task <Result <Player, JoinGameError> > >( async gameAndVersion => { var(game, version) = gameAndVersion; if (game.Players.Count >= Models.Game.MaxNumberOfPlayers) { return JoinGameError.GameFull; } var playerJoined = new PlayerJoined(playerName); await _eventRepository.AddEventAsync(gameId, playerJoined, version); var changedResources = playerJoined.ApplyAndGetModifiedResources(game); var changedResourceNames = ChangedResourcesResolver.GetResourceNames(changedResources); await _gameEventService.NotifyWorldUpdatedAsync(game.Id, changedResourceNames.ToArray()); return Convert(game.Players.Last()); }, readGameError => { return readGameError switch { ReadGameError.NotFound => Task.FromResult(new Result <Player, JoinGameError>(JoinGameError.GameNotFound)), _ => throw new ArgumentOutOfRangeException(nameof(readGameError), readGameError, null) }; }));