Ejemplo n.º 1
0
        /// <summary>
        /// If there are enough resources, return TimeSpan(0)
        /// Otherwise calculate how long it will take to get enough resources and transit res from
        /// main village, if we have that enabled. Return the one that takes less time.
        /// DateTime for usage in nextExecution time
        /// </summary>
        /// <param name="acc">Account</param>
        /// <param name="vill">(target) Village</param>
        /// <param name="requiredRes">Resources required</param>
        /// <param name="task">Bot task that doesn't have enough resources</param>
        /// <param name="buildingTask">Potential building task</param>
        /// <returns>When next village update should occur</returns>
        private static DateTime?NewUnfinishedTask(Account acc, Village vill, Resources requiredRes, BotTask task, BuildingTask buildingTask = null)
        {
            var stillNeededRes = SubtractResources(requiredRes.ToArray(), vill.Res.Stored.Resources.ToArray(), true);

            // Whether we have enough resources. This should already be checked before calling this method!
            if (IsZeroResources(stillNeededRes))
            {
                ResSpendingHelper.AddUnfinishedTask(vill, task, requiredRes);
                return(DateTime.Now);
            }

            acc.Wb.Log($"Not enough resources for the task {task.GetName()}! Needed {requiredRes}. Bot will try finish the task later");

            if (IsStorageTooLow(acc, vill, requiredRes))
            {
                acc.Wb.Log($"Storage is too low.");
                ResSpendingHelper.AddUnfinishedTask(vill, task, requiredRes);
                return(null);
            }

            // Try to use hero resources first
            if (vill.Settings.UseHeroRes &&
                acc.AccInfo.ServerVersion == ServerVersionEnum.T4_5) // Only T4.5 has resources in hero inv
            {
                var heroRes = HeroHelper.GetHeroResources(acc);

                // If we have some hero resources, we should use those first
                if (!IsZeroResources(heroRes))
                {
                    var heroEquipTask = UseHeroResources(acc, vill, ref stillNeededRes, heroRes, buildingTask);

                    // If we have enough hero res for our task, execute the task
                    // right after hero equip finishes
                    if (IsZeroResources(SubtractResources(stillNeededRes, heroRes, true)))
                    {
                        heroEquipTask.NextTask = task;
                        return(null);
                    }
                }
            }

            ResSpendingHelper.AddUnfinishedTask(vill, task, requiredRes);

            // When will we have enough resources from production
            DateTime enoughRes = TimeHelper.EnoughResToUpgrade(vill, stillNeededRes);

            var mainVill = AccountHelper.GetMainVillage(acc);

            if (mainVill == vill)
            {
                return(enoughRes);
            }

            DateTime resTransit = MarketHelper.TransitResourcesFromMain(acc, vill);

            if (resTransit < enoughRes)
            {
                enoughRes = resTransit;
            }

            if (enoughRes < DateTime.Now)
            {
                return(DateTime.Now);
            }

            return(enoughRes);
        }
Ejemplo n.º 2
0
        /// <summary>
        /// Called PageLoaded (after navigating to a specific url) or from
        /// Task timer, if there is no url/bot is already on the url
        /// </summary>
        /// <param name="acc">Account</param>
        /// <param name="task">Task to be executed</param>
        /// <returns></returns>
        public static async Task Execute(Account acc, BotTask task)
        {
            // Before every execution, wait a random delay
            if (acc.AccInfo.ServerVersion == Classificator.ServerVersionEnum.T4_5)
            {
                await Task.Delay(AccountHelper.Delay());
            }

            if (acc.Wb?.CurrentUrl == null && task.GetType() != typeof(CheckProxy))
            {
                await acc.Wb.Navigate($"{acc.AccInfo.ServerUrl}/dorf1.php");
            }

            if (task.Vill == null)
            {
                task.Vill = acc.Villages.FirstOrDefault(x => x.Active);
            }

            try
            {
                acc.Wb.Log($"Executing task {task.GetName()}" + (task.Vill == null ? "" : $" in village {task.Vill.Name}"));

                switch (await task.Execute(acc))
                {
                case TaskRes.Retry:
                    task.RetryCounter++;
                    if (task.NextExecute == null)
                    {
                        task.NextExecute = DateTime.Now.AddMinutes(3);
                    }
                    break;

                default:
                    task.RetryCounter = 0;
                    if (task.NextTask != null)
                    {
                        task.NextTask.ExecuteAt = DateTime.MinValue.AddHours(5);
                        task.NextTask.Stage     = TaskStage.Start;
                        TaskExecutor.AddTask(acc, task.NextTask);
                        task.NextTask = null;
                    }
                    break;
                }
            }
            catch (Exception e)
            {
                if (acc.Wb != null)
                {
                    acc.Wb.Log($"Error executing task {task.GetName()}! Vill {task.Vill?.Name}", e);
                }
                task.RetryCounter++;
                if (task.NextExecute == null)
                {
                    task.NextExecute = DateTime.Now.AddMinutes(3);
                }
            }

            //We want to re-execute the same task later
            if (task.NextExecute != null && task.RetryCounter < 3)
            {
                task.ExecuteAt   = task.NextExecute ?? default;
                task.NextExecute = null;
                ReorderTaskList(acc);
                task.Stage = TaskStage.Start;
                return;
            }
            // Remove the task from the task list
            acc.Tasks.Remove(task);
        }
