public SmCalcRecommendation(SmScenario scenario, SmDenseSchedule schedule, decimal[] pricePath, int revisionId, bool isCsp = false) { ScheduleId = schedule.ScheduleNumber; ScheduleMask = scenario.ScheduleMask; ScheduleMarkdownCount = schedule.MarkdownCount; IsCsp = isCsp; PricePath = pricePath; RevisionId = revisionId; // Defaults Rank = 0; TotalMarkdownCount = 0; TerminalStock = 0; TotalRevenue = 0M; TotalCost = 0M; TotalMarkdownCost = 0M; FinalDiscount = null; StockValue = 0M; EstimatedProfit = 0M; EstimatedSales = 0M; SellThroughRate = 0M; SellThroughTarget = 0M; FinalMarkdownType = MarkdownType.None; Projections = new List <SmCalcRecommendationProjection>(); }
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); }