/// <summary> /// Building is already constructed, upgrade it /// </summary> /// <param name="acc">Account</param> /// <returns>TaskResult</returns> private async Task <TaskRes> Upgrade(Account acc, HtmlNode node) { (var buildingEnum, var lvl) = InfrastructureParser.UpgradeBuildingGetInfo(node); if (buildingEnum == BuildingEnum.Site || lvl == -1) { acc.Wb.Log($"Can't upgrade building {this.Task.Building} in village {this.Vill.Name}. Will be removed from the queue."); RemoveCurrentTask(); return(TaskRes.Executed); } // If there is already a different building in this spot, find a new id to construct it. if (buildingEnum != Task.Building) { acc.Wb.Log($"We wanted to upgrade {Task.Building}, but there's already {buildingEnum} on this id ({Task.BuildingId})."); if (!BuildingHelper.FindBuildingId(Vill, this.Task)) { acc.Wb.Log($"Found another Id to build {Task.Building}, new id: {Task.BuildingId}"); return(TaskRes.Retry); } acc.Wb.Log($"Failed to find another Id to build {Task.Building}! No space in village. Building task will be removed"); RemoveCurrentTask(); return(TaskRes.Executed); } // Basic task already on/above desired level, don't upgrade further var building = Vill.Build.Buildings.FirstOrDefault(x => x.Id == this.Task.BuildingId); lvl = building.Level; if (building.UnderConstruction) { lvl++; } if (Task.Level <= lvl) { acc.Wb.Log($"{this.Task.Building} is on level {lvl}, on/above desired {Task.Level}. Removing it from queue."); RemoveCurrentTask(); RemoveCompletedTasks(this.Vill, acc); return(TaskRes.Executed); } var container = acc.Wb.Html.DocumentNode.Descendants("div").FirstOrDefault(x => x.HasClass("upgradeButtonsContainer")); var buttons = container?.Descendants("button"); if (buttons == null) { acc.Wb.Log($"We wanted to upgrade {Task.Building}, but no 'upgrade' button was found! Url={acc.Wb.CurrentUrl}"); return(TaskRes.Retry); } var errorMessage = acc.Wb.Html.GetElementbyId("build") .Descendants("div") .FirstOrDefault(x => x.HasClass("upgradeBuilding"))? .Descendants("div")? .FirstOrDefault(x => x.HasClass("errorMessage")); HtmlNode upgradeButton = buttons.FirstOrDefault(x => x.HasClass("build")); if (upgradeButton == null) { acc.Wb.Log($"We wanted to upgrade {Task.Building}, but no 'upgrade' button was found!"); return(TaskRes.Retry); } // Not enough resources? if (acc.AccInfo.ServerVersion == ServerVersionEnum.T4_5 && errorMessage != null) { acc.Wb.Log($"We wanted to upgrade {Task.Building}, but there was an error message:\n{errorMessage.InnerText}"); return(TaskRes.Retry); } var buildDuration = InfrastructureParser.GetBuildDuration(container, acc.AccInfo.ServerVersion); if (IsTaskCompleted(Vill, acc, this.Task)) { acc.Wb.Log($"Building {this.Task.Building} in village {this.Vill.Name} is already on desired level. Will be removed from the queue."); RemoveCurrentTask(); return(TaskRes.Executed); } if (acc.AccInfo.ServerVersion == ServerVersionEnum.T4_4 || buildDuration.TotalMinutes <= acc.Settings.WatchAdAbove || !await TryFastUpgrade(acc)) // +25% speed upgrade { await DriverHelper.ClickById(acc, upgradeButton.Id); // Normal upgrade } lvl++; CheckIfTaskFinished(lvl); acc.Wb.Log($"Started upgrading {this.Task.Building} to level {lvl} in {this.Vill?.Name}"); await PostTaskCheckDorf(acc); 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!"); } }