Ejemplo n.º 1
0
        /// <summary>
        /// Used by BotTasks to insert resources/coordinates into the page.
        /// </summary>
        /// <param name="acc">Account</param>
        /// <param name="resources">Target resources</param>
        /// <param name="coordinates">Target coordinates</param>
        /// <returns>Time it will take for transit to complete</returns>
        public static async Task <TimeSpan> MarketSendResource(Account acc, long[] resources, Village targetVillage, BotTask botTask)
        {
            var times = 1;

            if (acc.AccInfo.GoldClub ?? false)
            {
                times = 3;
            }
            else if (acc.AccInfo.PlusAccount)
            {
                times = 2;
            }

            // No resources to send
            if (resources.Sum() == 0)
            {
                return(TimeSpan.Zero);
            }

            var sendRes = resources.Select(x => x / times).ToArray();

            //round the resources that we want to send, so it looks less like a bot

            (var merchantsCapacity, var merchantsNum) = MarketHelper.ParseMerchantsInfo(acc.Wb.Html);
            // We don't have any merchants.
            if (merchantsNum == 0)
            {
                //Parse currently ongoing transits
                var transits   = MarketParser.ParseTransits(acc.Wb.Html);
                var activeVill = acc.Villages.FirstOrDefault(x => x.Active); // Could also just pass that in params

                var nextTry = SoonestAvailableMerchants(acc, activeVill, targetVillage, transits);
                if (nextTry != DateTime.MaxValue)
                {
                    nextTry = nextTry.AddSeconds(5);
                }

                botTask.NextExecute = nextTry;
                // Just return something, will get overwritten anyways.
                return(new TimeSpan((int)(nextTry - DateTime.Now).TotalHours + 1, 0, 0));
            }

            var maxRes = merchantsCapacity * times;
            var allRes = resources.Sum();

            if (allRes > maxRes)
            {
                // We don't have enough merchants to transit all the resources. Divide all resources by some divider.
                var     resDivider = (float)allRes / maxRes;
                float[] resFloat   = sendRes.Select(x => x / resDivider).ToArray();
                sendRes = resFloat.Select(x => (long)Math.Floor(x)).ToArray();
            }

            var wb = acc.Wb.Driver;

            for (int i = 0; i < 4; i++)
            {
                // To avoid exception devide by zero
                if (50 <= sendRes[i])
                {
                    //round the number to about -1%, for rounder numbers
                    var digits    = Math.Ceiling(Math.Log10(sendRes[i]));
                    var remainder = sendRes[i] % (long)Math.Pow(10, digits - 2);
                    sendRes[i] -= remainder;
                    await DriverHelper.WriteById(acc, "r" + (i + 1), sendRes[i]);
                }
                await Task.Delay(AccountHelper.Delay() / 5);
            }

            // Input coordinates
            await DriverHelper.WriteCoordinates(acc, targetVillage.Coordinates);

            //Select x2/x3
            if (times != 1)
            {
                wb.ExecuteScript($"document.getElementById('x2').value='{times}'");
                await Task.Delay(AccountHelper.Delay() / 5);
            }
            await DriverHelper.ClickById(acc, "enabledButton");

            var durNode = acc.Wb.Html.GetElementbyId("target_validate");

            if (durNode == null && acc.Wb.Html.GetElementbyId("prepareError") != null)
            {
                // Error "Abuse! You have not enough resources." is displayed.
            }
            //get duration of transit
            var dur = durNode.Descendants("td").ToList()[3].InnerText.Replace("\t", "").Replace("\n", "");

            // Will NOT trigger a page reload! Thus we should await some time before continuing.
            await DriverHelper.ClickById(acc, "enabledButton");

            targetVillage.Market.LastTransit = DateTime.Now;

            var duration = TimeParser.ParseDuration(dur);

            return(TimeSpan.FromTicks(duration.Ticks * (times * 2 - 1)));
        }
