/// <summary>
 ///     Get consumption in given time reference frame.
 /// </summary>
 /// <param name="em">Energiemenge</param>
 /// <param name="reference">time reference frame</param>
 /// <returns>Tuple of consumption value and automatically determined unit of measurement</returns>
 public static Tuple <decimal, Mengeneinheit> GetConsumption(this BO.Energiemenge em, ITimeRange reference)
 {
     using (MiniProfiler.Current.Step(nameof(GetConsumption)))
     {
         if (!IsPure(em))
         {
             throw new ArgumentException("The Energiemenge is not pure.");
         }
         if (em.Energieverbrauch.Count == 0)
         {
             return(Tuple.Create(0.0M, Mengeneinheit.ANZAHL));
         }
         ISet <Mengeneinheit> einheiten = new HashSet <Mengeneinheit>(em.Energieverbrauch.Select(x => x.Einheit));
         if (einheiten.Count > 1)
         {
             // z.B. kWh und Wh oder Monat und Jahr... Die liefern IsPure==true.
             throw new NotImplementedException("Converting different units of same type is not supported yet.");
         }
         var v           = em.Energieverbrauch.First();
         var consumption = em.GetConsumption(reference, v.Wertermittlungsverfahren, v.Obiskennzahl, v.Einheit);
         return(Tuple.Create(consumption, v.Einheit));
     }
 }
 /// <summary>
 ///     Get total consumption for given parameters
 /// </summary>
 /// <param name="em">Energiemenge</param>
 /// <param name="wev">type of measurement</param>
 /// <param name="obiskennzahl">OBIS</param>
 /// <param name="me">unit of measurement</param>
 /// <returns>consumption value</returns>
 public static decimal GetTotalConsumption(this BO.Energiemenge em,
                                           Wertermittlungsverfahren wev, string obiskennzahl, Mengeneinheit me)
 {
     return(em.GetConsumption(em.GetTimeRange(), wev, obiskennzahl, me));
 }
Beispiel #3
0
        /// <summary>
        ///     Returns a <see cref="PlausibilityReport" /> that compares <paramref name="emReference" /> with
        ///     <paramref name="emOther" />.
        ///     within the interval defined in <paramref name="timeframe" />.
        /// </summary>
        /// <param name="emReference">reference Energiemenge (reference = used for normalisation)</param>
        /// <param name="emOther">other Energiemenge</param>
        /// <param name="timeframe">
        ///     time frame to be analysed. If null, the overlap of <paramref name="emReference" /> and
        ///     <paramref name="emOther" /> is used.
        /// </param>
        /// <param name="ignoreLocation">
        ///     By default (false) an ArgumentException is thrown if the
        ///     <see cref="BO4E.BO.Energiemenge.LokationsId" /> do not match. Setting this flag suppresses the error.
        /// </param>
        /// <returns>a <see cref="PlausibilityReport" /></returns>
        public static PlausibilityReport GetPlausibilityReport(this BO.Energiemenge emReference,
                                                               BO.Energiemenge emOther, ITimeRange timeframe = null, bool ignoreLocation = false)
        {
            using (MiniProfiler.Current.Step(nameof(GetPlausibilityReport)))
            {
                var trReference = emReference.GetTimeRange();
                var trOther     = emOther.GetTimeRange();
                if (timeframe == null)
                {
                    var overlap = trReference.GetIntersection(trOther);
                    if (!ignoreLocation)
                    {
                        if (!(emReference.LokationsId == emOther.LokationsId &&
                              emReference.LokationsTyp == emOther.LokationsTyp))
                        {
                            throw new ArgumentException(
                                      $"locations do not match! '{emReference.LokationsId}' ({emReference.LokationsTyp}) != '{emOther.LokationsId}' ({emOther.LokationsTyp})");
                        }
                    }
                    timeframe = overlap;
                }

                Tuple <decimal, Mengeneinheit> consumptionReference;
                Tuple <decimal, Mengeneinheit> consumptionOtherRaw;
                using (MiniProfiler.Current.Step("Get Consumptions for overlap:"))
                {
                    consumptionReference = emReference.GetConsumption(timeframe);
                    consumptionOtherRaw  = emOther.GetConsumption(timeframe);
                }

                Tuple <decimal, Mengeneinheit> consumptionOther;
                if (consumptionReference.Item2 != consumptionOtherRaw.Item2)
                {
                    // unit mismatch
                    if (consumptionReference.Item2.IsConvertibleTo(consumptionOtherRaw.Item2))
                    {
                        consumptionOther = new Tuple <decimal, Mengeneinheit>(
                            consumptionOtherRaw.Item1 *
                            consumptionOtherRaw.Item2.GetConversionFactor(consumptionReference.Item2),
                            consumptionReference.Item2);
                    }
                    else
                    {
                        throw new ArgumentException(
                                  $"The unit {consumptionOtherRaw.Item2} is not comparable to {consumptionReference.Item2}!");
                    }
                }
                else
                {
                    consumptionOther = consumptionOtherRaw;
                }

                var     absoluteDeviation = consumptionOther.Item1 - consumptionReference.Item1;
                decimal?relativeDeviation;
                try
                {
                    relativeDeviation = absoluteDeviation / consumptionReference.Item1;
                }
                catch (DivideByZeroException)
                {
                    relativeDeviation = null;
                }

                var vReference =
                    emReference.Energieverbrauch.FirstOrDefault(); // copies obiskennzahl, wertermittlungsverfahren...
                vReference.Wert       = consumptionReference.Item1;
                vReference.Einheit    = consumptionReference.Item2;
                vReference.Startdatum = timeframe.Start;
                vReference.Enddatum   = timeframe.End;

                var vOther =
                    emOther.Energieverbrauch.FirstOrDefault(); // copies obiskennzahl, wertermittlungsverfahren...
                vOther.Wert       = consumptionOther.Item1;
                vOther.Einheit    = consumptionOther.Item2;
                vOther.Startdatum = timeframe.Start;
                vOther.Enddatum   = timeframe.End;

                var pr = new PlausibilityReport
                {
                    LokationsId        = emReference.LokationsId,
                    ReferenceTimeFrame = new Zeitraum
                    {
                        Startdatum = new DateTimeOffset(timeframe.Start),
                        Enddatum   = new DateTimeOffset(timeframe.End)
                    },
                    VerbrauchReference       = vReference,
                    VerbrauchOther           = vOther,
                    AbsoluteDeviation        = Math.Abs(absoluteDeviation),
                    AbsoluteDeviationEinheit = consumptionReference.Item2
                };
                if (relativeDeviation.HasValue)
                {
                    pr.RelativeDeviation = Math.Round(relativeDeviation.Value, 4);
                }
                else
                {
                    pr.RelativeDeviation = null;
                }
                return(pr);
            }
        }