public ForecastDto Calculate_forecast(string historyId, FeatureDto[] features)
        {
            var history = _repo.Load_history_by_id(historyId);

            Update_lastused(history);

            var forecast        = _forecasting.Calculate(history.HistoricalData, Map_features());
            var limitedForecast = Limit_to_range(forecast, 0.5f, 1.0f);

            return(new ForecastDto {
                Id = history.Id,
                Distribution = limitedForecast.Distribution.Select(d => new ForecastDto.PossibleOutcomeDto {
                    Prognosis = d.Prognosis,
                    Count = d.Count,
                    CummulatedProbability = d.CummulatedProbability
                }).ToArray(),
            });


            Forecast Limit_to_range(Forecast unlimitedForecast, float pMin, float pMax)
            {
                return(new Forecast {
                    Features = unlimitedForecast.Features,
                    Distribution = unlimitedForecast.Distribution.Where(e => pMin <= e.CummulatedProbability &&
                                                                        e.CummulatedProbability <= pMax)
                                   .ToArray()
                });
            }

            Feature[] Map_features()
            => features.Select(f => new Feature {
                Tags = f.Tags, Quantity = f.Quantity
            }).ToArray();

            void Update_lastused(History h)
            {
                h.LastUsed = DateTime.Now.ToUniversalTime();
                _repo.Store_history(h);
            }
        }
        public void Forecast()
        {
            var rndNumbers = new Queue <int>(new[] { 0, 2, 1, 1, 5, 3, 3, 4, 2 });
            var montecarlo = new MonteCarloSimulation(_ => rndNumbers.Dequeue());
            var sut        = new Forecasting(montecarlo, 3, 2);

            //TODO: integrationstest forecasting
            var historicalData = new[] {
                new History.Datapoint {
                    Value = 1f, Tags = new[] { "a" }
                },
                new History.Datapoint {
                    Value = 2f, Tags = new[] { "a" }
                },
                new History.Datapoint {
                    Value = 2f, Tags = new[] { "a" }
                },
                new History.Datapoint {
                    Value = 3f, Tags = new[] { "a" }
                },
                new History.Datapoint {
                    Value = 3f, Tags = new[] { "a" }
                },
                new History.Datapoint {
                    Value = 4f, Tags = new[] { "a" }
                },
                new History.Datapoint {
                    Value = 10f, Tags = new[] { "b" }
                },
                new History.Datapoint {
                    Value = 10f, Tags = new[] { "b" }
                },
                new History.Datapoint {
                    Value = 20f, Tags = new[] { "b" }
                },
                new History.Datapoint {
                    Value = 20f, Tags = new[] { "b" }
                },
                new History.Datapoint {
                    Value = 30f, Tags = new[] { "b" }
                }
            };
            var features = new[] {
                new Feature {
                    Quantity = 2, Tags = new[] { "a" }
                },
                new Feature {
                    Quantity = 1, Tags = new[] { "b" }
                },
            };

            /*
             * 3 Simulationen, 2 Intervalle
             * 2a(0..5), 1b(0..4)
             *
             * a: 0=1  1=2  3=3
             * a: 2=2  5=4  4=3
             * b: 1=10 3=20 2=20
             *    13   26   26
             *
             * 26-13=13
             * 13/2=6,5
             * 13..19,5, 19,5..26
             * (13,1,0.33), (26,2,1.0)
             */

            var result = sut.Calculate(historicalData, features);

            foreach (var f in result.Features)
            {
                Debug.WriteLine($"{string.Join(",", f)}");
            }

            foreach (var po in result.Distribution)
            {
                Debug.WriteLine($"{po.Prognosis}, {po.CummulatedProbability}");
            }

            Assert.AreEqual(new[] { "a", "a", "b" }, result.Features);
            Assert.AreEqual(2, result.Distribution.Length);
            Assert.AreEqual(3, result.Distribution.Select(g => g.Count).Sum());
            Assert.AreEqual(13f, result.Distribution[0].Prognosis);
            Assert.AreEqual(1, result.Distribution[0].Count);
            Assert.AreEqual(0.33f, result.Distribution[0].CummulatedProbability, 0.01f);
            Assert.AreEqual(26f, result.Distribution[1].Prognosis);
            Assert.AreEqual(2, result.Distribution[1].Count);
            Assert.AreEqual(1f, result.Distribution[1].CummulatedProbability, 0.01f);
        }