Ejemplo n.º 1
0
        //[TestCase(true, -1, -1)]
        public void TestSendWavesScenario(bool sendAll, int existing, int existing2, string villageName)
        {
            var action = new SendWavesAction
            {
                Action  = GameActionType.SEND_ARMY,
                Village = new Village
                {
                    Name = "Unexpected_Town_02"
                },
                SendAll = sendAll,
                To      = new Village
                {
                    Name        = villageName,
                    CoordinateX = -151,
                    CoordinateY = 118
                },
                Type        = SendArmyType.ATTACK,
                UnitsToSend = new Dictionary <string, int>
                {
                    { "Легионер", existing }
                },
                Waves = 4
            };

            var send = new SendWavesScenario(provider, action);
            BaseScenarioResult result = new BaseScenarioResult();

            Assert.DoesNotThrow(() => result = send.Execute(new ScenarioContext {
                Player = player
            }));

            Assert.AreEqual(4, result.Villages.Count);
        }
Ejemplo n.º 2
0
        private BaseScenarioResult Login(ScenarioContext context)
        {
            if (context.Cookies != null && context.Cookies.Any())
            {
                foreach (var cookie in context.Cookies)
                {
                    _driver.Manage().Cookies.AddCookie(cookie);
                }
            }

            _driver.Navigate().GoToUrl(new Uri(context.Player.Uri, "/dorf1.php"));
            if (_driver.Url.Contains("login"))
            {
                var login    = _driver.FindElement(By.XPath("//input[@name='name']"));
                var password = _driver.FindElement(By.XPath("//input[@name='password']"));

                login.SendKeys(context.Player.UserName);
                password.SendKeys(context.Player.Password);
                _driver.FindElement(By.Id("s1"))?.Click();
                if (_driver.Url.Contains("login"))
                {
                    var result = new BaseScenarioResult();
                    result.Errors.Add(new ScenarioError
                    {
                        ErrorMessage = "Unable to login. Try to update the cookies.",
                        ErrorSource  = nameof(BaseScenario),
                        ErrorType    = "Critical"
                    });

                    return(result);
                }
            }

            return(null);
        }
Ejemplo n.º 3
0
        public void TestFarmList()
        {
            var farm = new FindFarmTargetsScenario(provider);
            BaseScenarioResult result = new BaseScenarioResult();

            Assert.DoesNotThrow(() =>
            {
                result = farm.Execute(new ScenarioContext {
                    Player = player
                });
            });


            var json = JsonConvert.SerializeObject(new
            {
                server   = player.Uri.AbsolutePath,
                farmList = result.Villages
            },
                                                   new JsonSerializerSettings
            {
                ContractResolver = new CamelCasePropertyNamesContractResolver()
            });

            var path = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "data\\farm.json");

            using (var writer = File.CreateText(path))
            {
                writer.Write(json);
            }
        }
Ejemplo n.º 4
0
        private async Task <BaseScenarioResult> RunScenario(IScenario scenario, ScenarioContext context)
        {
            BaseScenarioResult result;

            try
            {
                result = await Task.Run(() => this._scenarioExecutor.ExecuteScenario(scenario, context));

                result.Success = !result.Errors.Any();
            }
            catch (Exception exc)
            {
                result = new BaseScenarioResult();
                result.Errors.Add(new ScenarioError
                {
                    ErrorMessage = $"Unable to execute scenario. Error code: {LoggingEvents.ScenarioException}",
                    ErrorSource  = $"{this.GetType().Name}::{MethodBase.GetCurrentMethod().Name}",
                    ErrorType    = "Critical"
                });

                this._logger.LogError(LoggingEvents.ScenarioException, exc, exc.Message);
            }

            return(result);
        }
Ejemplo n.º 5
0
        protected override BaseScenarioResult ExecuteVillageActions(ScenarioContext context)
        {
            var result  = new BaseScenarioResult();
            var village = GetVillageInfoScenario.UpdateInfo(_driver, _action.Village);

            village = CommonScenario.UpdateResources(_driver, context, _action.Village);
            result.Villages.Add(village);
            return(result);
        }
Ejemplo n.º 6
0
        public Task <BaseScenarioResult> RunUpdateUserInfo(TravianUser user)
        {
            var player = _mapper.Map <Player>(user);
            var result = new BaseScenarioResult
            {
                Player = player
            };

            return(Task.FromResult(result));
        }
Ejemplo n.º 7
0
        public Task <BaseScenarioResult> ExecuteActions <T>(TravianUser user, IEnumerable <T> actions) where T : GameAction
        {
            var player = _mapper.Map <Player>(user);
            var result = new BaseScenarioResult
            {
                Player = player
            };

            return(Task.FromResult(result));
        }
Ejemplo n.º 8
0
        public async Task TestWatchScenario()
        {
            var factory  = new ScenarioFactory(provider);
            var executor = new ScenarioExecutor();
            var api      = new GameplayApi(executor, factory, logger.Object);

            BaseScenarioResult result = await api.Watch(player);

            Assert.IsTrue(result.IsUserUnderAttack);
            Assert.IsTrue(result.Success);
        }
Ejemplo n.º 9
0
        public async Task TestCheckReportsScenario()
        {
            var factory  = new ScenarioFactory(provider);
            var executor = new ScenarioExecutor();
            var api      = new GameplayApi(executor, factory, logger.Object);

            BaseScenarioResult result = await api.Watch(player);

            Assert.IsTrue(result.IsUserUnderAttack);
            Assert.IsTrue(result.Success);
            Assert.AreEqual("No scan events found", result.Messages.FirstOrDefault());
        }
Ejemplo n.º 10
0
        public async Task TestIncomingAttackScenario()
        {
            var factory  = new ScenarioFactory(provider);
            var executor = new ScenarioExecutor();
            var api      = new GameplayApi(executor, factory, logger.Object);

            BaseScenarioResult result = await api.Scan(player, false);

            Assert.IsTrue(result.IsUserUnderAttack);
            Assert.IsTrue(result.Villages.Count > 0);
            Assert.IsNotNull(result.Villages.FirstOrDefault());
            Assert.IsTrue(result.Villages.FirstOrDefault().IsUnderAttack);
            Assert.IsTrue(result.Villages.FirstOrDefault().Attacks.Any());
        }
