private async Task CleanContext(JobExecutionData jobExecutionData) { var key = SchedulerService.BuildJobKey(jobExecutionData); var removed = _travianUser.ExecutionContext?.Commands?.RemoveAll(x => x.KeyGroup == key.Group && x.StartDateTime < DateTimeOffset.Now); if (removed > 0) { await _travianUserRepository.Update(_travianUser); } }
protected override async Task ExecuteJob(JobExecutionData jobExecutionData) { if (jobExecutionData != null) { await ExecuteJobScenario(new CancellationToken()); } else { throw new ArgumentNullException(nameof(jobExecutionData), "The provided execution data is null"); } }
protected override async Task ExecuteJob(JobExecutionData jobExecutionData) { await CleanContext(jobExecutionData); try { var actions = await this._actionProvider.GetActionsForPlayer(_travianUser); if (actions != null && actions.Any()) { _logger.LogDebug($"Starting Prepare to attack command for BotUserName:[{_botUser.UserName}], TravianUserName:[{_travianUser.UserName}]"); var response = await _gameplayClient.ExecuteActions(_travianUser, actions); if (response.Errors != null && response.Errors.Any(x => x != null)) { var villagesNames = string.Join(", ", actions.Select(x => x.Village.Name)); await _bot.SendTextMessageAsync(_botUser.ChatId, $"The prepare command completed with errors"); _logger.LogError(LoggingEvents.BackgroundJobCreationException, string.Join(", ", response.Errors)); var notFound = response.Errors.Where(x => x.ErrorType == "NotFound"); if (notFound.Any()) { foreach (var error in notFound) { await _bot.SendTextMessageAsync(_botUser.ChatId, error.ErrorMessage); } } } else { foreach (var action in actions) { var msg = $"The village {action.Village.Name} was prepared to attack with following action: [{action.Action.GetEnumDisplayName()}]"; if (action is SendResourcesAction) { var a = action as SendResourcesAction; msg += $" to {a.To.Name}"; } msg += "."; await _bot.SendTextMessageAsync(_botUser.ChatId, msg); } } _logger.LogDebug($"Prepare to attack command completed for player :[{_travianUser.UserName}]"); } } catch (Exception exc) { _logger.LogError(LoggingEvents.BackgroundJobCreationException, exc, exc.Message); } }
public async Task Execute(JobExecutionData jobExecutionData) { try { _botUser = await _botUserProvider.FindByNameAsync(jobExecutionData.TravianUser.BotUserName); _travianUser = jobExecutionData.TravianUser; } catch (Exception exc) { this._logger.LogError(LoggingEvents.BackgroundJobExecutingException, exc, "Unable to get parameters from JobExecutionContext."); return; } try { await ExecuteJob(jobExecutionData); } catch (Exception exc) { this._logger.LogError(LoggingEvents.BackgroundJobExecutingException, exc, "Unexpected error occurred during the job execution."); } }
protected override async Task ExecuteJob(JobExecutionData jobExecutionData) { var allVillages = await _villageRepository.GetVillages(_travianUser.UserName); var buildVillages = allVillages .Where(x => x.IsBuildFeatureOn) .ToList(); if (!buildVillages.Any()) { await _bot.SendTextMessageAsync(_botUser.ChatId, $"No villages with build feature found for player {_travianUser.UserName}"); return; } foreach (var village in buildVillages.Where(x => x.IsWaitingForResources)) { // for villages waiting for resources next execution time is the time when resources must be delivered // if next execution time passed resources are expected to be delivered village.IsWaitingForResources = village.NextBuildingPlanExecutionTime.HasValue && village.NextBuildingPlanExecutionTime.Value > DateTimeOffset.Now; } BaseScenarioResult infos = null; try { var updateActions = buildVillages .Select(x => new GameAction { Village = _mapper.Map <Village>(x) }); infos = await _gameplayClient.ExecuteActions(_travianUser, updateActions); var update = infos.Villages.Select(x => _mapper.Map <VillageModel>(x)); await _villageRepository.UpdateWatchInfo(update); } catch (Exception exc) { _logger.LogError(exc, exc.Message); await _bot.SendTextMessageAsync(_botUser.ChatId, $"Unable to update villages info for player {_travianUser.UserName}"); return; } if (!infos?.Villages?.Any() ?? true) { await _bot.SendTextMessageAsync(_botUser.ChatId, $"No info was found for villages of {_travianUser.UserName}"); return; } // suits only for rome or for player with travian plus. TODO: fix for other tribes var freeVillages = infos.Villages .Where(x => x.CanBuild) .ToList(); var busyVillages = infos.Villages .Where(x => !x.CanBuild) .ToList(); if (busyVillages?.Any() ?? false) { foreach (var village in busyVillages) { // if village has less than 10% filled warehouse we should send there more resources var limit = village.Warehourse * 0.1; if (!village.Dorf1BuildTimeLeft.HasValue || village.Resources.Lumber < limit || village.Resources.Clay < limit || village.Resources.Iron < limit || village.Resources.Crop < village.Granary * 0.1) { await SendResources(allVillages.ToList(), village); } } } var result = new BaseScenarioResult(); if (!freeVillages?.Any() ?? true) { await _bot.SendTextMessageAsync(_botUser.ChatId, $"All villages with building feature of player {_travianUser.UserName} are busy."); await _bot.SendTextMessageAsync(_botUser.ChatId, $"Calculating next build command execution time for player {_travianUser.UserName}."); } else { var i = 0; var allBuidlgins = await _buildingRepository.GetAllBuildings(); while ((freeVillages?.Any() ?? false) && i++ < buildVillages.Count) { var allActions = new List <BuildAction>(); foreach (var village in freeVillages) { var(hasMoreToBuild, actions) = await _actionProvider.GetBuildActions(village, allBuidlgins); if (!hasMoreToBuild) { await _bot.SendTextMessageAsync(_botUser.ChatId, $"No actions needed for village {village.Name} of player {village.PlayerName}. Swithching off the Build Feature."); try { var villageToUpdate = await _villageRepository.GetVillage(village.CoordinateX, village.CoordinateY); villageToUpdate.IsBuildFeatureOn = false; await _villageRepository.UpdateInfos(new List <VillageModel> { villageToUpdate }); } catch (Exception exc) { _logger.LogError(exc, exc.Message); await _bot.SendTextMessageAsync(_botUser.ChatId, $"Unable to update {village.Name} of player {village.PlayerName}. Check Logs."); } } else { allActions.AddRange(actions); } } if (allActions.Any()) { result = await _gameplayClient.ExecuteActions(_travianUser, allActions); var buildErrors = result.Errors .Where(x => x is BuildScenarioError) .Cast <BuildScenarioError>(); if (buildErrors.Any()) { var notEnoughRes = buildErrors .Where(x => (x as BuildScenarioError).BuildErrorType == BuildErrorType.NotEnoughResources); if (notEnoughRes.Any()) { foreach (var n in notEnoughRes) { var updatedVillage = result.Villages.First(x => x.CoordinateX == n.Village.CoordinateX && x.CoordinateY == n.Village.CoordinateY); await SendResources(allVillages.ToList(), updatedVillage); } } var noSpaceInQueue = buildErrors .Where(x => (x as BuildScenarioError).BuildErrorType == BuildErrorType.NoSpaceInQueue); if (noSpaceInQueue.Any()) { foreach (var n in noSpaceInQueue) { var errorVillage = result.Villages.First(x => x.CoordinateX == n.Village.CoordinateX && x.CoordinateY == n.Village.CoordinateY); errorVillage.CanBuild = false; } } } freeVillages = result.Villages.Where(x => x.CanBuild).ToList(); } } } var max = infos.Villages.Count > result.Villages.Count ? infos.Villages.Count : result.Villages.Count; TimeSpan nextRun = TimeSpan.MaxValue; for (var j = 0; j < max; j++) { if (j < infos.Villages.Count) { if (infos.Villages[j].Dorf1BuildTimeLeft.HasValue && infos.Villages[j].Dorf1BuildTimeLeft.Value > TimeSpan.Zero && infos.Villages[j].Dorf1BuildTimeLeft.Value < nextRun) { nextRun = infos.Villages[j].Dorf1BuildTimeLeft.Value; } } if (j < result.Villages.Count) { if (result.Villages[j].Dorf1BuildTimeLeft.HasValue && result.Villages[j].Dorf1BuildTimeLeft.Value > TimeSpan.Zero && result.Villages[j].Dorf1BuildTimeLeft.Value < nextRun) { nextRun = result.Villages[j].Dorf1BuildTimeLeft.Value; } } } if (nextRun < TimeSpan.MaxValue) { var waitingForResources = buildVillages ?.Where(x => x.IsWaitingForResources && x.NextBuildingPlanExecutionTime.HasValue) ?.Select(x => x.NextBuildingPlanExecutionTime.Value) ?.ToList(); var nextRunDateTime = DateTimeOffset.Now + nextRun; var nearestResourcesDelivery = (waitingForResources?.Any() ?? false) ? waitingForResources.Min() : DateTimeOffset.MaxValue; var cmd = _commandFactory.GetQueueableCommand(nameof(BuildCommand), _botUser.ChatId); cmd.Start = (nextRunDateTime < nearestResourcesDelivery ? nextRunDateTime : nearestResourcesDelivery) + TimeSpan.FromSeconds(2); await cmd.Execute(); } else { await _bot.SendTextMessageAsync(_botUser.ChatId, $"Unable to calculate next build command execution time for player {_travianUser.UserName}"); } }
protected abstract Task ExecuteJob(JobExecutionData jobExecutionData);