} // IntersectPeriods // ---------------------------------------------------------------------- public ITimePeriodCollection CalculateGaps() { // exclude periods TimePeriodCollection gapPeriods = new TimePeriodCollection(); foreach (ITimePeriod period in periods) { if (limits.IntersectsWith(period)) { gapPeriods.Add(new TimeRange(period)); } } ITimeLineMomentCollection timeLineMoments = GetTimeLineMoments(gapPeriods); if (timeLineMoments.Count == 0) { return(new TimePeriodCollection { limits }); } T range = new T(); range.Setup(MapPeriodStart(limits.Start), MapPeriodEnd(limits.End)); return(CalculateGaps(range, timeLineMoments)); } // CalculateGaps
} // GetTimeLineMoments // ---------------------------------------------------------------------- private static ITimePeriodCollection CombinePeriods(ITimeLineMomentCollection timeLineMoments) { TimePeriodCollection periods = new TimePeriodCollection(); if (timeLineMoments.IsEmpty) { return(periods); } // search for periods int itemIndex = 0; while (itemIndex < timeLineMoments.Count) { ITimeLineMoment periodStart = timeLineMoments[itemIndex]; if (periodStart.StartCount == 0) { throw new InvalidOperationException(); } // search next period end // use balancing to handle overlapping periods int balance = periodStart.StartCount; ITimeLineMoment periodEnd = null; while (itemIndex < timeLineMoments.Count - 1 && balance > 0) { itemIndex++; periodEnd = timeLineMoments[itemIndex]; balance += periodEnd.StartCount; balance -= periodEnd.EndCount; } if (periodEnd == null) { throw new InvalidOperationException(); } if (periodEnd.StartCount > 0) // touching { itemIndex++; continue; } // found a period if (itemIndex < timeLineMoments.Count) { T period = new T(); period.Setup(periodStart.Moment, periodEnd.Moment); periods.Add(period); } itemIndex++; } return(periods); } // CombinePeriods
/// <summary> /// ITimeLineMomentCollection으로부터 교집합에 해당하는 기간들을 구합니다 /// </summary> /// <typeparam name="T"></typeparam> /// <param name="timeLineMoments"></param> /// <returns></returns> public static ITimePeriodCollection IntersectPeriods <T>(this ITimeLineMomentCollection timeLineMoments) where T : ITimePeriod { if (IsDebugEnabled) { log.Debug("ITimeLineMomentCollection으로부터 교집합에 해당하는 기간들을 구합니다..."); } var periods = new TimePeriodCollection(); if (timeLineMoments.IsEmpty) { return(periods); } // search for periods var intersectionStart = -1; var balance = 0; for (var i = 0; i < timeLineMoments.Count; i++) { var moment = timeLineMoments[i]; balance += moment.StartCount; balance -= moment.EndCount; // intersection is starting by a period start if (moment.StartCount > 0 && balance > 1 && intersectionStart < 0) { intersectionStart = i; continue; } // intersection is starting by a period end if (moment.EndCount > 0 && balance <= 1 && intersectionStart >= 0) { var period = ActivatorTool.CreateInstance <T>(); period.Setup(timeLineMoments[intersectionStart].Moment, moment.Moment); if (IsDebugEnabled) { log.Debug("Intersect Period를 추가합니다. period=[{0}]", period); } periods.Add(period); intersectionStart = -1; } } if (IsDebugEnabled) { log.Debug("ITimeLineMomentCollection으로부터 교집합에 해당하는 기간들을 구했습니다. periods=[{0}]", periods.CollectionToString()); } return(periods); }
} // PeriodMapper // ---------------------------------------------------------------------- public ITimePeriodCollection CombinePeriods() { if (periods.Count == 0) { return(new TimePeriodCollection()); } ITimeLineMomentCollection timeLineMoments = GetTimeLineMoments(); return(timeLineMoments.Count == 0 ? new TimePeriodCollection { new TimeRange(periods) } : CombinePeriods(timeLineMoments)); } // CombinePeriods
public ITimePeriodCollection CombinePeriods() { if (Periods.Count == 0 || (Periods.Count > 1 && !HasNonMomentPeriods)) { return(new TimePeriodCollection()); } ITimeLineMomentCollection timeLineMoments = GetTimeLineMoments(); return(timeLineMoments.Count == 0 ? new TimePeriodCollection { new TimeRange(Periods) } : CombinePeriods(timeLineMoments)); }
} // CombinePeriods // ---------------------------------------------------------------------- public ITimePeriodCollection IntersectPeriods(bool combinePeriods = true) { if (periods.Count == 0) { return(new TimePeriodCollection()); } ITimeLineMomentCollection timeLineMoments = GetTimeLineMoments(); if (timeLineMoments.Count == 0) { return(new TimePeriodCollection()); } return(combinePeriods ? IntersectCombinedPeriods(timeLineMoments) : IntersectPeriods(timeLineMoments)); } // IntersectPeriods
} // CombinePeriods // ---------------------------------------------------------------------- private static ITimePeriodCollection IntersectCombinedPeriods(ITimeLineMomentCollection timeLineMoments) { TimePeriodCollection periods = new TimePeriodCollection(); if (timeLineMoments.IsEmpty) { return(periods); } // search for periods int intersectionStart = -1; int balance = 0; for (int i = 0; i < timeLineMoments.Count; i++) { ITimeLineMoment moment = timeLineMoments[i]; int startCount = moment.StartCount; int endCount = moment.EndCount; balance += startCount; balance -= endCount; // intersection is starting by a period start if (startCount > 0 && balance > 1 && intersectionStart < 0) { intersectionStart = i; continue; } // intersection is starting by a period end if (endCount <= 0 || balance > 1 || intersectionStart < 0) { continue; } T period = new T(); period.Setup(timeLineMoments[intersectionStart].Moment, moment.Moment); periods.Add(period); intersectionStart = -1; } return(periods); } // IntersectCombinedPeriods
} // IntersectCombinedPeriods // ---------------------------------------------------------------------- private static ITimePeriodCollection IntersectPeriods(ITimeLineMomentCollection timeLineMoments) { TimePeriodCollection periods = new TimePeriodCollection(); if (timeLineMoments.IsEmpty) { return(periods); } // search for periods int intersectionStart = -1; int balance = 0; foreach (var i in Enumerable.Range(0, timeLineMoments.Count)) { ITimeLineMoment moment = timeLineMoments[i]; balance += moment.BalanceCount; // intersection is starting by a period start if (balance > 1 && intersectionStart < 0) { intersectionStart = i; continue; } // intersection is starting by a period end if (intersectionStart < 0) { continue; } T period = new T(); period.Setup(timeLineMoments[intersectionStart].Moment, moment.Moment); periods.Add(period); intersectionStart = balance > 1 ? i : -1; } return(periods); } // IntersectCombinedPeriods
} // IntersectCombinedPeriods // ---------------------------------------------------------------------- private static ITimePeriodCollection CalculateGaps(ITimePeriod range, ITimeLineMomentCollection timeLineMoments) { TimePeriodCollection gaps = new TimePeriodCollection(); if (timeLineMoments.IsEmpty) { return(gaps); } // range leading gap ITimeLineMoment periodStart = timeLineMoments.Min; if (periodStart != null && range.Start < periodStart.Moment) { T startingGap = new T(); startingGap.Setup(range.Start, periodStart.Moment); gaps.Add(startingGap); } // search for gaps int itemIndex = 0; while (itemIndex < timeLineMoments.Count) { ITimeLineMoment moment = timeLineMoments[itemIndex]; if (moment.StartCount == 0) { throw new InvalidOperationException(); } // search next gap start // use balancing to handle overlapping periods int balance = moment.StartCount; ITimeLineMoment gapStart = null; while (itemIndex < timeLineMoments.Count - 1 && balance > 0) { itemIndex++; gapStart = timeLineMoments[itemIndex]; balance += gapStart.StartCount; balance -= gapStart.EndCount; } if (gapStart == null) { throw new InvalidOperationException(); } if (gapStart.StartCount > 0) // touching { itemIndex++; continue; } // found a gap if (itemIndex < timeLineMoments.Count - 1) { T gap = new T(); gap.Setup(gapStart.Moment, timeLineMoments[itemIndex + 1].Moment); gaps.Add(gap); } itemIndex++; } // range closing gap ITimeLineMoment periodEnd = timeLineMoments.Max; if (periodEnd != null && range.End > periodEnd.Moment) { T endingGap = new T(); endingGap.Setup(periodEnd.Moment, range.End); gaps.Add(endingGap); } return(gaps); } // CalculateGaps
/// <summary> /// ITimeLineMoment 컬렉션의 모든 기간의 합집합을 구합니다. /// </summary> /// <typeparam name="T"></typeparam> /// <param name="timeLineMoments">결합할 기간들</param> /// <returns></returns> public static ITimePeriodCollection CombinePeriods <T>(this ITimeLineMomentCollection timeLineMoments) where T : ITimePeriod { if (IsDebugEnabled) { log.Debug("ITimeLineMoment 컬렉션의 모든 기간의 합집합을 구합니다..."); } var periods = new TimePeriodCollection(); if (timeLineMoments.IsEmpty) { return(periods); } // search for periods var itemIndex = 0; while (itemIndex < timeLineMoments.Count) { var periodStart = timeLineMoments[itemIndex]; Guard.Assert(periodStart.StartCount != 0, "StartCount 값은 0이 아니여야 합니다. periodStart.StartCount=[{0}]", periodStart.StartCount); // search next period end // use balancing to handle overlapping periods var balance = periodStart.StartCount; ITimeLineMoment periodEnd = null; while (itemIndex < timeLineMoments.Count - 1 && balance > 0) { itemIndex++; periodEnd = timeLineMoments[itemIndex]; balance += periodEnd.StartCount; balance -= periodEnd.EndCount; } periodEnd.ShouldNotBeNull("periodEnd"); if (periodEnd.StartCount > 0) // touching { itemIndex++; continue; } // found a period if (itemIndex < timeLineMoments.Count) { var period = ActivatorTool.CreateInstance <T>(); period.Setup(periodStart.Moment, periodEnd.Moment); if (IsDebugEnabled) { log.Debug("Combine Period를 추가합니다. period=[{0}]" + period); } periods.Add(period); } itemIndex++; } if (IsDebugEnabled) { log.Debug("기간들을 결합했습니다. periods=[{0}]", periods.CollectionToString()); } return(periods); }
/// <summary> /// <paramref name="timeLineMoments"/>가 가진 모든 ITimePeriod 들의 Gap을 계산합니다. /// </summary> /// <typeparam name="T"></typeparam> /// <param name="timeLineMoments"></param> /// <param name="range"></param> /// <returns></returns> public static ITimePeriodCollection CalculateGaps <T>(this ITimeLineMomentCollection timeLineMoments, ITimePeriod range) where T : ITimePeriod { if (IsDebugEnabled) { log.Debug("ITimeLineMomentCollection의 Gap들을 계산합니다..."); } var gaps = new TimePeriodCollection(); if (timeLineMoments.IsEmpty) { return(gaps); } // find leading gap // var periodStart = timeLineMoments.Min; if (periodStart != null && range.Start < periodStart.Moment) { var startingGap = ActivatorTool.CreateInstance <T>(); startingGap.Setup(range.Start, periodStart.Moment); if (IsDebugEnabled) { log.Debug("Starting Gap을 추가합니다... startingGap=[{0}]", startingGap); } gaps.Add(startingGap); } // find intermediated gap // var itemIndex = 0; while (itemIndex < timeLineMoments.Count) { var moment = timeLineMoments[itemIndex]; Guard.Assert(moment.StartCount != 0, "monent.StartCount 값은 0이 아니여야 합니다. moment=[{0}]", moment); // search next gap start // use balancing to handle overlapping periods var balance = moment.StartCount; ITimeLineMoment gapStart = null; while (itemIndex < timeLineMoments.Count - 1 && balance > 0) { itemIndex++; gapStart = timeLineMoments[itemIndex]; balance += gapStart.StartCount; balance -= gapStart.EndCount; } gapStart.ShouldNotBeNull("gapStart"); if (gapStart.StartCount > 0) // touching { itemIndex++; continue; } // found a gap if (itemIndex < timeLineMoments.Count - 1) { var gap = ActivatorTool.CreateInstance <T>(); gap.Setup(gapStart.Moment, timeLineMoments[itemIndex + 1].Moment); if (IsDebugEnabled) { log.Debug("Intermediated Gap을 추가합니다. gap=[{0}]", gap); } gaps.Add(gap); } itemIndex++; } // find ending gap // var periodEnd = timeLineMoments.Max; if (periodEnd != null && range.End > periodEnd.Moment) { var endingGap = ActivatorTool.CreateInstance <T>(); endingGap.Setup(periodEnd.Moment, range.End); if (IsDebugEnabled) { log.Debug("Ending Gap을 추가합니다. endingGap=[{0}]", endingGap); } gaps.Add(endingGap); } if (IsDebugEnabled) { log.Debug("기간들의 Gap에 해당하는 부분을 계산했습니다!!! gaps=[{0}]", gaps.CollectionToString()); } return(gaps); }