/// <summary> /// Get consumption in given time reference frame. Trying to automatically determine parameters and forward to <see cref="BO4E.BO.Energiemenge.GetConsumption(BO.Energiemenge, TimeRange, Wertermittlungsverfahren, string, Mengeneinheit)"/>. /// </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 BO4E.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 <decimal, Mengeneinheit>(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."); } Verbrauch v = em.Energieverbrauch.First <Verbrauch>(); decimal consumption = em.GetConsumption(reference, v.Wertermittlungsverfahren, v.Obiskennzahl, v.Einheit); return(Tuple.Create <decimal, Mengeneinheit>(consumption, v.Einheit)); } }
/// <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 BO4E.BO.Energiemenge emReference, BO4E.BO.Energiemenge emOther, ITimeRange timeframe = null, bool ignoreLocation = false) { using (MiniProfiler.Current.Step(nameof(GetPlausibilityReport))) { TimeRange trReference = emReference.GetTimeRange(); TimeRange trOther = emOther.GetTimeRange(); if (timeframe == null) { ITimeRange 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; } decimal absoluteDeviation = consumptionOther.Item1 - consumptionReference.Item1; decimal?relativeDeviation; try { relativeDeviation = absoluteDeviation / consumptionReference.Item1; } catch (DivideByZeroException) { relativeDeviation = null; } Verbrauch vReference = emReference.Energieverbrauch.FirstOrDefault(); // copies obiskennzahl, wertermittlungsverfahren... vReference.Wert = consumptionReference.Item1; vReference.Einheit = consumptionReference.Item2; vReference.Startdatum = timeframe.Start; vReference.Enddatum = timeframe.End; Verbrauch 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 BO4E.COM.Zeitraum() { Startdatum = timeframe.Start, Enddatum = 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); } }
/// <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 BO4E.BO.Energiemenge em, Wertermittlungsverfahren wev, string obiskennzahl, Mengeneinheit me) { return(em.GetConsumption(em.GetTimeRange(), wev, obiskennzahl, me)); }