Ejemplo n.º 11
0
        protected sealed override BaseScenarioResult ExecuteScenario(ScenarioContext context)
        {
            var result       = new BaseScenarioResult();
            var villagesList = this._driver.FindElements(By.CssSelector("#sidebarBoxVillagelist .content ul li a"));

            Dictionary <string, Village> villagesLinks = new Dictionary <string, Village>();

            foreach (var v in villagesList)
            {
                var name    = v.FindElement(By.CssSelector("span.name")).Text;
                var village = new Village
                {
                    Name       = name,
                    PlayerName = context.Player.UserName
                };

                var xText    = v.FindElement(By.ClassName("coordinateX")).Text;
                var yText    = v.FindElement(By.ClassName("coordinateY")).Text;
                var successX = int.TryParse(Decode(xText), out int x);
                var successY = int.TryParse(Decode(yText), out int y);
                if (successX && successY)
                {
                    village.CoordinateX = x;
                    village.CoordinateY = y;
                }
                else
                {
                    result.Errors.Add(new ScenarioError
                    {
                        ErrorSource  = nameof(CommonScenario),
                        ErrorMessage = $"Unable to parse coordinates for village {name}. Input values: x = [{xText}], y = [{yText}]",
                        ErrorType    = "UpdateInfo"
                    });
                }

                villagesLinks.Add(v.GetAttribute("href"), village);
            }

            foreach (var link in villagesLinks)
            {
                this._driver.Navigate().GoToUrl(link.Key);
                var villageResult = this.ExecuteInVillage(context, link.Value);
                villageResult = UpdateResources(_driver, context, villageResult);
                result.Villages.Add(villageResult);
            }

            result.IsUserUnderAttack = result.Villages.Any(x => x.IsUnderAttack || x.Attacks.Any());
            return(result);
        }
Ejemplo n.º 12
0
        protected override BaseScenarioResult ExecuteScenario(ScenarioContext context)
        {
            var result     = new BaseScenarioResult();
            var newReports = this._driver.FindElements(By.CssSelector("#n5.reports div.speechBubbleContainer"));

            if (newReports.Any())
            {
                this._driver.Navigate().GoToUrl(new Uri(context.Player.Uri, "/berichte.php?t=3&opt=AAATABIA"));
                var reportsForm = this._driver.FindElement(By.Id("reportsForm"));
                var anchors     = reportsForm.FindElements(By.CssSelector("table tbody tr td.sub.newMessage div a"));
                var links       = new List <string>();

                foreach (var anchor in anchors)
                {
                    links.Add(anchor.GetAttribute("href"));
                }

                foreach (var link in links)
                {
                    this._driver.Navigate().GoToUrl(link);
                    var villageElem     = this._driver.FindElement(By.CssSelector("#reportWrapper div.role.attacker div.troopHeadline a.village"));
                    var userVillageElem = this._driver.FindElement(By.CssSelector("#reportWrapper div.role.defender div.troopHeadline a.village"));
                    var timeElem        = this._driver.FindElement(By.CssSelector("#reportWrapper div.time div.text"));
                    var villageName     = userVillageElem.Text;
                    var villageUrl      = villageElem.GetAttribute("href");

                    var scan = new Incoming
                    {
                        VillageName        = villageName,
                        DateTime           = timeElem.Text.ToDateTimeOffset(),
                        IntruderVillageUrl = villageUrl
                    };

                    result.Scans.Add(scan);
                }

                foreach (var scan in result.Scans)
                {
                    scan.IntruderDetails = ParseVillageDetailsFromUrl(scan.IntruderVillageUrl);
                }
            }

            if (!result.Scans.Any())
            {
                result.Messages.Add("No scan events found");
            }

            return(result);
        }
Ejemplo n.º 13
0
        public void TestParseMessageScenario()
        {
            const string       messageUrl = "https://ts2.travian.ru/messages.php?t=0&order=DESC&page=1&id=303073";
            var                parse      = new ParseSpamTargetsScenario(provider);
            BaseScenarioResult result     = new BaseScenarioResult();

            Assert.DoesNotThrow(() =>
            {
                result = parse.Execute(new ScenarioContext {
                    Player = player, StartUrl = messageUrl
                });
            });

            Assert.NotNull(result.Villages);
            Assert.AreEqual(3, result.Villages.Count);
            Assert.AreEqual(-46, result.Villages.First().CoordinateX);
            Assert.AreEqual(33, result.Villages.First().CoordinateY);
        }
Ejemplo n.º 14
0
        protected override BaseScenarioResult ExecuteVillageActions(ScenarioContext context)
        {
            var result = new BaseScenarioResult();

            this._driver.Navigate().GoToUrl(new Uri(context.Player.Uri + "/dorf2.php"));
            // open market (g17)
            this._driver.FindElement(By.CssSelector("#village_map .g17 .level")).Click();
            var send = this._driver.Url + "&t=5";

            this._driver.Navigate().GoToUrl(send);

            int tradersAvailable    = int.Parse(Decode(this._driver.FindElement(By.CssSelector(".merchantsAvailable")).Text));
            int maxCarryingCapacity = int.Parse(this._driver.FindElement(By.Id("addRessourcesLink1")).Text);

            //int toSend = tradersAvailable * maxCarryingCapacity / 4;

            //var inputs = this._driver.FindElements(By.CssSelector("#send_select .val input"));

            //// TODO: distinguish the input fields and send resources from action property
            //foreach (var input in inputs)
            //{
            //    input.SendKeys(toSend.ToString());
            //}

            _driver.FindElement(By.Id("r1")).SendKeys(_action.Resources.Lumber.ToString());
            _driver.FindElement(By.Id("r2")).SendKeys(_action.Resources.Clay.ToString());
            _driver.FindElement(By.Id("r3")).SendKeys(_action.Resources.Iron.ToString());
            _driver.FindElement(By.Id("r4")).SendKeys(_action.Resources.Crop.ToString());

            this._driver.FindElement(By.Id("xCoordInput")).SendKeys(_action.To.CoordinateX.ToString());
            this._driver.FindElement(By.Id("yCoordInput")).SendKeys(_action.To.CoordinateY.ToString());

            // prepare
            this._driver.FindElement(By.Id("enabledButton")).Click();

            // TODO: add error if can't send

            // send
            this._driver.FindElement(By.Id("enabledButton")).Click();
            result.Messages.Add($"Resources were sent from {_action.Village.Name} to {_action.To.Name}");

            return(result);
        }
Ejemplo n.º 15
0
        public void UpdateVillageDataTest()
        {
            var village = new Village
            {
                Name = "Unexpected_Town_15"
            };

            var scenario = new GetVillageInfoScenario(provider);
            BaseScenarioResult result = new BaseScenarioResult();

            Assert.DoesNotThrow(() =>
            {
                result = scenario.Execute(new ScenarioContext {
                    Player = player, Actions = new List <BuildAction>()
                });
            });

            Assert.NotNull(result.Villages);
        }
