|
using System;
using System.Collections.Generic;
using System.Text;
using System.Diagnostics;
namespace Idaligo.Time
{
public class Area : IArea
{
protected class Errors
{
protected Errors()
{
}
public static ApplicationException NoRanges()
{
return new ApplicationException("There are no ranges in the area.");
}
}
private List<IPeriod> list;
public Area()
{
this.list = new List<IPeriod>();
}
public Area(IPeriod period)
: this()
{
if (period == null) throw new ArgumentNullException("period");
this.Add(period);
}
public void Add(IPeriod period)
{
if (period == null) throw new ArgumentNullException("period");
this.list.Add(period);
}
public bool Hit(DateTime at)
{
bool result = false;
foreach (IPeriod range in this.list)
{
if (range.Hit(at))
{
result = true;
break;
}
}
return result;
}
//public IEnumerable<TimeRange> Walk1(DateTime from)
//{
// IEnumerator<IPeriod> iterator = this.list.GetEnumerator();
// if (iterator.MoveNext())
// {
// DateTime starts = DateTime.MaxValue;
// DateTime ends = DateTime.MinValue;
// bool found = false;
// TimeRange current = iterator.Current.CurrentPeriodIfAny(from);
// if (current != null)
// {
// found = true;
// starts = current.From;
// ends = current.Till;
// }
// while (iterator.MoveNext())
// {
// current = iterator.Current.CurrentPeriodIfAny(from);
// if (current != null)
// {
// if (found)
// {
// if (current.From < starts)
// {
// starts = current.From;
// }
// if (current.Till > ends)
// {
// starts = current.Till;
// }
// }
// else
// {
// starts = current.From;
// ends = current.Till;
// found = true;
// }
// }
// }
// if (found)
// {
// yield return new TimeRange(starts, ends);
// from = ends;
// }
// else
// {
// // do nothing
// }
// while (true)
// {
// starts = this.StartingBoundary(from);
// iterator = this.list.GetEnumerator();
// while (iterator.MoveNext())
// {
// current = iterator.Current.CurrentPeriodIfAny(starts);
// if (current != null)
// {
// if (current.Till > ends)
// {
// ends = current.Till;
// }
// }
// }
// yield return new TimeRange(starts, ends);
// from = ends;
// }
// }
// else
// {
// throw Errors.NoRanges();
// }
//}
public IEnumerable<TimeRange> Walk(DateTime from)
{
IEnumerator<IPeriod> iterator = this.list.GetEnumerator();
if (iterator.MoveNext())
{
DateTime starts = DateTime.MaxValue;
DateTime ends = DateTime.MinValue;
bool found = false;
TimeRange current = iterator.Current.CurrentPeriodIfAny(from);
if (current != null)
{
found = true;
starts = current.From;
ends = current.Till;
}
while (iterator.MoveNext())
{
current = iterator.Current.CurrentPeriodIfAny(from);
if (current != null)
{
if (found)
{
if (current.From < starts)
{
starts = current.From;
}
if (current.Till > ends)
{
starts = current.Till;
}
}
else
{
starts = current.From;
ends = current.Till;
found = true;
}
}
}
TimeRange last;
if (found)
{
last = new TimeRange(starts, ends);
}
else
{
last = null;
ends = from;
}
// in: last, from
while (true)
{
starts = this.StartingBoundary(ends);
ends = this.EndingBoundary(starts);
if (last != null)
{
if (last.Till == starts)
{
last = new TimeRange(last.From, ends);
}
else
{
yield return last;
last = new TimeRange(starts, ends);
}
}
else
{
last = new TimeRange(starts, ends);
}
}
}
else
{
throw Errors.NoRanges();
}
}
public DateTime EndingBoundary(DateTime starts)
{
DateTime result = starts;
bool found = false;
IEnumerator<IPeriod> iterator = this.list.GetEnumerator();
while (iterator.MoveNext())
{
TimeRange current = iterator.Current.CurrentPeriodIfAny(starts);
if (current != null)
{
if (current.Till > result)
{
found = true;
result = current.Till;
}
}
}
if (!found)
{
// must be found!!!
throw new InvalidProgramException();
}
return result;
}
public DateTime StartingBoundary(DateTime from)
{
DateTime result;
IEnumerator<IPeriod> iterator = this.list.GetEnumerator();
if (iterator.MoveNext())
{
TimeRange current = iterator.Current.CurrentPeriodIfAny(from);
if (current != null && current.From == from)
{
result = from;
}
else
{
result = iterator.Current.Next(from).From;
while (iterator.MoveNext())
{
current = iterator.Current.CurrentPeriodIfAny(from);
if (current != null)
{
result = from;
}
else
{
DateTime next = iterator.Current.Next(from).From;
if (result > next)
{
result = next;
}
}
}
}
}
else
{
throw Errors.NoRanges();
}
return result;
}
public bool IsEmpty
{
[DebuggerStepThrough]
get
{
return this.list.Count < 1;
}
}
}
}
|
By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.
If a file you wish to view isn't highlighted, and is a text file (not binary), please
let us know and we'll add colourisation support for it.