public static ITimeRange GetIntersection(this Verbrauch v1, Verbrauch v2) { return(v1.GetIntersection(new TimeRange(v2.Startdatum, v2.Enddatum))); }
public static HashSet <Verbrauch> Merge(this Verbrauch v1, Verbrauch v2, bool redundant, Boolean biased) { HashSet <Verbrauch> result = new HashSet <Verbrauch>(); if (v1.Obiskennzahl == v2.Obiskennzahl && v1.Wertermittlungsverfahren == v2.Wertermittlungsverfahren && v1.Einheit == v2.Einheit) { if (v1.OverlapsWith(v2)) { // don't wanna deal with time running backwards. //Debug.Assert(v1.enddatum >= v1.startdatum); //Debug.Assert(v2.enddatum >= v2.startdatum); TimeRange tr1 = new TimeRange(v1.Startdatum, v1.Enddatum); TimeRange tr2 = new TimeRange(v2.Startdatum, v2.Enddatum); ITimeRange overlap = v1.GetIntersection(v2); if (v1.Einheit.IsExtensive()) { Verbrauch vmerge = new Verbrauch() { Obiskennzahl = v1.Obiskennzahl, Einheit = v1.Einheit, Wertermittlungsverfahren = v1.Wertermittlungsverfahren }; if (redundant) { decimal exclusiveV1Wert = (decimal)(tr1.Duration.TotalSeconds - overlap.Duration.TotalSeconds) * v1.Wert / ((decimal)tr1.Duration.TotalSeconds); decimal exclusiveV2Wert = (decimal)(tr2.Duration.TotalSeconds - overlap.Duration.TotalSeconds) * v2.Wert / ((decimal)tr2.Duration.TotalSeconds); decimal overlapV1Wert = ((decimal)overlap.Duration.TotalSeconds * v1.Wert) / (decimal)(tr1.Duration.TotalSeconds); decimal overlapV2Wert = ((decimal)overlap.Duration.TotalSeconds * v2.Wert) / (decimal)(tr2.Duration.TotalSeconds); if (biased == true) { // biased ==> assume that v2 is contained in v1 vmerge.Startdatum = v1.Startdatum; vmerge.Enddatum = v1.Enddatum; if (exclusiveV1Wert == 0.0M && exclusiveV2Wert == 0.0M && overlapV1Wert == overlapV2Wert) { vmerge.Wert = overlapV1Wert; } else { vmerge.Wert = v1.Wert - overlapV2Wert; // overlapV1Wert; } } else if (biased == false) { vmerge.Startdatum = v1.Startdatum; vmerge.Enddatum = v2.Startdatum; vmerge.Wert = v1.Wert - overlapV2Wert; } else // biased null { vmerge.Startdatum = v1.Startdatum < v2.Startdatum ? v1.Startdatum : v2.Startdatum; vmerge.Enddatum = v1.Enddatum > v2.Enddatum ? v1.Enddatum : v2.Enddatum; if (overlapV1Wert != overlapV2Wert) { throw new ArgumentException("The inequality is unsolvable."); } vmerge.Wert = exclusiveV1Wert + overlapV1Wert + exclusiveV2Wert; } } else { vmerge.Startdatum = v1.Startdatum < v2.Startdatum ? v1.Startdatum : v2.Startdatum; vmerge.Enddatum = v1.Enddatum > v2.Enddatum ? v1.Enddatum : v2.Enddatum; vmerge.Wert = v1.Wert + v2.Wert; } result.Add(vmerge); } else { Verbrauch vmerge1 = new Verbrauch() { Obiskennzahl = v1.Obiskennzahl, Einheit = v1.Einheit, Wertermittlungsverfahren = v1.Wertermittlungsverfahren, Startdatum = v1.Startdatum < v2.Startdatum ? v1.Startdatum : v2.Startdatum, Enddatum = overlap.Start, Wert = v1.Startdatum < v2.Startdatum ? v1.Wert : v2.Wert }; Verbrauch vmerge2 = new Verbrauch() { Obiskennzahl = v1.Obiskennzahl, Einheit = v1.Einheit, Wertermittlungsverfahren = v1.Wertermittlungsverfahren, Startdatum = overlap.Start, Enddatum = overlap.End }; if (redundant) { if (v1.Wert != v2.Wert) { throw new ArgumentException($"Data cannot be redundant if values ({v1.Wert}{v1.Einheit} vs. {v2.Wert}{v2.Einheit}) don't match for interval [{vmerge2.Startdatum}, {vmerge2.Enddatum})."); } vmerge2.Wert = v1.Wert; } else { vmerge2.Wert = v1.Wert + v2.Wert; } Verbrauch vmerge3 = new Verbrauch() { Obiskennzahl = v1.Obiskennzahl, Einheit = v1.Einheit, Wertermittlungsverfahren = v1.Wertermittlungsverfahren, Startdatum = overlap.End, Enddatum = v1.Enddatum > v2.Enddatum ? v1.Enddatum : v2.Enddatum, Wert = v1.Enddatum > v2.Enddatum ? v1.Wert : v2.Wert }; result.Add(vmerge1); result.Add(vmerge2); result.Add(vmerge3); } } else if (v1.Startdatum == v2.Enddatum || v2.Startdatum == v1.Enddatum) { DateTime start = v1.Startdatum < v2.Startdatum ? v1.Startdatum : v2.Startdatum; DateTime stop = v1.Enddatum > v2.Enddatum ? v1.Enddatum : v2.Enddatum; Verbrauch vmerge = new Verbrauch() { Obiskennzahl = v1.Obiskennzahl, Einheit = v1.Einheit, Wertermittlungsverfahren = v1.Wertermittlungsverfahren, Startdatum = start, Enddatum = stop }; if (v1.Einheit.IsExtensive()) { vmerge.Wert = v1.Wert + v2.Wert; result.Add(vmerge); } else if (v1.Wert == v2.Wert) // implicitly intensive { vmerge.Wert = v1.Wert; result.Add(vmerge); } else { // merging intensive verbrauch with different values is not possible. result.Add(v1); result.Add(v2); } } else { // laaaangweilig ;) result.Add(v1); result.Add(v2); } } else { // laaaangweilig ;) result.Add(v1); result.Add(v2); } result.RemoveWhere(v => v.Einheit.IsIntensive() && new TimeRange(v.Startdatum, v.Enddatum).Duration.TotalMilliseconds == 0); return(result); }