public void Test_One_Village_With_Building_Being_Built()
        {
            var testVillage   = PrepareTestOneVillage();
            var resultVillage = _serviceProviderBuilder.Mapper.Map <Village>(testVillage);
            var finishTime    = TimeSpan.FromMinutes(30);

            resultVillage.Dorf1BuildTimeLeft = finishTime;
            resultVillage.CanBuild           = false;
            resultVillage.Resources          = new Resources
            {
                Lumber = 100,
                Clay   = 100,
                Iron   = 100,
                Crop   = 100
            };
            resultVillage.Warehourse = 800;
            resultVillage.Granary    = 800;

            var infoResult = Builder <BaseScenarioResult> .CreateNew()
                             .With(x => x.Success  = true)
                             .With(x => x.Villages = new List <Village> {
                resultVillage
            })
                             .Build();

            var gamePlayMock = new Mock <IGameplayClient>();

            gamePlayMock.Setup(x => x.ExecuteActions(It.IsAny <TravianUser>(), It.IsAny <IEnumerable <GameAction> >()))
            .Returns(Task.FromResult(infoResult));
            gamePlayMock.Setup(x => x.ExecuteActions(It.IsAny <TravianUser>(), It.IsAny <IEnumerable <BuildAction> >()))
            .Returns(Task.FromResult(new BaseScenarioResult()));
            _serviceProviderBuilder.WithService(gamePlayMock.Object);

            var cmd     = new FakeCommand();
            var cmdMock = new Mock <ICommandFactory>();

            cmdMock.Setup(x => x.GetQueueableCommand(nameof(BuildCommand), It.IsAny <long>()))
            .Returns(cmd);

            _serviceProviderBuilder.WithService(cmdMock.Object);

            var job  = new BuildingPlanExecutionJob(_serviceProviderBuilder.Build());
            var data = new JobExecutionData
            {
                TravianUser = FakeDataProvider.GetUser(PlayerStatus.ALL_QUIET, true),
                JobType     = typeof(BuildingPlanExecutionJob)
            };

            var now = DateTimeOffset.Now;

            Assert.DoesNotThrowAsync(async() => await job.Execute(data));

            _serviceProviderBuilder.LoggerMock.Verify(x => x.Log(
                                                          LogLevel.Error,
                                                          It.IsAny <EventId>(),
                                                          It.IsAny <It.IsAnyType>(),
                                                          It.IsAny <Exception>(),
                                                          (Func <It.IsAnyType, Exception, string>)It.IsAny <object>()), Times.Never);
            gamePlayMock.Verify(x => x.ExecuteActions(It.IsAny <TravianUser>(), It.IsAny <IEnumerable <GameAction> >()), Times.Once);
            gamePlayMock.Verify(x => x.ExecuteActions(It.IsAny <TravianUser>(), It.IsAny <IEnumerable <BuildAction> >()), Times.Never);

            var diff = cmd.Start - now - finishTime;

            Assert.IsTrue(diff <= TimeSpan.FromSeconds(3)); // will fail while debugging because of date time now
            Assert.IsTrue(diff >= TimeSpan.FromSeconds(2));
        }
        public async Task Test_Three_Villages_Build_Action_Returns_Error(BuildErrorType errorType)
        {
            var testVillage   = GetVillage(isBuildingFeatureOn: true);
            var resultVillage = _serviceProviderBuilder.Mapper.Map <Village>(testVillage);
            var finishTime    = TimeSpan.FromMinutes(30);

            resultVillage.Dorf1BuildTimeLeft = finishTime;
            resultVillage.CanBuild           = true;
            resultVillage.Resources          = new Resources
            {
                Lumber = 100,
                Clay   = 100,
                Iron   = 100,
                Crop   = 100
            };
            resultVillage.Warehourse = 800;
            resultVillage.Granary    = 800;

            var testVillage2   = GetVillage(isBuildingFeatureOn: true);
            var resultVillage2 = _serviceProviderBuilder.Mapper.Map <Village>(testVillage2);
            var finishTime2    = TimeSpan.FromMinutes(45);

            resultVillage2.Dorf1BuildTimeLeft = finishTime2;
            resultVillage2.CanBuild           = true;
            resultVillage2.Resources          = new Resources
            {
                Lumber = 100,
                Clay   = 100,
                Iron   = 100,
                Crop   = 100
            };
            resultVillage2.Warehourse = 800;
            resultVillage2.Granary    = 800;

            var testVillage3 = GetVillage(isBuildingFeatureOn: false);

            resultVillage2.Resources = new Resources
            {
                Lumber = 100,
                Clay   = 100,
                Iron   = 100,
                Crop   = 100
            };
            resultVillage2.Warehourse = 800;
            resultVillage2.Granary    = 800;

            var allVillages = new List <VillageModel> {
                testVillage, testVillage2, testVillage3
            };
            var villageRepo = new Mock <IVillageRepository>();

            villageRepo.Setup(x => x.GetVillages(_serviceProviderBuilder.TravianUser.UserName))
            .Returns(Task.FromResult((IEnumerable <VillageModel>)allVillages));
            villageRepo.Setup(x => x.GetVillage(It.IsAny <int>(), It.IsAny <int>()))
            .Returns((int x, int y) =>
            {
                return(Task.FromResult(allVillages.FirstOrDefault(z => z.CoordinateX == x && z.CoordinateY == y)));
            });
            _serviceProviderBuilder.WithService(villageRepo.Object);

            var infoResult = Builder <BaseScenarioResult> .CreateNew()
                             .With(x => x.Success  = true)
                             .With(x => x.Villages = new List <Village> {
                resultVillage2
            })
                             .Build();

            var actionProviderMock = new Mock <IActionProvider>();

            actionProviderMock.Setup(x => x.GetBuildActions(resultVillage, It.IsAny <IEnumerable <BuildingModel> >()))
            .Returns(Task.FromResult((true, (IEnumerable <BuildAction>) new List <BuildAction> {
                new BuildAction
                {
                    Village = resultVillage,
                    BuildingId = "test",
                    BuildingSlot = "test",
                    Level = 1
                }
            })));
            actionProviderMock.Setup(x => x.GetBuildActions(resultVillage2, It.IsAny <IEnumerable <BuildingModel> >()))
            .Returns(Task.FromResult((true, (IEnumerable <BuildAction>) new List <BuildAction> {
                new BuildAction
                {
                    Village = resultVillage2,
                    BuildingId = "test",
                    BuildingSlot = "test",
                    Level = 1
                }
            })));
            _serviceProviderBuilder.WithService(actionProviderMock.Object);

            var buildActionResult = Builder <BaseScenarioResult> .CreateNew()
                                    .With(x => x.Success  = true)
                                    .With(x => x.Villages = new List <Village>
            {
                Builder <Village>
                .CreateNew()
                .With(y => y.CanBuild            = false)
                .With(y => y.Dorf1BuildTimeLeft  = TimeSpan.FromMinutes(2))
                .With(y => y.CoordinateX         = resultVillage.CoordinateX)
                .With(y => y.CoordinateY         = resultVillage.CoordinateY)
                .With(y => y.Warehourse          = 800)
                .With(y => y.Granary             = 800)
                .With(y => y.Resources           = Builder <Resources> .CreateNew().Build())
                .With(y => y.ResourcesProduction = Builder <Resources> .CreateNew().Build())
                .Build(),
                Builder <Village>
                .CreateNew()
                .With(y => y.CanBuild           = false)
                .With(y => y.Dorf1BuildTimeLeft = TimeSpan.FromMinutes(5))
                .With(y => y.CoordinateX        = resultVillage2.CoordinateX)
                .With(y => y.CoordinateY        = resultVillage2.CoordinateY)
                .Build()
            })
                                    .With(x => x.Errors = new List <ScenarioError>
            {
                Builder <BuildScenarioError>
                .CreateNew()
                .With(y => y.BuildErrorType = errorType)
                .With(y => y.Village        = resultVillage)
                .Build()
            })
                                    .Build();

            var gamePlayMock = new Mock <IGameplayClient>();

            gamePlayMock.Setup(x => x.ExecuteActions(It.IsAny <TravianUser>(), It.IsAny <IEnumerable <GameAction> >()))
            .Returns(Task.FromResult(infoResult));
            gamePlayMock.Setup(x => x.ExecuteActions(It.IsAny <TravianUser>(), It.IsAny <IEnumerable <BuildAction> >()))
            .Returns(Task.FromResult(buildActionResult));
            _serviceProviderBuilder.WithService(gamePlayMock.Object);

            var cmd     = new FakeCommand();
            var cmdMock = new Mock <ICommandFactory>();

            cmdMock.Setup(x => x.GetQueueableCommand(nameof(BuildCommand), It.IsAny <long>()))
            .Returns(cmd);
            _serviceProviderBuilder.WithService(cmdMock.Object);

            var job         = new BuildingPlanExecutionJob(_serviceProviderBuilder.Build());
            var travianUser = FakeDataProvider.GetUser(PlayerStatus.ALL_QUIET, true);
            var data        = new JobExecutionData
            {
                TravianUser = travianUser,
                JobType     = typeof(BuildingPlanExecutionJob)
            };

            var now = DateTimeOffset.Now;

            Assert.DoesNotThrowAsync(async() => await job.Execute(data));

            _serviceProviderBuilder.LoggerMock.Verify(x => x.Log(
                                                          LogLevel.Error,
                                                          It.IsAny <EventId>(),
                                                          It.IsAny <It.IsAnyType>(),
                                                          It.IsAny <Exception>(),
                                                          (Func <It.IsAnyType, Exception, string>)It.IsAny <object>()), Times.Never);

            gamePlayMock.Verify(x => x.ExecuteActions(It.IsAny <TravianUser>(), It.IsAny <IEnumerable <BuildAction> >()), Times.Once);

            var expected = errorType == BuildErrorType.NoSpaceInQueue
                ? TimeSpan.FromMinutes(2)
                : Calculator.CalculateTimeForUnit(
                resultVillage,
                _serviceProviderBuilder.Mapper.Map <Village>(testVillage3),
                await _serviceProviderBuilder.UnitRepository.GetTrader(travianUser.PlayerData.Tribe));

            var diff = cmd.Start - now - TimeSpan.FromMinutes(2);

            Assert.IsTrue(diff <= TimeSpan.FromSeconds(3)); // will fail while debugging because of date time now
            Assert.IsTrue(diff >= TimeSpan.FromSeconds(2));

            buildActionResult = Builder <BaseScenarioResult> .CreateNew()
                                .With(x => x.Success  = true)
                                .With(x => x.Villages = new List <Village>
            {
                Builder <Village>
                .CreateNew()
                .With(y => y.CanBuild    = true)
                .With(y => y.CoordinateX = resultVillage.CoordinateX)
                .With(y => y.CoordinateY = resultVillage.CoordinateY)
                .Build(),
                Builder <Village>
                .CreateNew()
                .With(y => y.CanBuild           = false)
                .With(y => y.Dorf1BuildTimeLeft = TimeSpan.FromMinutes(5))
                .With(y => y.CoordinateX        = resultVillage2.CoordinateX)
                .With(y => y.CoordinateY        = resultVillage2.CoordinateY)
                .Build()
            })
                                .With(x => x.Errors = new List <ScenarioError>
            {
                Builder <BuildScenarioError>
                .CreateNew()
                .With(y => y.BuildErrorType = errorType)
                .With(y => y.Village        = resultVillage)
                .Build()
            })
                                .Build();

            gamePlayMock = new Mock <IGameplayClient>();
            gamePlayMock.Setup(x => x.ExecuteActions(It.IsAny <TravianUser>(), It.IsAny <IEnumerable <GameAction> >()))
            .Returns(Task.FromResult(infoResult));
            gamePlayMock.Setup(x => x.ExecuteActions(It.IsAny <TravianUser>(), It.IsAny <IEnumerable <BuildAction> >()))
            .Returns(Task.FromResult(buildActionResult));
            _serviceProviderBuilder.WithService(gamePlayMock.Object);

            job = new BuildingPlanExecutionJob(_serviceProviderBuilder.Build());
            now = DateTimeOffset.Now;
            Assert.DoesNotThrowAsync(async() => await job.Execute(data));

            _serviceProviderBuilder.LoggerMock.Verify(x => x.Log(
                                                          LogLevel.Error,
                                                          It.IsAny <EventId>(),
                                                          It.IsAny <It.IsAnyType>(),
                                                          It.IsAny <Exception>(),
                                                          (Func <It.IsAnyType, Exception, string>)It.IsAny <object>()), Times.Never);

            gamePlayMock.Verify(x => x.ExecuteActions(It.IsAny <TravianUser>(), It.IsAny <IEnumerable <BuildAction> >()), Times.Once);

            diff = cmd.Start - now;
            Assert.IsTrue(diff <= TimeSpan.FromSeconds(3)); // will fail while debugging because of date time now
            Assert.IsTrue(diff >= TimeSpan.FromSeconds(2));
        }
        private AbstractJob PrepareOneVillageTest(BaseScenarioResult buildScenarioResult, BaseScenarioResult infoScenarioResult)
        {
            var testVillage   = PrepareTestOneVillage(isBuildingFeatureOn: true);
            var resultVillage = _serviceProviderBuilder.Mapper.Map <Village>(testVillage);
            var finishTime    = TimeSpan.FromMinutes(30);

            resultVillage.Dorf1BuildTimeLeft = finishTime;
            resultVillage.CanBuild           = true;
            resultVillage.Resources          = new Resources
            {
                Lumber = 100,
                Clay   = 100,
                Iron   = 100,
                Crop   = 100
            };
            resultVillage.Warehourse = 800;
            resultVillage.Granary    = 800;

            var infoResult = Builder <BaseScenarioResult> .CreateNew()
                             .With(x => x.Success  = true)
                             .With(x => x.Villages = new List <Village> {
                resultVillage
            })
                             .Build();

            var actionProviderMock = new Mock <IActionProvider>();

            actionProviderMock.Setup(x => x.GetBuildActions(resultVillage, It.IsAny <IEnumerable <BuildingModel> >()))
            .Returns(Task.FromResult((true, (IEnumerable <BuildAction>) new List <BuildAction> {
                new BuildAction
                {
                    Village = resultVillage,
                    BuildingId = "test",
                    BuildingSlot = "test",
                    Level = 1
                }
            })));
            _serviceProviderBuilder.WithService(actionProviderMock.Object);

            var buildActionResult = Builder <BaseScenarioResult> .CreateNew()
                                    .With(x => x.Success  = true)
                                    .With(x => x.Villages = new List <Village>
            {
                Builder <Village>
                .CreateNew()
                .With(y => y.CanBuild           = false)
                .With(y => y.Dorf1BuildTimeLeft = TimeSpan.FromMinutes(5))
                .Build()
            })
                                    .Build();

            var gamePlayMock = new Mock <IGameplayClient>();

            gamePlayMock.Setup(x => x.ExecuteActions(It.IsAny <TravianUser>(), It.IsAny <IEnumerable <GameAction> >()))
            .Returns(Task.FromResult(infoResult));
            gamePlayMock.Setup(x => x.ExecuteActions(It.IsAny <TravianUser>(), It.IsAny <IEnumerable <BuildAction> >()))
            .Returns(Task.FromResult(buildActionResult));
            _serviceProviderBuilder.WithService(gamePlayMock.Object);

            var cmd     = new FakeCommand();
            var cmdMock = new Mock <ICommandFactory>();

            cmdMock.Setup(x => x.GetQueueableCommand(nameof(BuildCommand), It.IsAny <long>()))
            .Returns(cmd);
            _serviceProviderBuilder.WithService(cmdMock.Object);

            var job  = new BuildingPlanExecutionJob(_serviceProviderBuilder.Build());
            var data = new JobExecutionData
            {
                TravianUser = FakeDataProvider.GetUser(PlayerStatus.ALL_QUIET, true),
                JobType     = typeof(BuildingPlanExecutionJob)
            };

            return(job);
        }
        [TestCase(true, BuildErrorType.NoSpaceInQueue)]  // test one village with build action returns no space in queue error
        //[TestCase(true, BuildErrorType.NotEnoughResources)]
        public void Test_One_Village_Rescheduling_Next_Execution_Time(bool noSpaceInQueueError, BuildErrorType buildErrorType)
        {
            var testVillage   = PrepareTestOneVillage(isBuildingFeatureOn: true);
            var resultVillage = _serviceProviderBuilder.Mapper.Map <Village>(testVillage);
            var finishTime    = TimeSpan.FromMinutes(30);

            resultVillage.Dorf1BuildTimeLeft = finishTime;
            resultVillage.CanBuild           = true;
            resultVillage.Resources          = new Resources
            {
                Lumber = 100,
                Clay   = 100,
                Iron   = 100,
                Crop   = 100
            };
            resultVillage.Warehourse = 800;
            resultVillage.Granary    = 800;

            var infoResult = Builder <BaseScenarioResult> .CreateNew()
                             .With(x => x.Success  = true)
                             .With(x => x.Villages = new List <Village> {
                resultVillage
            })
                             .Build();

            var actionProviderMock = new Mock <IActionProvider>();

            actionProviderMock.Setup(x => x.GetBuildActions(resultVillage, It.IsAny <IEnumerable <BuildingModel> >()))
            .Returns(Task.FromResult((true, (IEnumerable <BuildAction>) new List <BuildAction> {
                new BuildAction
                {
                    Village = resultVillage,
                    BuildingId = "test",
                    BuildingSlot = "test",
                    Level = 1
                }
            })));
            _serviceProviderBuilder.WithService(actionProviderMock.Object);

            var buildActionResult = Builder <BaseScenarioResult> .CreateNew()
                                    .With(x => x.Success  = true)
                                    .With(x => x.Villages = new List <Village>
            {
                Builder <Village>
                .CreateNew()
                .With(y => y.CoordinateX        = resultVillage.CoordinateX)
                .With(y => y.CoordinateY        = resultVillage.CoordinateY)
                .With(y => y.CanBuild           = false)
                .With(y => y.Dorf1BuildTimeLeft = TimeSpan.FromMinutes(5))
                .Build()
            })
                                    .With(x => x.Errors = noSpaceInQueueError
                    ? new List <ScenarioError>
            {
                Builder <BuildScenarioError> .CreateNew()
                .With(y => y.BuildErrorType = buildErrorType)
                .With(y => y.Village        = resultVillage)
                .Build()
            }
                    : new List <ScenarioError>())
                                    .Build();

            var gamePlayMock = new Mock <IGameplayClient>();

            gamePlayMock.Setup(x => x.ExecuteActions(It.IsAny <TravianUser>(), It.IsAny <IEnumerable <GameAction> >()))
            .Returns(Task.FromResult(infoResult));
            gamePlayMock.Setup(x => x.ExecuteActions(It.IsAny <TravianUser>(), It.IsAny <IEnumerable <BuildAction> >()))
            .Returns(Task.FromResult(buildActionResult));
            _serviceProviderBuilder.WithService(gamePlayMock.Object);

            var cmd     = new FakeCommand();
            var cmdMock = new Mock <ICommandFactory>();

            cmdMock.Setup(x => x.GetQueueableCommand(nameof(BuildCommand), It.IsAny <long>()))
            .Returns(cmd);
            _serviceProviderBuilder.WithService(cmdMock.Object);

            var job  = new BuildingPlanExecutionJob(_serviceProviderBuilder.Build());
            var data = new JobExecutionData
            {
                TravianUser = FakeDataProvider.GetUser(PlayerStatus.ALL_QUIET, true),
                JobType     = typeof(BuildingPlanExecutionJob)
            };

            var now = DateTimeOffset.Now;

            Assert.DoesNotThrowAsync(async() => await job.Execute(data));

            _serviceProviderBuilder.LoggerMock.Verify(x => x.Log(
                                                          LogLevel.Error,
                                                          It.IsAny <EventId>(),
                                                          It.IsAny <It.IsAnyType>(),
                                                          It.IsAny <Exception>(),
                                                          (Func <It.IsAnyType, Exception, string>)It.IsAny <object>()), Times.Never);

            gamePlayMock.Verify(x => x.ExecuteActions(It.IsAny <TravianUser>(), It.IsAny <IEnumerable <BuildAction> >()), Times.Once);

            var diff = cmd.Start - now - TimeSpan.FromMinutes(5);

            Assert.IsTrue(diff <= TimeSpan.FromSeconds(3)); // will fail while debugging because of date time now
            Assert.IsTrue(diff >= TimeSpan.FromSeconds(2));
        }