예제 #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();
            }

            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)
            {
                acc.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)));
        }
예제 #2
0
        /// <summary>
        /// Gets tasks that should be executed after loading a page
        /// </summary>
        /// <param name="acc">Account</param>
        /// <returns>List of tasks</returns>
        public static List <Action> GetPostLoadTasks(Account acc)
        {
            var html = acc.Wb.Html;

            var ran = new Random();

            //Web browser not initialized
            if (!UpdateAccountObject.UpdateVillages(html, acc))
            {
                return(new List <Action>());
            }
            var vill = acc.Villages.FirstOrDefault(x => x.Active);

            return(new List <Action>()
            {
                // 1:
                () => acc.AccInfo.ServerVersion = (acc.Wb.Html.GetElementbyId("sidebarBoxDailyquests") == null ? Classificator.ServerVersionEnum.T4_5 : Classificator.ServerVersionEnum.T4_4),
                // 2:
                () => {
                    if (acc.Wb.CurrentUrl.Contains("dorf1"))
                    {
                        TaskExecutor.UpdateDorf1Info(acc);
                    }
                    else if (acc.Wb.CurrentUrl.Contains("dorf2"))
                    {
                        TaskExecutor.UpdateDorf2Info(acc);
                    }
                },
                // 3:
                () => acc.AccInfo.CulturePoints = RightBarParser.GetCulurePoints(html, acc.AccInfo.ServerVersion),
                // 4 Village expansion:
                () =>
                {
                    var villExpansionReady = acc.Villages.FirstOrDefault(x => x.Expansion.ExpansionAvailable);
                    if (acc.AccInfo.CulturePoints?.MaxVillages > acc.AccInfo.CulturePoints?.VillageCount &&
                        villExpansionReady != null)
                    {
                        villExpansionReady.Expansion.ExpansionAvailable = false;
                        TaskExecutor.AddTaskIfNotExists(acc, new SendSettlers()
                        {
                            ExecuteAt = DateTime.Now, Vill = villExpansionReady
                        });
                    }
                },
                // 5. Beginner Quests:
                () =>
                {
                    if (acc.AccInfo.ServerVersion == Classificator.ServerVersionEnum.T4_5 &&
                        acc.Wb.Html.GetElementbyId("sidebarBoxQuestmaster")?
                        .Descendants()?.FirstOrDefault(x => x.HasClass("newQuestSpeechBubble")) != null &&
                        acc.Wb.Html.GetElementbyId("mentorTaskList") == null &&
                        acc.Quests.ClaimBeginnerQuests)
                    {
                        TaskExecutor.AddTaskIfNotExists(acc, new ClaimBeginnerTask2021()
                        {
                            ExecuteAt = DateTime.Now
                        });
                        return;
                    }

                    acc.Quests.Quests = RightBarParser.GetBeginnerQuests(html, acc.AccInfo.ServerVersion);
                    var claimQuest = acc.Quests?.Quests?.FirstOrDefault(x => x.finished);
                    if (claimQuest != null &&
                        acc.Quests.ClaimBeginnerQuests
                        )
                    {
                        TaskExecutor.AddTaskIfNotExists(acc, new ClaimBeginnerTask()
                        {
                            ExecuteAt = DateTime.Now,
                            QuestToClaim = claimQuest,
                            Vill = VillageHelper.VillageFromId(acc, acc.Quests.VillToClaim)
                        });
                    }
                },
                // 6. Daily Quest:
                () =>
                {
                    if (acc.AccInfo.ServerVersion == Classificator.ServerVersionEnum.T4_5 &&
                        RightBarParser.CheckDailyQuest(html) &&
                        acc.Quests.ClaimDailyQuests)
                    {
                        TaskExecutor.AddTaskIfNotExists(acc, new ClaimDailyTask()
                        {
                            ExecuteAt = DateTime.Now,
                            Vill = VillageHelper.VillageFromId(acc, acc.Quests.VillToClaim)
                        });
                    }
                },
                // 7. Parse gold/silver
                () =>
                {
                    var goldSilver = RightBarParser.GetGoldAndSilver(html, acc.AccInfo.ServerVersion);
                    acc.AccInfo.Gold = goldSilver[0];
                    acc.AccInfo.Silver = goldSilver[1];
                },
                // 8:
                () => acc.AccInfo.PlusAccount = RightBarParser.HasPlusAccount(html, acc.AccInfo.ServerVersion),
                // 9 Check msgs:
                () =>
                {
                    if (MsgParser.UnreadMessages(html, acc.AccInfo.ServerVersion) > 0 &&
                        !acc.Wb.CurrentUrl.Contains("messages.php") &&
                        acc.Settings.AutoReadIgms)
                    {
                        TaskExecutor.AddTaskIfNotExists(acc, new ReadMessage()
                        {
                            ExecuteAt = DateTime.Now.AddSeconds(ran.Next(10, 600)), // Read msg in next 10-600 seconds
                            Priority = TaskPriority.Low
                        });
                    }
                },
                // 10: JS resources
                () => {
                    // TODO: cast directly from object to ResourcesJsObject, no de/serialization!
                    var resJson = DriverHelper.GetJsObj <string>(acc, "JSON.stringify(resources);");
                    var resJs = JsonConvert.DeserializeObject <ResourcesJsObject>(resJson);

                    vill.Res.Capacity.GranaryCapacity = resJs.maxStorage.l4;
                    vill.Res.Capacity.WarehouseCapacity = resJs.maxStorage.l1;

                    vill.Res.Stored.Resources = resJs.storage.GetResources();
                    vill.Res.Stored.LastRefresh = DateTime.Now;

                    vill.Res.Production = resJs.production.GetResources();
                    vill.Res.FreeCrop = resJs.production.l5;
                },
                // 11: Check if there are unfinished tasks
                () => ResSpendingHelper.CheckUnfinishedTasks(acc, vill),
                // 12: Donate to ally bonus'
                () => DonateToAlly(acc, vill),
                // 13:
                () => vill.Timings.NextVillRefresh = DateTime.Now.AddMinutes(ran.Next(30, 60)),
                // 14 NPC:
                () =>
                {
                    float ratio = (float)vill.Res.Stored.Resources.Crop / vill.Res.Capacity.GranaryCapacity;
                    if (0.99 <= ratio &&
                        3 <= acc.AccInfo.Gold &&
                        vill.Market.Npc.Enabled &&
                        (vill.Market.Npc.NpcIfOverflow || !MarketHelper.NpcWillOverflow(vill)))
                    {  //npc crop!
                        TaskExecutor.AddTaskIfNotExistInVillage(acc, vill, new NPC()
                        {
                            ExecuteAt = DateTime.MinValue,
                            Vill = vill
                        });
                    }
                },
                // 15:
                () => {
                    if (acc.Settings.AutoActivateProductionBoost && CheckProductionBoost(acc))
                    {
                        TaskExecutor.AddTask(acc, new TTWarsPlusAndBoost()
                        {
                            ExecuteAt = DateTime.Now.AddSeconds(1)
                        });
                    }
                },
                // 16. Insta upgrade:
                () =>
                {
                    if (vill.Build.InstaBuild &&
                        acc.AccInfo.Gold >= 2 &&
                        vill.Build.CurrentlyBuilding.Count >= (acc.AccInfo.PlusAccount ? 2 : 1) &&
                        vill.Build.CurrentlyBuilding.LastOrDefault().Duration
                        >= DateTime.Now.AddHours(vill.Build.InstaBuildHours))
                    {
                        TaskExecutor.AddTaskIfNotExistInVillage(acc, vill, new InstaUpgrade()
                        {
                            Vill = vill,
                            ExecuteAt = DateTime.Now.AddHours(-1)
                        });
                    }
                },
                // 17
                () => acc.Hero.AdventureNum = HeroParser.GetAdventureNum(html, acc.AccInfo.ServerVersion),
                // 18
                () => acc.Hero.Status = HeroParser.HeroStatus(html, acc.AccInfo.ServerVersion),
                // 19
                () => acc.Hero.HeroInfo.Health = HeroParser.GetHeroHealth(html, acc.AccInfo.ServerVersion),
                // 20 Hero:
                () =>
                {
                    bool heroReady = (acc.Hero.HeroInfo.Health > acc.Hero.Settings.MinHealth &&
                                      acc.Hero.Settings.AutoSendToAdventure &&
                                      acc.Hero.Status == Hero.StatusEnum.Home &&
                                      acc.Hero.NextHeroSend < DateTime.Now);

                    var homeVill = HeroHelper.GetHeroHomeVillage(acc);
                    // Update adventures
                    if (homeVill == null)
                    {
                        TaskExecutor.AddTask(acc, new HeroUpdateInfo()
                        {
                            ExecuteAt = DateTime.Now
                        });
                    }
                    else if (heroReady &&
                             (homeVill.Build.Buildings.Any(x => x.Type == Classificator.BuildingEnum.RallyPoint && 0 < x.Level)) &&
                             (acc.Hero.AdventureNum != acc.Hero.Adventures.Count() || HeroHelper.AdventureInRange(acc)))
                    {
                        // Update adventures
                        TaskExecutor.AddTaskIfNotExists(acc, new StartAdventure()
                        {
                            ExecuteAt = DateTime.Now.AddSeconds(10)
                        });
                    }
                    if (acc.Hero.AdventureNum == 0 && acc.Hero.Settings.BuyAdventures) //for UNL servers, buy adventures
                    {
                        TaskExecutor.AddTaskIfNotExists(acc, new TTWarsBuyAdventure()
                        {
                            ExecuteAt = DateTime.Now.AddSeconds(5)
                        });
                    }
                    if (acc.Hero.Status == Hero.StatusEnum.Dead && acc.Hero.Settings.AutoReviveHero) //if hero is dead, revive him
                    {
                        TaskExecutor.AddTaskIfNotExists(acc, new ReviveHero()
                        {
                            ExecuteAt = DateTime.Now.AddSeconds(5),
                            Vill = AccountHelper.GetHeroReviveVillage(acc)
                        });
                    }
                    if (HeroParser.LeveledUp(html, acc.AccInfo.ServerVersion) && acc.Hero.Settings.AutoSetPoints)
                    {
                        TaskExecutor.AddTaskIfNotExists(acc, new HeroSetPoints()
                        {
                            ExecuteAt = DateTime.Now
                        });
                    }
                },
                // 21:
                () => AutoExpandStorage(acc, vill),
                // 22: Extend protection
                () => {
                    if (acc.Settings.ExtendProtection &&
                        acc.Wb.Html.GetElementbyId("sidebarBoxInfobox").Descendants("button").Any(x => x.GetAttributeValue("value", "") == "Extend"))
                    {
                        TaskExecutor.AddTaskIfNotExists(acc, new ExtendProtection()
                        {
                            ExecuteAt = DateTime.Now
                        });
                    }
                }
            });
        }