public IEnumerable<TimedEvent> GetRange(DateTime RangeStart, DateTime RangeEnd)
{
// Get iterators from each schedule
List<SpyEnumerator<TimedEvent>> Iterators = new List<SpyEnumerator<TimedEvent>>(_Schedules.Count);
foreach (ISchedule Schedule1 in _Schedules)
Iterators.Add(Schedule1.GetRange(RangeStart, RangeEnd).GetSpyEnumerator());
// Batch loop
List<TimedEvent> BatchEvents = new List<TimedEvent>(MaxScheduleBufferSize * _Schedules.Count);
for (; ; ) {
DateTime? BatchEndTime = null;
// Peek first events from each iterator
foreach (SpyEnumerator<TimedEvent> Iterator in Iterators) {
if (Iterator.HasMore) {
TimedEvent Evt1 = Iterator.Peek;
if (!BatchEndTime.HasValue || Evt1.StartTime < BatchEndTime.Value)
BatchEndTime = Evt1.StartTime;
}
}
// Check if no more events can be iterated, break out
if (!BatchEndTime.HasValue) break;
// Iterate events up to BatchEndTime
foreach (SpyEnumerator<TimedEvent> Iterator in Iterators) {
int BatchSize = 0;
while (Iterator.HasMore) {
TimedEvent Evt1 = Iterator.Peek;
if (Evt1.StartTime > BatchEndTime) break;
Iterator.MoveNext();
BatchEvents.Add(Evt1);
BatchSize++;
if (BatchSize >= MaxScheduleBufferSize) {
// Max buffer size reached
// Set new BatchEndTime and skip to next schedule
BatchEndTime = Evt1.StartTime;
break;
}
}
}
// If no more events can be had, break from iteration
if (BatchEvents.Count == 0) break;
// Sort batch results to ensure chronological order, then return each event
BatchEvents.Sort();
int BatchIdx;
for (BatchIdx = 0; BatchIdx < BatchEvents.Count; BatchIdx++) {
TimedEvent Evt1 = BatchEvents[BatchIdx];
if (Evt1.StartTime > BatchEndTime) break;
yield return Evt1;
}
// Clear event list and repeat
BatchEvents.RemoveRange(0, BatchIdx);
}
yield break;
}