public void Get_Schedules_Will_Return_All_Schedules() { // 10 .. 13 = 4 weeks inclusive // 4 weeks as flags = 1 .. 1111 // 1 0001 // 2 0010 // 3 0011 // 4 0100 // 5 0101 // 6 0110 // 7 0111 // 8 1000 // 9 1001 // 10 1010 // 11 1011 // 12 1100 // 13 1101 // 14 1110 // 15 1111 var options = new SmScheduleOptions { WeekMin = 10, WeekMax = 13, WeeksAllowed = 0, ExcludeConsecutiveWeeks = false }; var result = new ScheduleService().GetSchedules(options); result .Select(x => x.ScheduleNumber) .ShouldAllBeEquivalentTo(Enumerable.Range(1, 15)); }
public void Get_Schedules_Will_Return_All_Schedules_With_Allowed_Mask() { var mask = 255; var options = new SmScheduleOptions { WeekMin = 10, WeekMax = 13, WeeksAllowed = mask, ExcludeConsecutiveWeeks = false }; var expected = Enumerable.Range(1, 15); var result = new ScheduleService().GetSchedules(options); result .Select(x => x.ScheduleNumber) .ShouldAllBeEquivalentTo(expected); }
public void Get_Schedules_Will_Require_Weeks() { // 1 0001 // 2 0010 // 3 0011 // 4 0100 // 5 0101 // 6 0110 o // 7 0111 o // 8 1000 // 9 1001 // 10 1010 // 11 1011 // 12 1100 // 13 1101 // 14 1110 o // 15 1111 o var mask = Convert.ToInt32("0110", 2); // 6 var options = new SmScheduleOptions { WeekMin = 10, WeekMax = 13, WeeksRequired = mask, ExcludeConsecutiveWeeks = false }; var expected = new List <int> { 6, 7, 14, 15 }; var result = new ScheduleService().GetSchedules(options); result .Select(x => x.ScheduleNumber) .ShouldAllBeEquivalentTo(expected); }
public void Get_Schedules_Will_Allow_High_And_Low_Schedules() { // 1 0001 o // 2 0010 // 3 0011 // 4 0100 // 5 0101 // 6 0110 // 7 0111 // 8 1000 o // 9 1001 o // 10 1010 // 11 1011 // 12 1100 // 13 1101 // 14 1110 // 15 1111 var mask = Convert.ToInt32("1001", 2); // 9 var options = new SmScheduleOptions { WeekMin = 10, WeekMax = 13, WeeksAllowed = mask, ExcludeConsecutiveWeeks = false }; var expected = new List <int> { 1, 8, 9 }; var result = new ScheduleService().GetSchedules(options); result .Select(x => x.ScheduleNumber) .ShouldAllBeEquivalentTo(expected); }
public void Get_Schedules_Will_Filter_Consecutive_Schedules() { // 1 0001 o // 2 0010 o // 3 0011 // 4 0100 o // 5 0101 o // 6 0110 // 7 0111 // 8 1000 o // 9 1001 o // 10 1010 o // 11 1011 // 12 1100 // 13 1101 // 14 1110 // 15 1111 var options = new SmScheduleOptions { WeekMin = 10, WeekMax = 13, WeeksAllowed = 0, ExcludeConsecutiveWeeks = true }; var expected = new List <int> { 1, 2, 4, 5, 8, 9, 10 }; var result = new ScheduleService().GetSchedules(options); result .Select(x => x.ScheduleNumber) .ShouldAllBeEquivalentTo(expected); }
/// <summary> /// Returns all schedule permutations from 1..n /// </summary> /// <param name="options"></param> /// <returns>A list of dense schedules defining the week</returns> public List <SmDenseSchedule> GetSchedules(SmScheduleOptions options) { return(Generate(options.WeekMin, options.WeekCount, options.WeeksAllowed, options.WeeksRequired, options.ExcludeConsecutiveWeeks, options.Constraints)); }
public static async Task Run(ILogger logger, IMarkdownFunctionSettings settings, Container container) { logger.Information("Running. Settings: {@Settings}", settings); var canUpload = false; var statsInterval = TimeSpan.FromSeconds(10); var cancellationSource = new CancellationTokenSource(); var cancellationToken = cancellationSource.Token; var calcService = container.GetInstance <IMarkdownService>(); var functionService = container.GetInstance <IFunctionService>(); var scenarioService = container.GetInstance <IScenarioService>(); var scheduleService = container.GetInstance <IScheduleService>(); try { // Inform AppDb we've started logger.Information("Calculate start (getting data and scenarios)"); await functionService.CalculateStart(settings.ScenarioId, settings.PartitionCount, settings.PartitionId); // Todo: exclude products where markdown count > max markdown var model = await scenarioService.GetModelData(settings); var data = await scenarioService.GetScenarioData(settings, settings.PartitionId); var scenario = data.Item1; var products = data.Item2; var modelId = settings.ModelId; var revisionId = 0; var scheduleOptions = new SmScheduleOptions { WeekMin = scenario.ScheduleWeekMin, WeekMax = scenario.ScheduleWeekMax, WeeksAllowed = scenario.ScheduleMask, ExcludeConsecutiveWeeks = true }; logger.Information("Getting schedules with {@Options}", scheduleOptions); var schedules = scheduleService.GetSchedules(scheduleOptions); logger.Information($"Got {schedules.Count} schedules"); var decayHierarchies = model.DecayHierarchies; var elasticityHierarchies = model.ElasticityHierarchies; var recommendationResults = new ConcurrentBag <SmCalcProduct>(); // Setup calculation var stats = new CalculationStatistics(logger, statsInterval); stats.AddTotalProductCount(products.Count); stats.Start(); logger.Information("Product loop start"); { await functionService.CalculateUpdate( settings.ScenarioId, settings.PartitionCount, settings.PartitionId, products.Count, stats.ProductCount, 0, stats.PricePaths, (int)stats.HierarchyErrorCount); // Start Parallel.ForEach(products, x => { stats.StartCalculation(); var product = calcService.Calculate(scenario, modelId, revisionId, schedules, decayHierarchies, elasticityHierarchies, x, null, cancellationToken); stats.FinishCalculation(); stats.AddProducts(1L); stats.AddPricePaths(product.ScheduleCrossProductCount); stats.AddRecommendations(product.Recommendations.Count); recommendationResults.Add(product); }); } logger.Information("Product loop finish"); stats.Stop(); // Save data logger.Information("Calculate save."); var s3Path = SmS3Path.ScenarioPartitionPath(SmS3PathName.Output, settings); await calcService.Save(recommendationResults.ToList(), s3Path); logger.Information("Calculate saved."); // Inform AppliationDb we've finished var productRate = stats.ProductCount / stats.ElapsedSeconds; var productCount = stats.ProductCount; var pricePathCount = stats.PricePaths; var hierarchyErrorCount = stats.HierarchyErrorCount; var finishResult = await functionService.CalculateFinish(settings.ScenarioId, settings.PartitionCount, settings.PartitionId, products.Count, productCount, productRate, pricePathCount, (int)hierarchyErrorCount); // Detect finish state logger.Information("Finish state: {@Model}", finishResult); if (finishResult.SuccessCount == finishResult.FunctionInstanceTotal) { canUpload = true; logger.Information("This function is the last partition, where UploadQueue == Total"); } logger.Information("Finished"); } catch (Exception ex) { cancellationSource.Cancel(); await functionService.CalculateError(settings.ScenarioId, settings.PartitionCount, settings.PartitionId, ex.ToString()); throw; } if (canUpload && settings.Upload) { logger.Information("Launching upload function"); var lambdaClient = container.GetInstance <IAmazonLambda>(); for (var i = 1; i <= settings.PartitionCount; i++) { await lambdaClient.InvokeAsync(new InvokeRequest { FunctionName = settings.FunctionName, InvocationType = "Event", Payload = JsonConvert.SerializeObject(new Dictionary <string, object> { { "Program", "upload" }, { "ScenarioId", settings.ScenarioId }, { "OrganisationId", settings.OrganisationId }, { "UserId", settings.UserId }, { "PartitionId", i }, { "PartitionCount", settings.PartitionCount } }) }, cancellationToken); } } }