Ejemplo n.º 16
0
        public BaseScenarioResult Execute(ScenarioContext context)
        {
            var result = new BaseScenarioResult();

            _driver.Navigate().GoToUrl(new Uri(context.Player.Uri, "/dorf1.php"));
            _driver.Manage().Window.Maximize();
            if (_driver.Url.Contains("login"))
            {
                var loginResult = Login(context);
                if (loginResult != null)
                {
                    return(loginResult);
                }
            }
            else
            {
                var playerNameElem = _driver.FindElement(By.ClassName("playerName"));
                var a = playerNameElem.FindElements(By.XPath($"//a[contains(text(), '{context.Player.UserName}')]"));
                if (a == null || !a.Any())
                {
                    var loginResult = Login(context);
                    if (loginResult != null)
                    {
                        return(loginResult);
                    }
                }
            }

            var dismissCookieNoticeElems = _driver.FindElements(By.Id("dismissCookieNotice"));

            if (dismissCookieNoticeElems.Any())
            {
                dismissCookieNoticeElems.First().Click();
            }

            result         = Proceed(context);
            result.Success = result.Errors.Count == 0;
            result.Cookies = _driver.Manage().Cookies.AllCookies.ToList();

            return(result);
        }
Ejemplo n.º 17
0
        protected override BaseScenarioResult ExecuteScenario(ScenarioContext context)
        {
            _driver.Navigate().GoToUrl(context.StartUrl);

            //var header = _driver.FindElement(By.CssSelector(".header.text")).Text.ToLower();
            //if (header.Contains("spam") || header.Contains("спам"))
            //{

            //}

            var targets = _driver.FindElements(By.CssSelector("#message a.bbCoordsLink")).Select(x => x.GetAttribute("href")).ToList();
            var result  = new BaseScenarioResult();

            foreach (var target in targets)
            {
                var village = ParseVillageDetailsFromUrl(target);
                result.Villages.Add(village);
            }

            return(result);
        }
Ejemplo n.º 18
0
        protected override BaseScenarioResult ExecuteScenario(ScenarioContext context)
        {
            var result = new BaseScenarioResult();

            this._driver.FindElement(By.CssSelector("#n3 a")).Click();
            var mapContainer = this._driver.FindElement(By.Id("mapContainer"));

            var action = new Actions(this._driver);
            int w      = mapContainer.Size.Width / 9;
            int h      = mapContainer.Size.Height / 7;
            int i      = 0;
            int j      = 1;

            action.MoveToElement(mapContainer)
            .MoveByOffset(-5 * w + w / 2, -4 * h + h / 2)
            .MoveByOffset(i * w + w / 2, j * h + h / 2)
            .Click()
            .Build()
            .Perform();

            return(result);
        }
Ejemplo n.º 19
0
        protected override BaseScenarioResult ExecuteVillageActions(ScenarioContext context)
        {
            this._driver.Navigate().GoToUrl(new Uri(context.Player.Uri, "/dorf2.php"));
            this._driver.FindElement(By.CssSelector("#village_map .g19 .level")).Click();
            var result = new BaseScenarioResult();

            foreach (var unit in this._action.UnitsToTrain)
            {
                var unitWrappers = this._driver.FindElements(By.XPath("//div[contains(@class, 'innerTroopWrapper') and .//a[text() = \'" + unit.Key + "\']]"));
                if (unitWrappers != null && unitWrappers.Any())
                {
                    if (unit.Value == (int)TrainArmyFlag.MAX)
                    {
                        var a = unitWrappers[0].FindElement(By.CssSelector("div.cta > a"));
                        a.Click();
                    }
                    else if (unit.Value > 0)
                    {
                        var input = unitWrappers[0].FindElement(By.CssSelector("input.text"));
                        input.SendKeys(unit.Value.ToString());
                    }

                    this._driver.FindElement(By.Id("s1")).Click();
                    result.Messages.Add($"Started to train {unit.Value} units of {unit.Key}");
                }
                else
                {
                    result.Errors.Add(new ScenarioError
                    {
                        ErrorMessage = $"Unable to find unit {unit.Key}",
                        ErrorSource  = nameof(TrainArmyScenario),
                        ErrorType    = "NotFound"
                    });
                }
            }

            return(result);
        }
Ejemplo n.º 20
0
        protected sealed override BaseScenarioResult ExecuteScenario(ScenarioContext context)
        {
            var result = new BaseScenarioResult();

            if (_action == null)
            {
                result.Errors.Add(new ScenarioError {
                    ErrorMessage = "No actions found in scenario context.", ErrorSource = nameof(VillageScenario <T>)
                });
                return(result);
            }

            var found        = false;
            var villagesList = _driver.FindElements(By.CssSelector("#sidebarBoxVillagelist .content ul li a"));

            foreach (var v in villagesList)
            {
                var name = v.FindElement(By.CssSelector("span.name")).Text;
                if (this._action.Village.Name == name)
                {
                    found = true;
                    v.Click();
                    break;
                }
            }

            if (!found)
            {
                result.Errors.Add(new ScenarioError {
                    ErrorMessage = $"Unable to find village {this._action.Village.Name}.", ErrorSource = nameof(VillageScenario <T>)
                });
                return(result);
            }

            return(this.ExecuteVillageActions(context));
        }
        protected override BaseScenarioResult ExecuteScenario(ScenarioContext context)
        {
            // open statistics
            _driver.FindElement(By.Id("n4")).Click();
            // go to last page
            _driver.FindElement(By.CssSelector("a.last")).Click();
            var result = new BaseScenarioResult();

            var maxPopulation = int.MaxValue;
            var targets       = new List <string>();

            while (targets.Count < Targets || maxPopulation > MaxPopulation)
            {
                var rows = GetRows(_driver.FindElement(By.CssSelector("table#player"))).OrderByDescending(x => x.rank)
                           .Where(x => x.population >= MinPopulation &&
                                  x.population <= MaxPopulation &&
                                  string.IsNullOrWhiteSpace(x.alliance) &&
                                  x.villages <= MaxVillages);

                if (rows.Any())
                {
                    maxPopulation = rows.Max(x => x.population);
                    targets.AddRange(rows.Select(x => x.url));
                }

                _driver.FindElement(By.CssSelector("a.previous")).Click();
            }

            foreach (var target in targets)
            {
                _driver.Navigate().GoToUrl(target);

                var playerName   = _driver.FindElement(By.CssSelector("#content h1.titleInHeader")).Text;
                var villagesList = _driver.FindElements(By.CssSelector("#villages tbody tr"));
                foreach (var v in villagesList)
                {
                    var name     = v.FindElement(By.CssSelector(".name a")).Text;
                    var capital  = v.FindElements(By.CssSelector(".name span"));
                    var xText    = v.FindElement(By.ClassName("coordinateX")).Text;
                    var yText    = v.FindElement(By.ClassName("coordinateY")).Text;
                    var successX = int.TryParse(Decode(xText), out int x);
                    var successY = int.TryParse(Decode(yText), out int y);

                    var village = new Village
                    {
                        Name       = name,
                        PlayerName = playerName,
                        IsCapital  = capital.Count > 0
                    };

                    if (successX && successY)
                    {
                        village.CoordinateX = x;
                        village.CoordinateY = y;
                    }
                    else
                    {
                        result.Errors.Add(new ScenarioError
                        {
                            ErrorSource  = nameof(CommonScenario),
                            ErrorMessage = $"Unable to parse coordinates for village {name}. Input values: x = [{xText}], y = [{yText}]",
                            ErrorType    = "UpdateInfo"
                        });
                    }

                    result.Villages.Add(village);
                }
            }

            return(result);
        }
