ItEr49S10CUVisualizacionResponsabilidadesTRaballoNaPlanificacionItEr48S10: Adding or operation to AvailabilityTimeLine
This commit is contained in:
parent
4ca561567a
commit
25bf19c453
2 changed files with 161 additions and 11 deletions
|
|
@ -137,6 +137,11 @@ public class AvailabilityTimeLine {
|
|||
public String toString() {
|
||||
return date.toString();
|
||||
}
|
||||
|
||||
public static LocalDate tryExtract(DatePoint start) {
|
||||
FixedPoint point = (FixedPoint) start;
|
||||
return point.getDate();
|
||||
}
|
||||
}
|
||||
|
||||
public static class EndOfTime extends DatePoint {
|
||||
|
|
@ -299,6 +304,11 @@ public class AvailabilityTimeLine {
|
|||
&& end.compareTo(other.start) >= 0;
|
||||
}
|
||||
|
||||
public Interval intersect(Interval other) {
|
||||
Validate.isTrue(overlaps(other));
|
||||
return new Interval(max(start, other.start), min(end, other.end));
|
||||
}
|
||||
|
||||
public Interval coalesce(Interval other) {
|
||||
if (!overlaps(other)) {
|
||||
throw new IllegalArgumentException(
|
||||
|
|
@ -361,37 +371,63 @@ public class AvailabilityTimeLine {
|
|||
}
|
||||
|
||||
private void insert(Interval toBeInserted) {
|
||||
int binarySearch = Collections.binarySearch(invalids, toBeInserted);
|
||||
if (invalids.isEmpty()) {
|
||||
invalids.add(toBeInserted);
|
||||
return;
|
||||
}
|
||||
toBeInserted = coalesceWithAdjacent(insertionPoint(binarySearch),
|
||||
toBeInserted);
|
||||
toBeInserted = coalesceWithAdjacent(toBeInserted);
|
||||
int insertionPoint = insertBeforeAllAdjacent(toBeInserted);
|
||||
removeAdjacent(insertionPoint, toBeInserted);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the insertion position for the interval. Inserting the interval
|
||||
* at that position guarantees that interval start is posterior or equal to
|
||||
* any previous interval start. If the next interval start is equal to the
|
||||
* interval, the length of the former is less than the latter
|
||||
*/
|
||||
private int findInsertionPosition(Interval interval) {
|
||||
int binarySearch = Collections.binarySearch(invalids, interval);
|
||||
return insertionPoint(binarySearch);
|
||||
}
|
||||
|
||||
private int insertBeforeAllAdjacent(Interval toBeInserted) {
|
||||
int n = Collections.binarySearch(invalids, toBeInserted);
|
||||
int insertionPoint = insertionPoint(n);
|
||||
int insertionPoint = findInsertionPosition(toBeInserted);
|
||||
invalids.add(insertionPoint, toBeInserted);
|
||||
return insertionPoint;
|
||||
}
|
||||
|
||||
private Interval coalesceWithAdjacent(int insertionPoint,
|
||||
Interval toBeInserted) {
|
||||
private Interval coalesceWithAdjacent(Interval toBeInserted) {
|
||||
Interval result = toBeInserted;
|
||||
List<Interval> adjacent = getAdjacent(toBeInserted);
|
||||
for (Interval each : adjacent) {
|
||||
result = result.coalesce(each);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private List<Interval> getAdjacent(Interval toBeInserted) {
|
||||
final int insertionPoint = findInsertionPosition(toBeInserted);
|
||||
List<Interval> result = new ArrayList<Interval>();
|
||||
for (int i = insertionPoint; i >= 0
|
||||
&& (i == invalids.size() || at(i).overlaps(
|
||||
toBeInserted)); i--) {
|
||||
&& (i == invalids.size() || at(i).overlaps(toBeInserted)); i--) {
|
||||
if (i < invalids.size()) {
|
||||
result = result.coalesce(at(i));
|
||||
result.add(at(i));
|
||||
}
|
||||
}
|
||||
for (int i = insertionPoint; i < invalids.size()
|
||||
&& at(i).overlaps(toBeInserted); i++) {
|
||||
result = result.coalesce(at(i));
|
||||
result.add(at(i));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private List<Interval> intersectWithAdjacent(Interval interval) {
|
||||
List<Interval> result = new ArrayList<Interval>();
|
||||
List<Interval> adjacent = getAdjacent(interval);
|
||||
for (Interval each : adjacent) {
|
||||
assert interval.overlaps(each);
|
||||
result.add(interval.intersect(each));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
|
@ -440,6 +476,36 @@ public class AvailabilityTimeLine {
|
|||
return result;
|
||||
}
|
||||
|
||||
public AvailabilityTimeLine or(AvailabilityTimeLine another) {
|
||||
List<Interval> intersections = doIntersections(this, another);
|
||||
AvailabilityTimeLine result = AvailabilityTimeLine.allValid();
|
||||
for (Interval each : intersections) {
|
||||
boolean fromStartOfTime = each.getStart().equals(
|
||||
StartOfTime.create());
|
||||
boolean untilEndOfTime = each.getEnd().equals(EndOfTime.create());
|
||||
if (fromStartOfTime && untilEndOfTime) {
|
||||
result.allInvalid();
|
||||
} else if (fromStartOfTime) {
|
||||
result.invalidUntil(FixedPoint.tryExtract(each.getEnd()));
|
||||
} else if (untilEndOfTime) {
|
||||
result.invalidFrom(FixedPoint.tryExtract(each.getStart()));
|
||||
} else {
|
||||
result.invalidAt(FixedPoint.tryExtract(each.getStart()),
|
||||
FixedPoint.tryExtract(each.getEnd()));
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private static List<Interval> doIntersections(AvailabilityTimeLine one,
|
||||
AvailabilityTimeLine another) {
|
||||
List<Interval> result = new ArrayList<Interval>();
|
||||
for (Interval each : one.invalids) {
|
||||
result.addAll(another.intersectWithAdjacent(each));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private void inserting(AvailabilityTimeLine result, List<Interval> invalid) {
|
||||
for (Interval each : invalid) {
|
||||
result.insert(each);
|
||||
|
|
|
|||
|
|
@ -234,6 +234,90 @@ public class AvailabilityTimeLineTest {
|
|||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void doingOROnTwoTimeLinesResultingOnAnAllValidTimeLine() {
|
||||
AvailabilityTimeLine one = AvailabilityTimeLine.allValid();
|
||||
one.invalidAt(contemporaryExample.minusDays(40), contemporaryExample
|
||||
.minusDays(20));
|
||||
|
||||
AvailabilityTimeLine another = AvailabilityTimeLine.allValid();
|
||||
another.invalidAt(contemporaryExample.minusDays(10),
|
||||
contemporaryExample.plusDays(10));
|
||||
|
||||
AvailabilityTimeLine result = one.or(another);
|
||||
|
||||
assertThat(result.getValidPeriods(), definedBy(StartOfTime.create(),
|
||||
EndOfTime.create()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void doingORonTwoTimeLinesWithSeveralIntersectingInvalidPeriods() {
|
||||
AvailabilityTimeLine one = AvailabilityTimeLine.allValid();
|
||||
one.invalidAt(contemporaryExample.minusDays(40), contemporaryExample
|
||||
.minusDays(20));
|
||||
one.invalidAt(contemporaryExample.plusDays(35), contemporaryExample
|
||||
.plusDays(50));
|
||||
|
||||
AvailabilityTimeLine another = AvailabilityTimeLine.allValid();
|
||||
another.invalidAt(contemporaryExample.minusDays(25),
|
||||
contemporaryExample.plusDays(10));
|
||||
another.invalidAt(contemporaryExample.plusDays(30), contemporaryExample
|
||||
.plusDays(40));
|
||||
|
||||
AvailabilityTimeLine result = one.or(another);
|
||||
|
||||
assertThat(result.getValidPeriods(), definedBy(StartOfTime.create(),
|
||||
point(contemporaryExample.minusDays(25)),
|
||||
point(contemporaryExample.minusDays(20)),
|
||||
point(contemporaryExample.plusDays(35)),
|
||||
point(contemporaryExample.plusDays(40)), EndOfTime.create()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void doingOROnTheSameTimeLineResultsInTheSameTimeLine() {
|
||||
AvailabilityTimeLine timeLine = AvailabilityTimeLine.allValid();
|
||||
timeLine.invalidAt(earlyExample, contemporaryExample);
|
||||
timeLine.invalidAt(lateExample, lateExample.plusDays(20));
|
||||
|
||||
AvailabilityTimeLine result = timeLine.or(timeLine);
|
||||
|
||||
assertThat(result.getValidPeriods(), definedBy(StartOfTime.create(),
|
||||
point(earlyExample), point(contemporaryExample),
|
||||
point(lateExample), point(lateExample
|
||||
.plusDays(20)), EndOfTime.create()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void doingAnAndWithAnAllValidTimeLineProducesTheSameTimeLine() {
|
||||
AvailabilityTimeLine timeLine = AvailabilityTimeLine.allValid();
|
||||
timeLine.invalidAt(earlyExample, contemporaryExample);
|
||||
timeLine.invalidAt(lateExample, lateExample.plusDays(20));
|
||||
|
||||
AvailabilityTimeLine result = timeLine.and(AvailabilityTimeLine
|
||||
.allValid());
|
||||
|
||||
assertThat(result.getValidPeriods(), definedBy(StartOfTime.create(),
|
||||
point(earlyExample), point(contemporaryExample),
|
||||
point(lateExample), point(lateExample
|
||||
.plusDays(20)), EndOfTime.create()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void doingAnOrWithANeverValidTimeLineProducesTheSameTimeLine() {
|
||||
AvailabilityTimeLine timeLine = AvailabilityTimeLine.allValid();
|
||||
timeLine.invalidAt(earlyExample, contemporaryExample);
|
||||
timeLine.invalidAt(lateExample, lateExample.plusDays(20));
|
||||
AvailabilityTimeLine another = AvailabilityTimeLine.allValid();
|
||||
another.allInvalid();
|
||||
|
||||
AvailabilityTimeLine result = timeLine.and(another);
|
||||
|
||||
assertThat(result.getValidPeriods(), definedBy(StartOfTime.create(),
|
||||
point(earlyExample), point(contemporaryExample),
|
||||
point(lateExample), point(lateExample.plusDays(20)), EndOfTime
|
||||
.create()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void anAllValidPeriodsGeneratesAnAllEncompassingInterval() {
|
||||
AvailabilityTimeLine timeLine = AvailabilityTimeLine.allValid();
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue