/// <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)); }
/// <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); } }