Ejemplo n.º 22
0
        protected override BaseScenarioResult ExecuteVillageActions(ScenarioContext context)
        {
            var result  = new BaseScenarioResult();
            var windows = new List <string>();

            var uri = new Uri(context.Player.Uri + "/build.php?tt=2&id=39");

            for (int i = 0; i < _action.Waves; i++)
            {
                if (i > 0)
                {
                    OpenNewTab(uri.AbsoluteUri);
                    WaitUntilElementExists(By.Id("xCoordInput"));
                }
                else
                {
                    _driver.Navigate().GoToUrl(uri);
                }

                // go to army center tab 2 (send army)
                _driver.FindElement(By.Id("xCoordInput")).SendKeys(_action.To.CoordinateX.ToString());
                _driver.FindElement(By.Id("yCoordInput")).SendKeys(_action.To.CoordinateY.ToString());

                var options = _driver.FindElements(By.CssSelector("form div.option label"));
                if (options.Count != 3)
                {
                    result.Errors.Add(new ScenarioError
                    {
                        ErrorMessage = "Can't find options to send army",
                        ErrorSource  = nameof(SendArmyScenario)
                    });
                }
                else
                {
                    switch (_action.Type)
                    {
                    case SendArmyType.BACKUP:
                        options[0].Click();
                        break;

                    case SendArmyType.ATTACK:
                        options[1].Click();
                        break;

                    case SendArmyType.RAID:
                        options[2].Click();
                        break;

                    default:
                        throw new Exception("Unknown send army type");
                    }
                }

                var table = _driver.FindElement(By.Id("troops"));
                foreach (var units in _action.UnitsToSend)
                {
                    var tds = table.FindElements(By.XPath($"//td[img[@alt='{units.Key}']]"));
                    if (tds.Any())
                    {
                        var td = tds.First();
                        var a  = td.FindElements(By.TagName("a"));
                        if (!a.Any())
                        {
                            continue;
                        }

                        if (units.Value == -1)
                        {
                            td.FindElement(By.TagName("a")).Click();
                        }
                        else
                        {
                            td.FindElement(By.TagName("input")).SendKeys(units.Value.ToString());
                        }
                    }
                }

                _driver.FindElement(By.Id("btn_ok")).Click();
            }

            foreach (var w in _driver.WindowHandles)
            {
                _driver.SwitchTo().Window(w);
                _driver.FindElement(By.Id("btn_ok")).Click();
                result.Villages.Add(_action.To);
            }

            return(result);
        }
        private AbstractJob PrepareOneVillageTest(BaseScenarioResult buildScenarioResult, BaseScenarioResult infoScenarioResult)
        {
            var testVillage   = PrepareTestOneVillage(isBuildingFeatureOn: true);
            var resultVillage = _serviceProviderBuilder.Mapper.Map <Village>(testVillage);
            var finishTime    = TimeSpan.FromMinutes(30);

            resultVillage.Dorf1BuildTimeLeft = finishTime;
            resultVillage.CanBuild           = true;
            resultVillage.Resources          = new Resources
            {
                Lumber = 100,
                Clay   = 100,
                Iron   = 100,
                Crop   = 100
            };
            resultVillage.Warehourse = 800;
            resultVillage.Granary    = 800;

            var infoResult = Builder <BaseScenarioResult> .CreateNew()
                             .With(x => x.Success  = true)
                             .With(x => x.Villages = new List <Village> {
                resultVillage
            })
                             .Build();

            var actionProviderMock = new Mock <IActionProvider>();

            actionProviderMock.Setup(x => x.GetBuildActions(resultVillage, It.IsAny <IEnumerable <BuildingModel> >()))
            .Returns(Task.FromResult((true, (IEnumerable <BuildAction>) new List <BuildAction> {
                new BuildAction
                {
                    Village = resultVillage,
                    BuildingId = "test",
                    BuildingSlot = "test",
                    Level = 1
                }
            })));
            _serviceProviderBuilder.WithService(actionProviderMock.Object);

            var buildActionResult = Builder <BaseScenarioResult> .CreateNew()
                                    .With(x => x.Success  = true)
                                    .With(x => x.Villages = new List <Village>
            {
                Builder <Village>
                .CreateNew()
                .With(y => y.CanBuild           = false)
                .With(y => y.Dorf1BuildTimeLeft = TimeSpan.FromMinutes(5))
                .Build()
            })
                                    .Build();

            var gamePlayMock = new Mock <IGameplayClient>();

            gamePlayMock.Setup(x => x.ExecuteActions(It.IsAny <TravianUser>(), It.IsAny <IEnumerable <GameAction> >()))
            .Returns(Task.FromResult(infoResult));
            gamePlayMock.Setup(x => x.ExecuteActions(It.IsAny <TravianUser>(), It.IsAny <IEnumerable <BuildAction> >()))
            .Returns(Task.FromResult(buildActionResult));
            _serviceProviderBuilder.WithService(gamePlayMock.Object);

            var cmd     = new FakeCommand();
            var cmdMock = new Mock <ICommandFactory>();

            cmdMock.Setup(x => x.GetQueueableCommand(nameof(BuildCommand), It.IsAny <long>()))
            .Returns(cmd);
            _serviceProviderBuilder.WithService(cmdMock.Object);

            var job  = new BuildingPlanExecutionJob(_serviceProviderBuilder.Build());
            var data = new JobExecutionData
            {
                TravianUser = FakeDataProvider.GetUser(PlayerStatus.ALL_QUIET, true),
                JobType     = typeof(BuildingPlanExecutionJob)
            };

            return(job);
        }
        protected override BaseScenarioResult ExecuteScenario(ScenarioContext context)
        {
            var result = new BaseScenarioResult();

            this._driver.Navigate().GoToUrl(new Uri(context.Player.Uri, "/spieler.php"));
            var villagesList = _driver.FindElements(By.CssSelector("#villages tbody tr"));

            var details = new List <Village>();

            foreach (var v in villagesList)
            {
                var name     = v.FindElement(By.CssSelector(".name a")).Text;
                var capital  = v.FindElements(By.CssSelector(".name span"));
                var xText    = v.FindElement(By.ClassName("coordinateX")).Text;
                var yText    = v.FindElement(By.ClassName("coordinateY")).Text;
                var successX = int.TryParse(Decode(xText), out int x);
                var successY = int.TryParse(Decode(yText), out int y);

                var village = new Village
                {
                    Name       = name,
                    PlayerName = context.Player.UserName,
                    IsCapital  = capital.Count > 0
                };

                if (successX && successY)
                {
                    village.CoordinateX = x;
                    village.CoordinateY = y;
                }
                else
                {
                    result.Errors.Add(new ScenarioError
                    {
                        ErrorSource  = nameof(CommonScenario),
                        ErrorMessage = $"Unable to parse coordinates for village {name}. Input values: x = [{xText}], y = [{yText}]",
                        ErrorType    = "UpdateInfo"
                    });
                }

                details.Add(village);
            }

            result.Villages = details;


            this._driver.Navigate().GoToUrl(new Uri(context.Player.Uri, "/dorf2.php"));
            var player    = context.Player;
            var buildings = this._driver.FindElements(By.CssSelector(".buildingSlot"));

            if (buildings != null && buildings.Any())
            {
                var building = buildings[0];
                var classes  = building.GetAttribute("class").Split(" ");
                var folk     = classes[classes.Length - 1];
                folk = folk.ToUpperInvariant();
                if (Enum.TryParse(folk, out Tribe tribe))
                {
                    player.Tribe = tribe;
                }
                else
                {
                    result.Errors.Add(new ScenarioError
                    {
                        ErrorMessage = $"Unable to parse the Tribe: {folk}",
                        ErrorSource  = nameof(UpdateUserInfoScenario)
                    });
                }
            }
            else
            {
                result.Errors.Add(new ScenarioError
                {
                    ErrorMessage = "Unable to find any building to update the Tribe",
                    ErrorSource  = nameof(UpdateUserInfoScenario)
                });
            }

            this._driver.Navigate().GoToUrl(new Uri(context.Player.Uri, "/options.php"));
            var timeZoneId = this._driver.FindElement(By.XPath("//select[@name='timezone']//option[@selected='selected']"))?.Text;

            if (string.IsNullOrEmpty(timeZoneId))
            {
                result.Errors.Add(new ScenarioError
                {
                    ErrorMessage = "Unable to find time zone id",
                    ErrorSource  = nameof(UpdateUserInfoScenario)
                });
            }
            else
            {
                player.TimeZone = timeZoneId;
            }

            var allianceElems = _driver.FindElements(By.XPath("//a[contains(@href, 'allianz.php')]"));

            if (allianceElems.Any())
            {
                player.Alliance = allianceElems.First().Text;
            }

            result.Player = player;
            return(result);
        }
