public void DifferentMarginTest() { var request = new Request(); request.ProductHierarchy = new List<Relation>(this.hierarchy); request.GeographyHierarchy = new List<Relation>(this.hierarchy); request.SalesComponentHierarchy = new List<Relation>(this.hierarchy); request.PeriodHierarchy = new List<Relation>(); request.Sales = new List<ConcreteFact>(); request.Sales.AddRange(makeDuetos(4, 7, 4, 7, 4, 7, 1, 10, 100)); //including facts for each period request.Margins = Enumerable.Range(1, 10).SelectMany(r => { var facts = new List<NullableFact>(); facts.Add(new NullableFact() { TimeId = (short)r, ProductId = 2, Value = 0.15f }); facts.Add(new NullableFact() { TimeId = (short)r, ProductId = 3, Value = 0.25f }); return facts; }).ToList(); request.Spend = new List<NullableFact>() { new NullableFact() { ProductId = 1, GeographyId = 1, Value = 100 } }; // no adjustments request.Adjustments = null; var calculator = new CalculatorService(); var result = calculator.CalculateRoi(request); Assert.AreEqual(1, result.Count); Assert.AreEqual(128f, result.Single().Value, 0.0001); }
public List<NullableFact> CalculateRoi(Request request) { var products = new Hierarchy(request.ProductHierarchy); var geographies = new Hierarchy(request.GeographyHierarchy); var causals = new Hierarchy(request.SalesComponentHierarchy); var periods = new Hierarchy(request.PeriodHierarchy); var adjuster = new Adjuster(products, geographies, causals, periods); var sales = adjuster.AdjustSales(request); var aggregatedDuetos = adjuster.AggregateSales(request.Spend, sales); var rois = request.Spend.Join(aggregatedDuetos, s => new { s.ProductId, s.GeographyId, CausalId = s.SalesComponentId, s.TimeId }, adt => new { adt.ProductId, adt.GeographyId, CausalId = adt.SalesComponentId, adt.TimeId }, (s, adt) => new NullableFact() { ProductId = s.ProductId, GeographyId = s.GeographyId, SalesComponentId = s.SalesComponentId, TimeId = s.TimeId, Value = adt.Value / s.Value }); return rois.ToList(); }
public List<ConcreteFact> AdjustSales(Request roiRequest) { var marginLookup = new FactLookup(roiRequest.Margins, products, geographies, causals, periods); var spendPeriods = roiRequest.Spend.Select(s => s.TimeId).ToList(); if (!spendPeriods.Any()) return new List<ConcreteFact>(); // we can genericize this when more adjustments come online List<NullableFact> adjustment = null; var adjustmentLookup = new FactLookup(adjustment, products, geographies, causals, periods); var timeIsNull = spendPeriods.All(s => s == null); var dueTos = roiRequest.Sales.Where(d => timeIsNull || spendPeriods.Contains(d.TimeId)); dueTos.AsParallel().ForAll(item => { var margin = marginLookup.GetParent(item, false); var adjustmentFactor = adjustmentLookup.GetParent(item, false, 1.0f, false); item.Value *= margin; item.Value *= adjustmentFactor; }); return roiRequest.Sales; }
public void IntegratedCalculateRoi_ComplexTest() { var request = new Request(); request.ProductHierarchy = new List<Relation>(this.hierarchy); request.GeographyHierarchy = new List<Relation>(this.hierarchy); request.SalesComponentHierarchy = new List<Relation>(); request.PeriodHierarchy = new List<Relation>(); request.Sales = new List<ConcreteFact>(); request.Sales.AddRange(makeDuetos(2, 2, 2, 2, 1, 1, 1, 10, 50)); request.Sales.AddRange(makeDuetos(2, 2, 2, 2, 2, 2, 1, 10, 120)); request.Sales.AddRange(makeDuetos(2, 2, 2, 2, 3, 3, 6, 10, 95)); request.Margins = Enumerable.Range(1, 10).Select(r => new NullableFact() { TimeId = (short)r, Value = 0.15f }).ToList(); request.Spend = new List<NullableFact>() { new NullableFact() { ProductId = 1, GeographyId = 1, Value = 100 } }; // no adjustments request.Adjustments = null; var calculator = new CalculatorService(); var result = calculator.CalculateRoi(request); Assert.AreEqual(1, result.Count); Assert.AreEqual(3.2625f, result.Single().Value, 0.01); }
public void DifferentMarginTest_WithDiscreteGaps() { var request = new Request(); request.ProductHierarchy = new List<Relation>(this.hierarchy); request.GeographyHierarchy = new List<Relation>(this.hierarchy); request.SalesComponentHierarchy = new List<Relation>(this.hierarchy); request.PeriodHierarchy = new List<Relation>(); request.Sales = new List<ConcreteFact>(); request.Sales.AddRange(makeDuetos(4, 7, 4, 7, 4, 7, 1, 10, 1)); // no product 7 in geog 7 // will exclude for all 4 sales components x 10 weeks (40 leaf) request.Sales.RemoveAll(d => d.ProductId == 7 && d.GeographyId == 7); // causal 6 not run in geogs 4,5 // will exclude for all 4 products x 10 weeks in both geogs (80 leaf) request.Sales.RemoveAll(d => d.SalesComponentId == 6 && (d.GeographyId == 4 || d.GeographyId == 5)); //including facts for each period request.Margins = Enumerable.Range(1, 10).SelectMany(r => { var facts = new List<NullableFact>(); facts.Add(new NullableFact() { TimeId = (short)r, ProductId = 2, Value = 0.15f }); facts.Add(new NullableFact() { TimeId = (short)r, ProductId = 3, Value = 0.25f }); return facts; }).ToList(); request.Spend = new List<NullableFact>() { new NullableFact() { ProductId = 1, GeographyId = 1, Value = 100 } }; // no adjustments request.Adjustments = null; var calculator = new CalculatorService(); var result = calculator.CalculateRoi(request); Assert.AreEqual(1, result.Count); Assert.AreEqual(1.02f, result.Single().Value, 0.0001); }
public void IntegratedTest() { var request = new Request(); request.ProductHierarchy = new List<Relation>(this.hierarchy); request.GeographyHierarchy = new List<Relation>(this.hierarchy); request.SalesComponentHierarchy = new List<Relation>(); request.PeriodHierarchy = new List<Relation>(); request.Sales = new List<ConcreteFact>(); request.Sales.AddRange(makeDuetos(4, 7, 4, 7, 4, 7, 1, 10, 100)); request.Margins = new List<NullableFact>() { new NullableFact() { Value = 0.15f } }; request.Spend = new List<NullableFact>() { new NullableFact() { ProductId = 1, GeographyId = 1, Value = 100 } }; var calculator = new CalculatorService(); var adjustments = new List<NullableFact>(); for (short g = 4; g <= 7; g++) for (short s = 4; s <= 7; s++) { adjustments.Add(new NullableFact() { GeographyId = g, SalesComponentId = s, Value = 1.5f }); } request.Adjustments = new List<Adjustment>() { new Adjustment() { AdjustmentType = AdjustmentType.Adjustment, Facts = adjustments } }; var result = calculator.CalculateRoi(request); // Missing assert Assert.Fail(); }