public async Task <DetailCastleStateModel> DetailCastle(Guid id, Guid castleId, string userId, int streamVersion) { var state = await Build(id, userId, streamVersion); if (state.HasError) { return(null); } ISnapshot latestSnapshot = _store.Advanced.GetSnapshot(id, int.MaxValue); GameAggregate gameSnapshot = latestSnapshot?.Payload as GameAggregate; var castle = gameSnapshot?.Castles?.FirstOrDefault(e => e.Id == castleId); if (castle == null) { return(null); } DetailCastleStateModel result = Mapper.Map <DetailCastleStateModel>(castle); result.StreamRevision = latestSnapshot.StreamRevision; result.CurrentUserArmy = state.UserId == userId ? Army.Blue : Army.Red; if (streamVersion >= 0) { result.Events = Mapper.Map <List <EventBaseModel> >(_domain.GetEvents(id, userId, streamVersion)); } result.Soldiers = GetSoldiersOfCastle(castle); bool isOwner = result.OwnerUserId == userId; result.CanChangeTroopType = isOwner; result.CanUpgrade = isOwner && result.Strength < await GetMaximunStrength(); await UpdateGameStateForReadData(id.ToString(), state); result.Revenue = _gameDomainService.CalculateCoin(gameSnapshot, castle); result.RevenueTime = _gameDomainService.GetRevenueTimeBySpeed(gameSnapshot.Speed); result.UpkeepTime = _gameDomainService.GetUpkeepTimeBySpeed(gameSnapshot.Speed); result.CanProductionSoldier = castle.IsProductionState() && result.ProduceExecuteAt.CompareTo(DateTime.UtcNow) > 0; if (!result.CanProductionSoldier) { var ownerCoins = castle.OwnerUserId == state.UserId ? state.UserCoins : state.OpponentCoins; result.IsNotEnoughCoinForProduction = ownerCoins < 0; } var ownerTask = _userRepository.GetByIdAsync(castle.OwnerUserId).ContinueWith(r => { if (r.Result == null) { return; } result.OwnerUser = Mapper.Map <UserModel>(r.Result); List <Hero> heroes = r.Result.Heroes; if (heroes == null || heroes.All(e => e.Id != castle.OwnerId)) { return; } result.Owner = Mapper.Map <HeroModel>(r.Result.Heroes.First(e => e.Id == castle.OwnerId)); }); var siegeOwnerTask = castle.Siege == null?Task.FromResult(true) : _userRepository.GetByIdAsync(castle.Siege.OwnerUserId).ContinueWith(r => { if (r.Result == null) { return; } result.Siege.OwnerUser = Mapper.Map <UserModel>(r.Result); }); await Task.WhenAll(ownerTask, siegeOwnerTask); return(result); }