Ejemplo n.º 25
0
        private bool TryBuildNewBuilding(ref BaseScenarioResult result)
        {
            var         slotQuery = string.IsNullOrWhiteSpace(_action.BuildingSlot) ? string.Empty : $" and contains(@class, '{_action.BuildingSlot}')";
            var         wrapper   = _driver.FindElements(By.XPath($"//div[@id='village_map']/div[contains(@class, 'g0') {slotQuery}]"))?.FirstOrDefault();
            IWebElement contract  = null;

            if (wrapper == null)
            {
                result.Errors.Add(new ScenarioError
                {
                    ErrorMessage = $"Unable to find building building id: {_action.BuildingId}, slot: {_action.BuildingSlot}",
                    ErrorSource  = nameof(BuildScenario)
                });
                return(false);
            }

            var field = wrapper.FindElements(By.CssSelector("svg g.clickShape path"))?.FirstOrDefault();

            if (field == null)
            {
                result.Errors.Add(new ScenarioError
                {
                    ErrorMessage = $"Unable to find building building id: {_action.BuildingId}, slot: {_action.BuildingSlot}",
                    ErrorSource  = nameof(BuildScenario)
                });
                return(false);
            }

            var script = field.GetAttribute("onclick");

            _driver.ExecuteJavaScript <object>(script);
            //field.Click();
            var id        = _action.BuildingId.Replace("g", string.Empty);
            var container = WaitUntilElementExists(_driver, By.CssSelector("div.contentNavi.subNavi.tabWrapper .scrollingContainer"), 5);

            var nav = container.FindElements(By.CssSelector("div.content a"));

            if (nav == null || nav.Count != 3)
            {
                result.Errors.Add(new ScenarioError
                {
                    ErrorMessage = $"Unable build new building with id: {_action.BuildingId}, slot: {_action.BuildingSlot}. Unable to locate navigation on new buildings page.",
                    ErrorSource  = nameof(BuildScenario)
                });
                return(false);
            }

            var links = nav.Select(x => x.GetAttribute("href")).ToList();

            for (int i = 0; i < links.Count && contract == null; i++)
            {
                _driver.Navigate().GoToUrl(links[i]);
                contract = _driver.FindElements(By.Id($"contract_building{id}"))?.FirstOrDefault();
            }

            if (contract == null)
            {
                result.Errors.Add(new ScenarioError
                {
                    ErrorMessage = $"Unable build new building with id: {_action.BuildingId}, slot: {_action.BuildingSlot}. Unable to locate navigation on new buildings page.",
                    ErrorSource  = nameof(BuildScenario)
                });
                return(false);
            }

            var btn = contract.FindElements(By.CssSelector("div.contractLink button.green"))?.FirstOrDefault();

            if (btn == null)
            {
                var errors       = contract.FindElements(By.CssSelector("span.buildingCondition.error"));
                var errorsResult = new List <ScenarioError>();
                foreach (var error in errors)
                {
                    var condition = $"{error.FindElement(By.TagName("a")).Text} {error.FindElement(By.TagName("span")).Text}";
                    errorsResult.Add(new ScenarioError
                    {
                        ErrorMessage = $"Unable build new building with id: {_action.BuildingId}, slot: {_action.BuildingSlot}. Conditions not met: {condition}",
                        ErrorSource  = nameof(BuildScenario)
                    });
                }

                result.Errors.AddRange(errorsResult);
                return(false);
            }

            btn.Click();
            return(true);
        }
