public static List <SmProduct> Build(ILogger logger, List <Product> products, List <ProductHierarchy> productHierarchies, List <ProductPriceLadder> productPriceLadders, List <PriceLadderValue> priceLadderValues, Dictionary <int, decimal> hierarchySellThrough, Dictionary <int, Tuple <int, decimal> > productSalesTax, List <ProductParameterValues> productParameterValues, List <ProductMarkdownConstraint> productMarkdownConstraint, List <ProductSalesFlexFactor> salesFlexFactor, List <ProductMinimumAbsolutePriceChange> productMinimumAbsolutePriceChange, List <ProductWeekParameterValues> productWeekParameterValues, List <ProductWeekMarkdownTypeParameterValues> productWeekMarkdownTypeParameterValues) { var priceLadders = SmPriceLadder.Build(priceLadderValues); return(products? .Select(x => Build(logger, x, productHierarchies, productPriceLadders, priceLadders, hierarchySellThrough, productSalesTax, productParameterValues, productMarkdownConstraint, salesFlexFactor, productMinimumAbsolutePriceChange, productWeekParameterValues, productWeekMarkdownTypeParameterValues)) .Where(x => x != null) .ToList()); }
public static List <Tuple <int, decimal> > Optimise(SmDenseSchedule schedule, SmPriceLadder priceLadder) { var weeks = schedule.MarkdownWeeks; var prices = priceLadder.Values; var width = weeks.Length; var height = prices.Length; var markdownCount = weeks.Length; var minDepths = weeks.Select(x => schedule.Constraints?.SingleOrDefault(y => y.Week == x)?.Min).ToArray(); var maxDepths = weeks.Select(x => schedule.Constraints?.SingleOrDefault(y => y.Week == x)?.Max).ToArray(); if (prices.Length < markdownCount) { throw new ArgumentException("Insufficient number of price paths to satisfy markdown count requirement", nameof(prices)); } var weekDiscounts = new List <Tuple <int, decimal> >(); var previousDiscounts = new List <decimal>(); for (var w = 0; w < width; w++) { var week = weeks[w]; var discounts = new List <decimal>(); for (var p = 0; p < height; p++) { var discount = prices[p]; var isLong = width - w >= markdownCount - p; var isShort = height - p >= markdownCount - w; var isLow = minDepths[w] != null && discount < minDepths[w]; var isHigh = maxDepths[w] != null && discount > maxDepths[w]; var isMarkdown = !previousDiscounts.Any() || discount > previousDiscounts[0]; if (isLong && isShort && !isHigh & !isLow && isMarkdown) { discounts.Add(discount); } } weekDiscounts.AddRange(discounts.Select(x => Tuple.Create(week, x))); previousDiscounts = discounts; } return(weekDiscounts); }
public SmSchedulePricePath[] Expand(SmPriceLadder ladder) { var weekPrices = Optimise(this, ladder); return(CrossProduct(MarkdownWeeks, WeekMin, WeekMax, ladder.Type, weekPrices)); }