Ejemplo n.º 3
0
        /// <summary>
        /// Called PageLoaded (after navigating to a specific url) or from
        /// Task timer, if there is no url/bot is already on the url
        /// </summary>
        /// <param name="acc">Account</param>
        /// <param name="task">Task to be executed</param>
        /// <returns></returns>
        public static async Task Execute(Account acc, BotTask task)
        {
            // Before every execution, wait a random delay
            await Task.Delay(AccountHelper.Delay());

            if (task.Vill == null)
            {
                task.Vill = acc.Villages.FirstOrDefault(x => x.Active);
            }

            acc.Logger.Information($"Executing task {task.GetName()}" + (task.Vill == null ? "" : $" in village {task.Vill.Name}"));

            try
            {
                switch (await task.Execute(acc))
                {
                case TaskRes.Retry:
                    task.RetryCounter++;
                    if (task.NextExecute == null)
                    {
                        task.NextExecute = DateTime.Now.AddMinutes(3);
                    }
                    break;

                default:
                    task.RetryCounter = 0;
                    if (task.NextTask != null)
                    {
                        task.NextTask.ExecuteAt = DateTime.MinValue.AddHours(5);
                        task.NextTask.Stage     = TaskStage.Start;
                        acc.Tasks.Add(task.NextTask);
                        task.NextTask = null;
                    }
                    break;
                }
            }
            catch (WebDriverException e) when(e.Message.Contains("chrome not reachable") || e.Message.Contains("no such window:"))
            {
                acc.Logger.Warning($"Chrome has problem while executing task {task.GetName()}! Vill {task.Vill?.Name}. Try reopen Chrome");

                acc.Tasks.Add(new ReopenDriver()
                {
                    ExecuteAt = DateTime.MinValue,
                    Priority  = TaskPriority.High,
                    ReopenAt  = DateTime.MinValue
                });

                //try exccute task after we reopen chrome 1 mintues

                if (task.NextExecute == null)
                {
                    task.NextExecute = DateTime.MinValue.AddMinutes(1);                           // make sure current task is excuted after reopen driver
                }
            }
            catch (Exception e)
            {
                acc.Logger.Error(e, $"Error executing task {task.GetName()}! Vill {task.Vill?.Name}");
                task.RetryCounter++;
                if (task.NextExecute == null)
                {
                    task.NextExecute = DateTime.Now.AddMinutes(3);
                }
            }

            //We want to re-execute the same task later
            if (task.NextExecute != null && task.RetryCounter < 3)
            {
                task.ExecuteAt   = task.NextExecute ?? default;
                task.NextExecute = null;
                acc.Tasks.ReOrder();

                task.Stage = TaskStage.Start;
                acc.Logger.Warning($"Task {task.GetName()}" + (task.Vill == null ? "" : $" in village {task.Vill.Name} will be re-executed at {task.ExecuteAt}"));
                return;
            }
            // Remove the task from the task list
            acc.Tasks.Remove(task);
            if (task.RetryCounter >= 3)
            {
                acc.Logger.Warning($"Task {task.GetName()}" + (task.Vill == null ? "" : $" in village {task.Vill.Name} is already re-executed 3 times. Ignore it"));
            }
            else
            {
                acc.Logger.Information($"Task {task.GetName()}" + (task.Vill == null ? "" : $" in village {task.Vill.Name} is done."));
            }
        }