Ejemplo n.º 26
0
        private async Task WasUnderAttackScenario(BaseScenarioResult result)
        {
            if (result.Errors.Any())
            {
                await _bot.SendTextMessageAsync(
                    _botUser.ChatId,
                    string.Join(", ", result.Errors));

                return;
            }

            var currentVillagesData = await _villageRepository.GetVillages(_travianUser.UserName);

            var update  = result.Villages.Select(x => _mapper.Map <VillageModel>(x));
            var attacks = result.Villages
                          .Where(x => x.Attacks != null)
                          .SelectMany(x => x.Attacks)
                          .Select(x => _mapper.Map <AttackModel>(x))
                          .OrderBy(x => x.DateTime)
                          .ToList();

            if (attacks != null && attacks.Any())
            {
                var resultVillages = result.Villages.Select(x => _mapper.Map <VillageModel>(x));
                var newAttacks     = GetNewAttacks(resultVillages, currentVillagesData).ToList();
                if (newAttacks.Any())
                {
                    await _bot.SendTextMessageAsync(
                        _botUser.ChatId,
                        $"New incoming attacks discovered for player [{_travianUser.UserName}]");

                    try
                    {
                        foreach (var newAttack in newAttacks)
                        {
                            var msg = ArmyEventReportBuilder
                                      .ForVillage(newAttack.VillageName, _travianUser.PlayerData.TimeZone)
                                      .WithNotification(newAttack)
                                      .ReportText;

                            await _bot.SendTextMessageAsync(
                                _botUser.ChatId,
                                msg);
                        }

                        await _villageRepository.UpdateWatchInfo(update);

                        foreach (var newAttack in newAttacks)
                        {
                            var cmd      = _commandFactory.GetQueueableCommand(nameof(PrepareToAttackCommand), _botUser.ChatId);
                            var attackDt = newAttack.DateTime;
                            var diff     = TimeSpan.FromMinutes(5);
                            cmd.Start = attackDt - DateTimeOffset.UtcNow > diff ? attackDt - diff : DateTimeOffset.UtcNow;
                            await cmd.Execute();
                        }
                    }
                    catch (Exception exc)
                    {
                        await _bot.SendTextMessageAsync(
                            _botUser.ChatId,
                            $"Unable to find or update army events for travian user [{_travianUser.UserName}]. Error code: [{LoggingEvents.DbOpertationException}]");

                        _logger.LogError(LoggingEvents.DbOpertationException, exc, $"BotUserName:[{_botUser.UserName}], TravianUserName:[{_travianUser.UserName}], error: {exc.Message}");
                    }
                }
                else
                {
                    await _villageRepository.UpdateWatchInfo(update);
                }
            }
            else
            {
                await _villageRepository.UpdateWatchInfo(update);

                _travianUser.PlayerData.Status = PlayerStatus.ALL_QUIET;
            }
        }