Ejemplo n.º 2
0
        /// <summary>
        /// Used by BotTasks to insert resources/coordinates into the page.
        /// </summary>
        /// <param name="acc">Account</param>
        /// <param name="resources">Target resources</param>
        /// <param name="coordinates">Target coordinates</param>
        /// <returns>Time it will take for transit to complete</returns>
        public static async Task <TimeSpan> MarketSendResource(Account acc, long[] resources, Village targetVillage, BotTask botTask)
        {
            var times = 1;

            if (acc.AccInfo.GoldClub ?? false)
            {
                times = 3;
            }
            else if (acc.AccInfo.PlusAccount)
            {
                times = 2;
            }

            var sendRes = resources.Select(x => x / times).ToArray();

            //round the resources that we want to send, so it looks less like a bot

            //TODO: check if we have enough merchants
            (var merchantsCapacity, var merchantsNum) = MarketHelper.ParseMerchantsInfo(acc.Wb.Html);
            // We don't have any merchants.
            if (merchantsNum == 0)
            {
                //Parse currently ongoing transits
                var transits   = MarketParser.ParseTransits(acc.Wb.Html);
                var activeVill = acc.Villages.FirstOrDefault(x => x.Active); // Could also just pass that in params

                var nextTry = SoonestAvailableMerchants(acc, activeVill, targetVillage, transits);

                botTask.NextExecute = nextTry.AddSeconds(5);
                // Just return something, will get overwritten anyways.
                return(new TimeSpan((int)(nextTry - DateTime.Now).TotalHours + 1, 0, 0));
            }

            var maxRes = merchantsCapacity * times;
            var allRes = resources.Sum();

            if (allRes > maxRes)
            {
                // We don't have enough merchants to transit all the resources. Divide all resources by some divider.
                var     resDivider = (float)allRes / maxRes;
                float[] resFloat   = sendRes.Select(x => x / resDivider).ToArray();
                sendRes = resFloat.Select(x => (long)Math.Floor(x)).ToArray();
            }

            var wb = acc.Wb.Driver;

            for (int i = 0; i < 4; i++)
            {
                // To avoid exception devide by zero
                if (sendRes[i] != 0)
                {
                    //round the number to about -1%, for rounder numbers
                    var digits    = Math.Ceiling(Math.Log10(sendRes[i]));
                    var remainder = sendRes[i] % (long)Math.Pow(10, digits - 2);
                    sendRes[i] -= remainder;
                }
                wb.ExecuteScript($"document.getElementById('r{i + 1}').value='{sendRes[i]}'");
                await Task.Delay(AccountHelper.Delay() / 5);
            }

            wb.ExecuteScript($"document.getElementById('xCoordInput').value='{targetVillage.Coordinates.x}'");
            await Task.Delay(AccountHelper.Delay() / 5);

            wb.ExecuteScript($"document.getElementById('yCoordInput').value='{targetVillage.Coordinates.y}'");
            await Task.Delay(AccountHelper.Delay() / 5);

            //Select x2/x3
            if (times != 1)
            {
                wb.ExecuteScript($"document.getElementById('x2').value='{times}'");
                await Task.Delay(AccountHelper.Delay() / 5);
            }

            // Some bot protection here I guess. Just remove the class of the DOM.
            var script = @"
                    var button = document.getElementById('enabledButton');
                    button.click();
                    ";

            wb.ExecuteScript(script); //Prepare

            //update htmlDoc, parse duration, TODO: maybe some other method to wait until the page is loaded?
            HtmlNode durNode = null;

            do
            {
                await Task.Delay(AccountHelper.Delay());

                HtmlDocument html2 = new HtmlDocument();
                html2.LoadHtml(wb.PageSource);
                durNode = html2.GetElementbyId("target_validate");
            }while (durNode == null);

            //get duration of transit
            var dur = durNode.Descendants("td").ToList()[3].InnerText.Replace("\t", "").Replace("\n", "");

            // Will NOT trigger a page reload! Thus we should await some time before continuing.
            wb.ExecuteScript("document.getElementById('enabledButton').click()"); //SendRes

            await Task.Delay(AccountHelper.Delay() * 2);

            var duration = TimeParser.ParseDuration(dur);

            return(TimeSpan.FromTicks(duration.Ticks * (times * 2 - 1)));
        }