} // IgnoreEmptyPeriods // ---------------------------------------------------------------------- protected virtual void StartEvaluation() { if (periods.Count > 0) { TimeLineMomentCollection timeLineMoments = new TimeLineMomentCollection(); timeLineMoments.AddAll(periods); if (timeLineMoments.Count > 1) { int periodCount = 0; for (int i = 0; i < timeLineMoments.Count - 1; i++) { ITimeLineMoment start = timeLineMoments[i]; ITimeLineMoment end = timeLineMoments[i + 1]; if (i == 0) { periodCount += start.StartCount; periodCount -= start.EndCount; } ITimePeriod period = new TimeRange(MapPeriodStart(start.Moment), MapPeriodEnd(end.Moment)); if (!(IgnoreEmptyPeriods && period.IsMoment)) { if (EvaluatePeriod(period, periodCount) == false) { break; } } periodCount += end.StartCount; periodCount -= end.EndCount; } } } } // StartEvaluation
} // 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
} // Remove // ---------------------------------------------------------------------- public ITimeLineMoment Find(DateTime moment) { ITimeLineMoment timeLineMoment = null; if (Count > 0) { timeLineMomentLookup.TryGetValue(moment, out timeLineMoment); } return(timeLineMoment); } // Find
} // AddStart // ---------------------------------------------------------------------- protected virtual void AddEnd(DateTime moment, ITimePeriod period) { ITimeLineMoment timeLineMoment = Find(moment); if (timeLineMoment == null) { timeLineMoment = new TimeLineMoment(moment); timeLineMoments.Add(moment, timeLineMoment); } timeLineMoment.AddEnd(); } // AddEnd
} // IEnumerable.GetEnumerator // ---------------------------------------------------------------------- private void AddPeriod(DateTime moment, ITimePeriod period) { ITimeLineMoment timeLineMoment = Find(moment); if (timeLineMoment == null) { timeLineMoment = new TimeLineMoment(moment); timeLineMoments.Add(timeLineMoment); } timeLineMoment.Periods.Add(period); } // AddPeriod
} // IEnumerable.GetEnumerator // ---------------------------------------------------------------------- protected virtual void AddStart(DateTime moment) { ITimeLineMoment timeLineMoment = Find(moment); if (timeLineMoment == null) { timeLineMoment = new TimeLineMoment(moment); timeLineMoments.Add(timeLineMoment); timeLineMomentLookup.Add(moment, timeLineMoment); } timeLineMoment.AddStart(); } // AddStart
} // RemoveStart // ---------------------------------------------------------------------- protected virtual void RemoveEnd(DateTime moment, ITimePeriod period) { ITimeLineMoment timeLineMoment = Find(moment); if (timeLineMoment == null) { throw new InvalidOperationException(); } timeLineMoment.RemoveEnd(); if (timeLineMoment.IsEmpty) { timeLineMoments.Remove(moment); } } // RemoveEnd
} // AddPeriod // ---------------------------------------------------------------------- private void RemovePeriod(DateTime moment, ITimePeriod period) { ITimeLineMoment timeLineMoment = Find(moment); if (timeLineMoment == null || !timeLineMoment.Periods.Contains(period)) { throw new InvalidOperationException(); } timeLineMoment.Periods.Remove(period); if (timeLineMoment.Periods.Count == 0) { timeLineMoments.Remove(timeLineMoment); } } // RemovePeriod
} // AddEnd // ---------------------------------------------------------------------- protected virtual void RemoveStart(DateTime moment) { ITimeLineMoment timeLineMoment = Find(moment); if (timeLineMoment == null) { throw new InvalidOperationException(); } timeLineMoment.RemoveStart(); if (timeLineMoment.IsEmpty) { timeLineMoments.Remove(timeLineMoment); timeLineMomentLookup.Remove(moment); } } // RemoveStart
} // 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
} // HasOverlaps // ---------------------------------------------------------------------- public bool HasGaps() { bool hasGaps = false; if (Count > 1) { int momentCount = 0; for (int index = 0; index < timeLineMoments.Count; index++) { ITimeLineMoment timeLineMoment = timeLineMoments[index]; momentCount += timeLineMoment.StartCount; momentCount -= timeLineMoment.EndCount; if (momentCount == 0 && index > 0 && index < timeLineMoments.Count - 1) { hasGaps = true; break; } } } return(hasGaps); } // HasGaps
} // HasOverlaps // ---------------------------------------------------------------------- public bool HasGaps() { bool hasGaps = false; if (Count > 1) { int momentCount = 0; foreach (var index in Enumerable.Range(0, timeLineMoments.Count)) { ITimeLineMoment timeLineMoment = timeLineMoments[index]; momentCount += timeLineMoment.StartCount; momentCount -= timeLineMoment.EndCount; if (momentCount == 0 && index > 0 && index < timeLineMoments.Count - 1) { hasGaps = true; break; } } } return(hasGaps); } // HasGaps
public Task AddMoment(ITimelineParticipant grain, ITimeLineMoment moment) { throw new System.NotImplementedException(); }
/// <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); }
} // 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> /// <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); }