Ejemplo n.º 27
0
        private async Task <bool> WasQuietScenario(BaseScenarioResult result)
        {
            if (result.IsUserUnderAttack)
            {
                try
                {
                    var scans = result.Scans;

                    if (scans.Any())
                    {
                        foreach (var scan in scans)
                        {
                            var scanReport = ScanReportBuilder
                                             .Create(_travianUser.UserName, _travianUser.PlayerData.TimeZone)
                                             .WithNotification(scan)
                                             .ReportText;

                            await _bot.SendTextMessageAsync(
                                _botUser.ChatId,
                                scanReport);
                        }

                        _travianUser.PlayerData.Status = PlayerStatus.WAS_SCANNED;
                    }
                    else
                    {
                        _travianUser.PlayerData.Status = PlayerStatus.ALL_QUIET;
                    }

                    if (result.IsUserUnderAttack)
                    {
                        var attacks = result.Villages
                                      .SelectMany(x => x.Attacks)
                                      .OrderBy(x => x.DateTime)
                                      .ToList();
                        foreach (var attack in attacks)
                        {
                            var report = IncomingAttackReportBuilder.Create(_travianUser.UserName, _travianUser.PlayerData.TimeZone);
                            report = report.WithNotification(attack);
                            await _bot.SendTextMessageAsync(
                                _botUser.ChatId,
                                report.ReportText);
                        }

                        _travianUser.PlayerData.Status = PlayerStatus.UNDER_ATTACK;
                    }
                }
                catch (Exception exc)
                {
                    await _bot.SendTextMessageAsync(
                        _botUser.ChatId,
                        $"Unable to find any notification for travian user [{_travianUser.UserName}]. Error code: [{12}]");

                    _logger.LogError(12, $"BotUserName:[{_botUser.UserName}], TravianUserName:[{_travianUser.UserName}] " +
                                     $"{exc.Message}: \r\n {exc.StackTrace}");
                }
            }

            if (!result.Success)
            {
                await _bot.SendTextMessageAsync(
                    _botUser.ChatId,
                    string.Join(", ", result.Errors));
            }

            return(result.IsUserUnderAttack);
        }
        protected override async Task ExecuteJob(JobExecutionData jobExecutionData)
        {
            var allVillages = await _villageRepository.GetVillages(_travianUser.UserName);

            var buildVillages = allVillages
                                .Where(x => x.IsBuildFeatureOn)
                                .ToList();

            if (!buildVillages.Any())
            {
                await _bot.SendTextMessageAsync(_botUser.ChatId, $"No villages with build feature found for player {_travianUser.UserName}");

                return;
            }

            foreach (var village in buildVillages.Where(x => x.IsWaitingForResources))
            {
                // for villages waiting for resources next execution time is the time when resources must be delivered
                // if next execution time passed resources are expected to be delivered
                village.IsWaitingForResources = village.NextBuildingPlanExecutionTime.HasValue && village.NextBuildingPlanExecutionTime.Value > DateTimeOffset.Now;
            }

            BaseScenarioResult infos = null;

            try
            {
                var updateActions = buildVillages
                                    .Select(x => new GameAction {
                    Village = _mapper.Map <Village>(x)
                });
                infos = await _gameplayClient.ExecuteActions(_travianUser, updateActions);

                var update = infos.Villages.Select(x => _mapper.Map <VillageModel>(x));
                await _villageRepository.UpdateWatchInfo(update);
            }
            catch (Exception exc)
            {
                _logger.LogError(exc, exc.Message);
                await _bot.SendTextMessageAsync(_botUser.ChatId, $"Unable to update villages info for player {_travianUser.UserName}");

                return;
            }

            if (!infos?.Villages?.Any() ?? true)
            {
                await _bot.SendTextMessageAsync(_botUser.ChatId, $"No info was found for villages of {_travianUser.UserName}");

                return;
            }

            // suits only for rome or for player with travian plus. TODO: fix for other tribes
            var freeVillages = infos.Villages
                               .Where(x => x.CanBuild)
                               .ToList();

            var busyVillages = infos.Villages
                               .Where(x => !x.CanBuild)
                               .ToList();

            if (busyVillages?.Any() ?? false)
            {
                foreach (var village in busyVillages)
                {
                    // if village has less than 10% filled warehouse we should send there more resources
                    var limit = village.Warehourse * 0.1;
                    if (!village.Dorf1BuildTimeLeft.HasValue || village.Resources.Lumber < limit || village.Resources.Clay < limit ||
                        village.Resources.Iron < limit || village.Resources.Crop < village.Granary * 0.1)
                    {
                        await SendResources(allVillages.ToList(), village);
                    }
                }
            }

            var result = new BaseScenarioResult();

            if (!freeVillages?.Any() ?? true)
            {
                await _bot.SendTextMessageAsync(_botUser.ChatId, $"All villages with building feature of player {_travianUser.UserName} are busy.");

                await _bot.SendTextMessageAsync(_botUser.ChatId, $"Calculating next build command execution time for player {_travianUser.UserName}.");
            }
            else
            {
                var i            = 0;
                var allBuidlgins = await _buildingRepository.GetAllBuildings();

                while ((freeVillages?.Any() ?? false) && i++ < buildVillages.Count)
                {
                    var allActions = new List <BuildAction>();
                    foreach (var village in freeVillages)
                    {
                        var(hasMoreToBuild, actions) = await _actionProvider.GetBuildActions(village, allBuidlgins);

                        if (!hasMoreToBuild)
                        {
                            await _bot.SendTextMessageAsync(_botUser.ChatId, $"No actions needed for village {village.Name} of player {village.PlayerName}. Swithching off the Build Feature.");

                            try
                            {
                                var villageToUpdate = await _villageRepository.GetVillage(village.CoordinateX, village.CoordinateY);

                                villageToUpdate.IsBuildFeatureOn = false;
                                await _villageRepository.UpdateInfos(new List <VillageModel> {
                                    villageToUpdate
                                });
                            }
                            catch (Exception exc)
                            {
                                _logger.LogError(exc, exc.Message);
                                await _bot.SendTextMessageAsync(_botUser.ChatId, $"Unable to update {village.Name} of player {village.PlayerName}. Check Logs.");
                            }
                        }
                        else
                        {
                            allActions.AddRange(actions);
                        }
                    }

                    if (allActions.Any())
                    {
                        result = await _gameplayClient.ExecuteActions(_travianUser, allActions);

                        var buildErrors = result.Errors
                                          .Where(x => x is BuildScenarioError)
                                          .Cast <BuildScenarioError>();
                        if (buildErrors.Any())
                        {
                            var notEnoughRes = buildErrors
                                               .Where(x => (x as BuildScenarioError).BuildErrorType == BuildErrorType.NotEnoughResources);
                            if (notEnoughRes.Any())
                            {
                                foreach (var n in notEnoughRes)
                                {
                                    var updatedVillage = result.Villages.First(x => x.CoordinateX == n.Village.CoordinateX && x.CoordinateY == n.Village.CoordinateY);
                                    await SendResources(allVillages.ToList(), updatedVillage);
                                }
                            }

                            var noSpaceInQueue = buildErrors
                                                 .Where(x => (x as BuildScenarioError).BuildErrorType == BuildErrorType.NoSpaceInQueue);
                            if (noSpaceInQueue.Any())
                            {
                                foreach (var n in noSpaceInQueue)
                                {
                                    var errorVillage = result.Villages.First(x => x.CoordinateX == n.Village.CoordinateX && x.CoordinateY == n.Village.CoordinateY);
                                    errorVillage.CanBuild = false;
                                }
                            }
                        }

                        freeVillages = result.Villages.Where(x => x.CanBuild).ToList();
                    }
                }
            }

            var      max     = infos.Villages.Count > result.Villages.Count ? infos.Villages.Count : result.Villages.Count;
            TimeSpan nextRun = TimeSpan.MaxValue;

            for (var j = 0; j < max; j++)
            {
                if (j < infos.Villages.Count)
                {
                    if (infos.Villages[j].Dorf1BuildTimeLeft.HasValue &&
                        infos.Villages[j].Dorf1BuildTimeLeft.Value > TimeSpan.Zero &&
                        infos.Villages[j].Dorf1BuildTimeLeft.Value < nextRun)
                    {
                        nextRun = infos.Villages[j].Dorf1BuildTimeLeft.Value;
                    }
                }
                if (j < result.Villages.Count)
                {
                    if (result.Villages[j].Dorf1BuildTimeLeft.HasValue &&
                        result.Villages[j].Dorf1BuildTimeLeft.Value > TimeSpan.Zero &&
                        result.Villages[j].Dorf1BuildTimeLeft.Value < nextRun)
                    {
                        nextRun = result.Villages[j].Dorf1BuildTimeLeft.Value;
                    }
                }
            }

            if (nextRun < TimeSpan.MaxValue)
            {
                var waitingForResources = buildVillages
                                          ?.Where(x => x.IsWaitingForResources && x.NextBuildingPlanExecutionTime.HasValue)
                                          ?.Select(x => x.NextBuildingPlanExecutionTime.Value)
                                          ?.ToList();

                var nextRunDateTime          = DateTimeOffset.Now + nextRun;
                var nearestResourcesDelivery = (waitingForResources?.Any() ?? false) ? waitingForResources.Min() : DateTimeOffset.MaxValue;

                var cmd = _commandFactory.GetQueueableCommand(nameof(BuildCommand), _botUser.ChatId);
                cmd.Start = (nextRunDateTime < nearestResourcesDelivery ? nextRunDateTime : nearestResourcesDelivery) + TimeSpan.FromSeconds(2);
                await cmd.Execute();
            }
            else
            {
                await _bot.SendTextMessageAsync(_botUser.ChatId, $"Unable to calculate next build command execution time for player {_travianUser.UserName}");
            }
        }
