//If Troop == null, just update the troop levels public override async Task <TaskRes> Execute(HtmlDocument htmlDoc, ChromeDriver wb, Files.Models.AccModels.Account acc) { var academy = vill.Build.Buildings.FirstOrDefault(x => x.Type == Classificator.BuildingEnum.Academy); if (academy == null) { return(TaskRes.Executed); } await acc.Wb.Navigate($"{acc.AccInfo.ServerUrl}/build.php?id={academy.Id}"); var troop = vill.Troops.ToResearch.FirstOrDefault(); if (troop == TroopsEnum.None) { return(TaskRes.Executed); //We have researched all troops that were on the list } var troopNode = htmlDoc.DocumentNode.Descendants("img").FirstOrDefault(x => x.HasClass("u" + (int)troop)); if (troopNode == null) { this.ErrorMessage = $"Researching {troop} was not possible! Bot assumes you already have it researched"; vill.Troops.Researched.Add(troop); return(TaskRes.Retry); } while (!troopNode.HasClass("research")) { troopNode = troopNode.ParentNode; } var button = troopNode.Descendants("button").FirstOrDefault(x => x.HasClass("green")); if (button == null) { RepeatTask(vill, troop, DateTime.Now); } (TimeSpan dur, Resources cost) = TroopsParser.AcademyResearchCost(htmlDoc, troop); var nextExecute = ResourcesHelper.EnoughResourcesOrTransit(acc, vill, cost); if (nextExecute < DateTime.Now.AddMilliseconds(1)) //We have enough resources, click Research button { wb.ExecuteScript($"document.getElementById('{button.Id}').click()"); var executeNext = DateTime.Now.Add(dur).AddMilliseconds(10 * AccountHelper.Delay()); TaskExecutor.AddTask(acc, new ImproveTroop() { vill = this.vill, ExecuteAt = DateTime.Now.Add(dur) } ); RepeatTask(vill, troop, executeNext); return(TaskRes.Executed); } else //Retry same task after resources get produced/transited { this.NextExecute = nextExecute; return(TaskRes.Executed); } }
public override async Task <TaskRes> Execute(HtmlDocument htmlDoc, ChromeDriver wb, Files.Models.AccModels.Account acc) { var building = vill.Build.Buildings.FirstOrDefault(x => x.Type == Classificator.BuildingEnum.Residence || x.Type == Classificator.BuildingEnum.Palace || x.Type == Classificator.BuildingEnum.CommandCenter); if (building == null) { //update dorg, no buildingId found? TaskExecutor.AddTask(acc, new UpdateDorf2() { ExecuteAt = DateTime.Now, vill = vill }); Console.WriteLine($"There is no Residence/Palace/CommandCenter in this village!"); return(TaskRes.Executed); } await acc.Wb.Navigate($"{acc.AccInfo.ServerUrl}/build.php?s=1&id={building.Id}"); var cost = htmlDoc.DocumentNode.Descendants("div").FirstOrDefault(x => x.HasClass("resourceWrapper")); if (cost == null) { this.ErrorMessage = "Could not train settlers. Will retry in 5min"; this.NextExecute = DateTime.Now.AddMinutes(5); //retry in 5min return(TaskRes.Executed); } var resources = ResourceParser.GetResourceCost(cost); var enoughResAt = ResourcesHelper.EnoughResourcesOrTransit(acc, vill, resources); if (enoughResAt <= DateTime.Now.AddMilliseconds(1)) //we have enough res, create new settler! { wb.ExecuteScript($"document.getElementsByName('t10')[0].value='1'"); await Task.Delay(AccountHelper.Delay()); wb.ExecuteScript($"document.getElementById('s1').click()"); //Train settler vill.Troops.Settlers++; if (vill.Troops.Settlers < 3) { //In 1 minute, do the same task (to get total of 3 settlers) this.NextExecute = DateTime.Now.AddSeconds(1); } else { if (acc.NewVillages.AutoSettleNewVillages) { //parse in training table this.PostTaskCheck.Add(NewVillage); } } return(TaskRes.Executed); } else { //Not enough res, wait for production/transit res this.NextExecute = enoughResAt.AddSeconds(60 * AccountHelper.Delay()); return(TaskRes.Executed); } }
public override async Task <TaskRes> Execute(HtmlDocument htmlDoc, ChromeDriver wb, Files.Models.AccModels.Account acc) { if (vill == null) { vill = acc.Villages.First(x => x.Active); } var smithy = vill.Build.Buildings.FirstOrDefault(x => x.Type == Classificator.BuildingEnum.Smithy); if (smithy == null) { return(TaskRes.Executed); } await acc.Wb.Navigate($"{acc.AccInfo.ServerUrl}/build.php?id={smithy.Id}"); var levels = TroopsParser.GetTroopLevels(htmlDoc); if (levels == null) { this.ErrorMessage = "There was an error at getting Smithy troop levels"; return(TaskRes.Executed); } vill.Troops.Levels = levels; UpdateResearchedTroops(vill); var currentlyImproving = TroopsParser.GetImprovingTroops(htmlDoc); var troop = TroopToImprove(vill, currentlyImproving); if (troop == Classificator.TroopsEnum.None) { return(TaskRes.Executed); } //If we have plus account we can improve 2 troops at the same time int maxImproving = acc.AccInfo.PlusAccount ? 2 : 1; if (currentlyImproving.Count() >= maxImproving) { this.NextExecute = DateTime.Now.Add(currentlyImproving.Last().Time); return(TaskRes.Executed); } //call NextImprove() after enough res OR when this improvement finishes. var cost = vill.Troops.Levels.FirstOrDefault(x => x.Troop == troop); var nextExecute = ResourcesHelper.EnoughResourcesOrTransit(acc, vill, cost.UpgradeCost); if (nextExecute < DateTime.Now.AddMilliseconds(1)) //We have enough resources, click Improve button { //Click on the button var troopNode = htmlDoc.DocumentNode.Descendants("img").FirstOrDefault(x => x.HasClass("u" + (int)troop)); while (!troopNode.HasClass("research")) { troopNode = troopNode.ParentNode; } var button = troopNode.Descendants("button").FirstOrDefault(x => x.HasClass("green")); if (button == null) { this.ErrorMessage = $"Could not find Upgrade button to improve {troop}"; this.NextExecute = DateTime.Now.AddMinutes(1); return(TaskRes.Retry); } wb.ExecuteScript($"document.getElementById('{button.Id}').click()"); // If we have plus account and there is currently no other troop to improve, go ahead and improve the unit again this.NextExecute = (currentlyImproving.Count() == 0 && maxImproving == 2) ? DateTime.MinValue : DateTime.Now.Add(cost.TimeCost).AddMilliseconds(5 * AccountHelper.Delay()); return(TaskRes.Executed); } else //Retry same task after resources get produced/transited { this.NextExecute = nextExecute; return(TaskRes.Executed); } }
public override async Task <TaskRes> Execute(HtmlDocument htmlDoc, ChromeDriver wb, Files.Models.AccModels.Account acc) { if (this.task == null) { ConfigNextExecute(acc.Wb.Html, acc); this.NextExecute = DateTime.Now.AddMinutes(2); if (this.task == null) { // There is no building task left. Remove the BotTask acc.Tasks.Remove(this); return(TaskRes.Executed); } } // Check if the task is complete var urlId = BuildingHelper.GetUrlForBuilding(vill, task); if (urlId == null) { //no space for this building vill.Build.Tasks.Remove(this.task); this.task = null; return(await Execute(htmlDoc, wb, acc)); } // In which dorf is the building. Maybe not needed. if (!acc.Wb.CurrentUrl.Contains($"/dorf{((task.BuildingId ?? default) < 19 ? 1 : 2)}.php")) { //Switch village! BotTask updateDorfTask = (task.BuildingId ?? default) < 19 ? (BotTask) new UpdateDorf1() : (BotTask) new UpdateDorf2(); updateDorfTask.vill = this.vill; updateDorfTask.ExecuteAt = DateTime.MinValue.AddHours(2); TaskExecutor.AddTask(acc, updateDorfTask); this.NextExecute = updateDorfTask.ExecuteAt.AddMinutes(1); return(TaskRes.Executed); } // Check if there are already too many buildings currently constructed BuildingHelper.RemoveFinishedCB(vill); var maxBuild = 1; if (acc.AccInfo.PlusAccount) { maxBuild++; } if (acc.AccInfo.Tribe == TribeEnum.Romans) { maxBuild++; } if (vill.Build.CurrentlyBuilding.Count >= maxBuild) { //Execute next upgrade task after currently building this.NextExecute = vill.Build.CurrentlyBuilding.First().Duration.AddSeconds(3); TaskExecutor.ReorderTaskList(acc); return(TaskRes.Executed); } var url = $"{acc.AccInfo.ServerUrl}/build.php?id={urlId}"; // Fast building for TTWars, only if we have enough resources //if (acc.AccInfo.ServerUrl.Contains("ttwars") && !url.Contains("category") && false) // disabling this //{ // var building = vill.Build.Buildings.FirstOrDefault(x => x.Id == this.task.BuildingId); // var lvl = building.Level; // if (building.UnderConstruction) lvl++; // var storedRes = ResourcesHelper.ResourcesToArray(vill.Res.Stored.Resources); // var neededRes = BuildingsCost.GetBuildingCost(this.task.Building, lvl + 1); // if (ResourcesHelper.EnoughRes(storedRes, neededRes)) // { // //url += "&fastUP=1"; // return TaskRes.Executed; // } //} //append correct tab switch (this.task.Building) { case BuildingEnum.RallyPoint: url += "&tt=0"; break; case BuildingEnum.Marketplace: url += "&t=0"; break; } await acc.Wb.Navigate(url); this.PostTaskCheck.Add(ConfigNextExecute); this.NextExecute = DateTime.Now.AddMinutes(2); var contractBuilding = htmlDoc.GetElementbyId($"contract_building{(int)task.Building}"); var upgradeBuildingContract = htmlDoc.GetElementbyId("build"); if (contractBuilding != null) //Construct a new building { var resWrapper = contractBuilding.Descendants().FirstOrDefault(x => x.HasClass("resourceWrapper")); var res = ResourceParser.GetResourceCost(resWrapper); var nextExecute = ResourcesHelper.EnoughResourcesOrTransit(acc, vill, res); if (nextExecute < DateTime.Now.AddMilliseconds(1)) // we have enough res, go construct that building boii { var button = contractBuilding.Descendants("button").FirstOrDefault(x => x.HasClass("new")); //TODO: if button null: check for prerequisites. Maybe a prerequisit is currently building... if (button == null) { this.NextExecute = vill.Build.CurrentlyBuilding.LastOrDefault()?.Duration; this.PostTaskCheck.Remove(ConfigNextExecute); return(TaskRes.Executed); } //check if button is null! wb.ExecuteScript($"document.getElementById('{button.Id}').click()"); this.task.ConstructNew = false; return(TaskRes.Executed); } //not enough resources, wait until resources get produced/transited from main village this.NextExecute = nextExecute; this.PostTaskCheck.Remove(ConfigNextExecute); return(TaskRes.Executed); } else if (upgradeBuildingContract != null) // Upgrade building { (var buildingEnum, var lvl) = InfrastructureParser.UpgradeBuildingGetInfo(upgradeBuildingContract); if (buildingEnum == BuildingEnum.Site || lvl == -1) { this.ErrorMessage = $"Can't upgrade building {this.task.Building} in village {this.vill.Name}. Will be removed from the queue."; vill.Build.Tasks.Remove(this.task); return(TaskRes.Executed); } // If there is already a different building in this spot, find a new id to construct it. if (buildingEnum != task.Building) { if (!BuildingHelper.FindBuildingId(vill, task)) { vill.Build.Tasks.Remove(this.task); } return(TaskRes.Retry); } // Basic task already on/above desired level, don't upgrade further var building = vill.Build.Buildings.FirstOrDefault(x => x.Id == this.task.BuildingId); if (building.UnderConstruction) { lvl++; } if (lvl >= task.Level) { this.ErrorMessage = $"{this.task.Building} is on level {lvl}, above desired {task.Level}. Removing it from queue."; vill.Build.Tasks.Remove(this.task); RemoveCompletedTasks(this.vill, acc); return(TaskRes.Executed); } var container = htmlDoc.DocumentNode.Descendants("div").FirstOrDefault(x => x.HasClass("upgradeButtonsContainer")); var buttons = container?.Descendants("button"); if (buttons == null) { this.ErrorMessage = "No 'upgrade' button found!"; return(TaskRes.Executed); } HtmlNode upgradeButton = buttons.FirstOrDefault(x => x.HasClass("build")); //We have enough resources, click on build if (upgradeButton != null) { var buildDuration = InfrastructureParser.GetBuildDuration(container, acc.AccInfo.ServerVersion); if (IsTaskCompleted(vill, acc, this.task)) { this.ErrorMessage = $"Building {this.task.Building} in village {this.vill.Name} is already done. Will be removed from the queue."; vill.Build.Tasks.Remove(this.task); return(TaskRes.Executed); } //TODO move this CheckSettlers(acc, vill, lvl, DateTime.Now.Add(buildDuration)); Console.WriteLine($"Village {vill.Name} will upgrade {task.Building}"); wb.ExecuteScript($"document.getElementById('{upgradeButton.Id}').click()"); return(TaskRes.Executed); } else { HtmlNode error = container.Descendants("span").FirstOrDefault(x => x.HasClass("none")); //Not enough resources var contract = htmlDoc.GetElementbyId("contract"); var resWrapper = contract.Descendants().FirstOrDefault(x => x.HasClass("resourceWrapper")); var res = ResourceParser.GetResourceCost(resWrapper); this.PostTaskCheck.Remove(ConfigNextExecute); this.NextExecute = ResourcesHelper.EnoughResourcesOrTransit(acc, vill, res); return(TaskRes.Executed); } } else { throw new Exception("No construct or upgrade contract was found!"); } }