Exemple #1
0
        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));
        }
Exemple #2
0
        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);
        }
Exemple #3
0
        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);
        }
Exemple #4
0
        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);
        }
Exemple #5
0
        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);
        }
Exemple #6
0
 /// <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));
 }
Exemple #7
0
        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);
                }
            }
        }