Ejemplo n.º 29
0
        protected override BaseScenarioResult ExecuteVillageActions(ScenarioContext context)
        {
            var result = new BaseScenarioResult();

            if (_action.To.Name == "send_to_any_natar")
            {
                this._driver.Navigate().GoToUrl(new Uri(context.Player.Uri + "/build.php?tt=99&id=39"));
                var natarRows = _driver.FindElements(By.XPath($"//tr[./td[@class='village' and ./a[text()[contains(., 'Натары')]]]]")).ToList();
                var min       = natarRows.OrderBy(x => double.Parse(x.FindElement(By.ClassName("distance")).Text)).FirstOrDefault();

                var natars = min.FindElements(By.TagName("a")); // "//tr[//a[contains(text(), 'Натары')]]"
                if (natars.Any())
                {
                    natars.First().Click();
                    this._driver.FindElement(By.XPath("//a[contains(text(), 'Отправить войска')]")).Click();
                }
            }
            else
            {
                // go to army center tab 2 (send army)
                this._driver.Navigate().GoToUrl(new Uri(context.Player.Uri + "/build.php?tt=2&id=39"));
                _driver.FindElement(By.Id("xCoordInput")).SendKeys(_action.To.CoordinateX.ToString());
                _driver.FindElement(By.Id("yCoordInput")).SendKeys(_action.To.CoordinateY.ToString());
            }

            var options = _driver.FindElements(By.CssSelector("form div.option label"));

            if (options.Count != 3)
            {
                result.Errors.Add(new ScenarioError
                {
                    ErrorMessage = "Can't find options to send army",
                    ErrorSource  = nameof(SendArmyScenario)
                });
            }
            else
            {
                switch (_action.Type)
                {
                case SendArmyType.BACKUP:
                    options[0].Click();
                    break;

                case SendArmyType.ATTACK:
                    options[1].Click();
                    break;

                case SendArmyType.RAID:
                    options[2].Click();
                    break;

                default:
                    throw new Exception("Unknown send army type");
                }
            }

            if (_action.SendAll)
            {
                var links = _driver.FindElements(By.CssSelector("table#troops td a"));
                foreach (var l in links)
                {
                    l.Click();
                }
            }
            else
            {
                var table = _driver.FindElement(By.Id("troops"));
                foreach (var units in _action.UnitsToSend)
                {
                    var tds = table.FindElements(By.XPath($"//td[img[@alt='{units.Key}']]"));
                    if (tds.Any())
                    {
                        var td = tds.First();
                        var a  = td.FindElements(By.TagName("a"));
                        if (!a.Any())
                        {
                            continue;
                        }

                        if (units.Value == -1)
                        {
                            td.FindElement(By.TagName("a")).Click();
                        }
                        else
                        {
                            td.FindElement(By.TagName("input")).SendKeys(units.Value.ToString());
                        }
                    }
                }
            }

            // send
            _driver.FindElement(By.Id("btn_ok")).Click();

            // if no troops choosen
            var errors = _driver.FindElements(By.ClassName("error"));

            if (errors.Any())
            {
                result.Errors.Add(new ScenarioError
                {
                    ErrorMessage = "no troops choosen",
                    ErrorSource  = nameof(SendArmyScenario)
                });
            }
            else
            {
                // confirm
                _driver.FindElement(By.Id("btn_ok")).Click();
                result.Villages.Add(_action.To);
            }
            return(result);
        }
Ejemplo n.º 30
0
        protected override BaseScenarioResult ExecuteVillageActions(ScenarioContext context)
        {
            var result = new BaseScenarioResult();

            _driver.FindElement(By.CssSelector("#navigation > .village.resourceView")).Click();
            var field = _driver.FindElements(By.XPath($"//div[@id='resourceFieldContainer']/div[contains(@class, '{_action.BuildingId}') and contains(@class, '{_action.BuildingSlot}')]"))?.FirstOrDefault();

            if (field == null)
            {
                _driver.FindElement(By.CssSelector("#navigation > .village.buildingView")).Click();
                field = _driver.FindElements(By.XPath($"//div[@id='village_map']/div[contains(@class, '{_action.BuildingId}') and contains(@class, '{_action.BuildingSlot}')]/div"))?.FirstOrDefault();
                if (field == null)
                {
                    if (TryBuildNewBuilding(ref result))
                    {
                        return(result);
                    }
                    else
                    {
                        result.Errors.Add(new ScenarioError
                        {
                            ErrorMessage = $"Unable to build new building.Building Id: {_action.BuildingId}, building slot: {_action.BuildingSlot}",
                            ErrorType    = "NEW_BUILDING_FAILED"
                        });

                        return(result);
                    }
                }
            }

            var css = field.GetAttribute("class");

            if (css.Contains("good", StringComparison.OrdinalIgnoreCase))
            {
                field.Click();
                var btn = _driver.FindElements(By.CssSelector("div.upgradeButtonsContainer .section1 button.green"));
                if (btn.Any())
                {
                    btn.First().Click();
                }
            }
            else if (css.Contains("notNow", StringComparison.OrdinalIgnoreCase))
            {
                field.Click();

                var contract = _driver.FindElements(By.Id("contract"))?.FirstOrDefault();
                if (contract == null)
                {
                    result.Errors.Add(new ScenarioError
                    {
                        ErrorMessage = $"Unable build new building with id: {_action.BuildingId}, slot: {_action.BuildingSlot}. Unable to locate contract.",
                        ErrorSource  = nameof(BuildScenario)
                    });
                    return(result);
                }

                var blocked    = _driver.FindElements(By.CssSelector("div.upgradeBlocked"))?.FirstOrDefault();
                var blockCause = BuildErrorType.NoSpaceInQueue;
                if (blocked != null)
                {
                    if (blocked?.FindElements(By.CssSelector("div.errorMessage"))?.Any() ?? false)
                    {
                        blockCause = BuildErrorType.NotEnoughResources;
                    }
                }
                else
                {
                    field.Click();
                    var btn = _driver.FindElements(By.CssSelector("div.upgradeButtonsContainer.section2Enabled .section1 button.green"));
                    if (btn.Any())
                    {
                        btn.First().Click();
                        return(result);
                    }
                }

                var error = new BuildScenarioError
                {
                    BuildErrorType = blockCause,
                    Village        = _action.Village
                };

                if (blockCause == BuildErrorType.NotEnoughResources)
                {
                    var resources = GetResourcesOnWarehouse(_driver);
                    var contracts = _driver.FindElements(By.CssSelector("#contract div.resource span.value")).Select(x => int.Parse(x.Text.RemoveNonAsciiCharacters())).ToList();
                    if (contracts.Count != 5)
                    {
                        result.Errors.Add(new ScenarioError
                        {
                            ErrorMessage = $"Unable to find resources from contract for building building id: {_action.BuildingId}, slot: {_action.BuildingSlot}",
                            ErrorSource  = nameof(BuildScenario)
                        });
                    }
                    var diff = new Resources
                    {
                        Lumber = resources.Lumber - contracts[0],
                        Clay   = resources.Clay - contracts[1],
                        Iron   = resources.Iron - contracts[2],
                        Crop   = resources.Crop - contracts[3]
                    };

                    error.ResourcesNeeded = diff;
                }

                result.Errors.Add(error);

                //if (errType != BuildErrorType.NotEnoughCropProduction)
                //{
                //    _driver.FindElement(By.Id("closeContentButton")).Click();

                //}
            }
            else
            {
                var errType = css.Contains("underConstruction", StringComparison.OrdinalIgnoreCase)
                        ? BuildErrorType.BuildingIsUnderConstruction
                        : BuildErrorType.NotEnoughCropProduction;

                result.Errors.Add(new BuildScenarioError
                {
                    BuildErrorType = errType,
                    Village        = _action.Village
                });
            }

            var update = GetVillageInfoScenario.UpdateInfo(_driver, _action.Village);

            result.Villages.Add(update);
            return(result);
        }