Merge branch 'dev'
This commit is contained in:
@@ -28,8 +28,7 @@ public class APFactory implements AbstractAPFactory {
|
||||
|
||||
@Override
|
||||
public LocalDayPlan createLocalDayPlan(LocalDay day, Instant start, Instant end) {
|
||||
// TODO Return an instance of your class that implements LocalDayPlan
|
||||
return null;
|
||||
return new LocalDayPlanImpl(day, start, end);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -12,6 +12,13 @@ public class AppointmentImpl implements Appointment {
|
||||
|
||||
private AppointmentRequest request;
|
||||
|
||||
public AppointmentImpl(Instant start, AppointmentRequest request) {
|
||||
this.start = start;
|
||||
this.request = request;
|
||||
|
||||
this.stop = start.plus(request.duration());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Instant start() {
|
||||
return start;
|
||||
|
||||
@@ -3,6 +3,7 @@ package appointmentplanner;
|
||||
import java.time.Duration;
|
||||
import java.time.Instant;
|
||||
import java.time.LocalTime;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.function.Predicate;
|
||||
@@ -15,11 +16,12 @@ import appointmentplanner.api.LocalDayPlan;
|
||||
import appointmentplanner.api.TimePreference;
|
||||
import appointmentplanner.api.TimeSlot;
|
||||
import appointmentplanner.customlist.CustomLinkedListImpl;
|
||||
import appointmentplanner.customlist.CustomListToJavaBinding;
|
||||
import appointmentplanner.customlist.api.CustomLinkedList;
|
||||
|
||||
public class LocalDayPlanImpl implements LocalDayPlan {
|
||||
|
||||
private CustomLinkedList<AppointmentImpl> timeline = new CustomLinkedListImpl<>();
|
||||
private CustomLinkedList<Appointment> timeline = new CustomLinkedListImpl<>();
|
||||
|
||||
public LocalDayPlanImpl(LocalDay day, Instant start, Instant end) {
|
||||
this.day = day;
|
||||
@@ -55,8 +57,7 @@ public class LocalDayPlanImpl implements LocalDayPlan {
|
||||
|
||||
@Override
|
||||
public Optional<Appointment> addAppointment(AppointmentData appointmentData, LocalTime startTime) {
|
||||
// TODO Auto-generated method stub
|
||||
throw new UnsupportedOperationException("Unimplemented method 'addAppointment'");
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -67,20 +68,26 @@ public class LocalDayPlanImpl implements LocalDayPlan {
|
||||
|
||||
@Override
|
||||
public AppointmentRequest removeAppointment(Appointment appointment) {
|
||||
// TODO Auto-generated method stub
|
||||
throw new UnsupportedOperationException("Unimplemented method 'removeAppointment'");
|
||||
Appointment removedItem = timeline.remove(appointment);
|
||||
return removedItem == null ? null : removedItem.request();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<AppointmentRequest> removeAppointments(Predicate<Appointment> filter) {
|
||||
// TODO Auto-generated method stub
|
||||
throw new UnsupportedOperationException("Unimplemented method 'removeAppointments'");
|
||||
|
||||
CustomLinkedList<AppointmentRequest> removedRequests = new CustomLinkedListImpl<>();
|
||||
|
||||
for (Appointment appointment : timeline.removeFound(filter)) {
|
||||
removedRequests.add(appointment.request());
|
||||
}
|
||||
|
||||
return new CustomListToJavaBinding<>(removedRequests);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Appointment> appointments() {
|
||||
// TODO Auto-generated method stub
|
||||
throw new UnsupportedOperationException("Unimplemented method 'appointments'");
|
||||
return new CustomListToJavaBinding<Appointment>(timeline);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -89,28 +96,47 @@ public class LocalDayPlanImpl implements LocalDayPlan {
|
||||
throw new UnsupportedOperationException("Unimplemented method 'findMatchingFreeSlotsOfDuration'");
|
||||
}
|
||||
|
||||
private CustomLinkedList<TimeSlot> traverseGapsFitting(Duration toFind, CustomLinkedList<TimeSlot> goodSlots,
|
||||
Instant startOfBefore, Iterator<Appointment> iterator) {
|
||||
|
||||
boolean hasNext = iterator.hasNext();
|
||||
|
||||
Appointment nextAppointment = hasNext ? iterator.next() : null;
|
||||
|
||||
TimeSlot possibleFittingSlot = new TimeSlotImpl(hasNext ? nextAppointment.end() : startOfDay(),
|
||||
startOfBefore == null ? endOfDay() : startOfBefore);
|
||||
|
||||
if (possibleFittingSlot.fits(toFind)) {
|
||||
goodSlots.add(possibleFittingSlot);
|
||||
}
|
||||
|
||||
if (!hasNext) {
|
||||
return goodSlots;
|
||||
}
|
||||
|
||||
return traverseGapsFitting(toFind, goodSlots, nextAppointment.start(), iterator);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<TimeSlot> findGapsFitting(Duration duration) {
|
||||
// TODO Auto-generated method stub
|
||||
throw new UnsupportedOperationException("Unimplemented method 'findGapsFitting'");
|
||||
return new CustomListToJavaBinding<>(
|
||||
traverseGapsFitting(duration, new CustomLinkedListImpl<>(), null, timeline.iterator()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Appointment> findAppointments(Predicate<Appointment> filter) {
|
||||
// TODO Auto-generated method stub
|
||||
throw new UnsupportedOperationException("Unimplemented method 'findAppointments'");
|
||||
return new CustomListToJavaBinding<>(timeline.find(filter));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean contains(Appointment appointment) {
|
||||
// TODO Auto-generated method stub
|
||||
throw new UnsupportedOperationException("Unimplemented method 'contains'");
|
||||
return timeline.contains(appointment);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int nrOfAppointments() {
|
||||
// TODO Auto-generated method stub
|
||||
throw new UnsupportedOperationException("Unimplemented method 'nrOfAppointments'");
|
||||
return timeline.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
package appointmentplanner;
|
||||
|
||||
import java.time.Instant;
|
||||
|
||||
import appointmentplanner.api.TimeSlot;
|
||||
|
||||
public class TimeSlotImpl implements TimeSlot {
|
||||
|
||||
private Instant start;
|
||||
private Instant end;
|
||||
|
||||
public TimeSlotImpl(Instant start, Instant end) {
|
||||
this.start = start;
|
||||
this.end = end;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Instant start() {
|
||||
return start;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Instant end() {
|
||||
return end;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
package appointmentplanner.customlist;
|
||||
|
||||
import java.util.Iterator;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
import appointmentplanner.customlist.api.CustomLinkedList;
|
||||
|
||||
@@ -84,31 +85,32 @@ public class CustomLinkedListImpl<T> implements CustomLinkedList<T> {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void remove(T item) {
|
||||
public T remove(T item) {
|
||||
|
||||
if (head == null) {
|
||||
return;
|
||||
return null;
|
||||
}
|
||||
|
||||
if (head.getItem().equals(item)) {
|
||||
head = head.getNext();
|
||||
return;
|
||||
return item;
|
||||
}
|
||||
|
||||
CustomLinkedListNode<T> beforeNode = traverseFind(head, item, ItemPosition.BEFORE);
|
||||
|
||||
if (beforeNode == null) {
|
||||
return;
|
||||
return item;
|
||||
}
|
||||
|
||||
CustomLinkedListNode<T> nodeToRemove = beforeNode.getNext();
|
||||
|
||||
if (beforeNode.getNext() == null) {
|
||||
beforeNode.setNext(null);
|
||||
return;
|
||||
return item;
|
||||
}
|
||||
|
||||
beforeNode.setNext(nodeToRemove.getNext());
|
||||
return item;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -172,4 +174,34 @@ public class CustomLinkedListImpl<T> implements CustomLinkedList<T> {
|
||||
return recursiveSizeCalc(this.head, 1);
|
||||
}
|
||||
|
||||
private CustomLinkedList<T> traverseFilter(Predicate<T> filter, CustomLinkedListNode<T> node,
|
||||
CustomLinkedList<T> found) {
|
||||
|
||||
if (node == null) {
|
||||
return found;
|
||||
}
|
||||
|
||||
T item = node.getItem();
|
||||
|
||||
if (filter.test(item)) {
|
||||
found.add(item);
|
||||
}
|
||||
|
||||
return traverseFilter(filter, node.getNext(), found);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CustomLinkedList<T> find(Predicate<T> filter) {
|
||||
return traverseFilter(filter, head, new CustomLinkedListImpl<>());
|
||||
}
|
||||
|
||||
@Override
|
||||
public CustomLinkedList<T> removeFound(Predicate<T> filter) {
|
||||
CustomLinkedList<T> items = find(filter);
|
||||
for (T item : items) {
|
||||
remove(item);
|
||||
}
|
||||
return items;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -17,6 +17,9 @@ public class CustomLinkedListIterator<T> implements Iterator<T> {
|
||||
|
||||
@Override
|
||||
public boolean hasNext() {
|
||||
if (lastNode == null) {
|
||||
return false;
|
||||
}
|
||||
return lastNode.getNext() != null;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,11 +1,15 @@
|
||||
|
||||
package appointmentplanner.customlist.api;
|
||||
|
||||
import java.util.function.Predicate;
|
||||
|
||||
public interface CustomLinkedList<T> extends Iterable<T> {
|
||||
|
||||
void add(T item);
|
||||
|
||||
void remove(T item);
|
||||
T remove(T item);
|
||||
|
||||
CustomLinkedList<T> removeFound(Predicate<T> filter);
|
||||
|
||||
void insertAfter(T reference, T item);
|
||||
|
||||
@@ -18,4 +22,6 @@ public interface CustomLinkedList<T> extends Iterable<T> {
|
||||
boolean contains(T item);
|
||||
|
||||
int size();
|
||||
|
||||
CustomLinkedList<T> find(Predicate<T> filter);
|
||||
}
|
||||
|
||||
@@ -2,15 +2,19 @@ package appointmentplanner;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
import java.time.Duration;
|
||||
import java.time.Instant;
|
||||
import java.util.List;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.params.ParameterizedTest;
|
||||
import org.junit.jupiter.params.provider.Arguments;
|
||||
import org.junit.jupiter.params.provider.MethodSource;
|
||||
|
||||
import appointmentplanner.api.LocalDay;
|
||||
import appointmentplanner.api.LocalDayPlan;
|
||||
import appointmentplanner.api.TimeSlot;
|
||||
|
||||
public class LocalDayPlanTest {
|
||||
|
||||
@@ -23,14 +27,14 @@ public class LocalDayPlanTest {
|
||||
|
||||
@ParameterizedTest
|
||||
@MethodSource("provideLocalDPDataset")
|
||||
void ldPlanInit_shouldBeSuccessful(LocalDay day, Instant start, Instant end) {
|
||||
void ldpInit_shouldBeSuccessful(LocalDay day, Instant start, Instant end) {
|
||||
LocalDayPlan plan = new LocalDayPlanImpl(day, start, end);
|
||||
assertThat(plan).isNotNull();
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@MethodSource("provideLocalDPDataset")
|
||||
void ldPlanGetters_shouldReturnSetValues(LocalDay day, Instant start, Instant end) {
|
||||
void ldpGetters_shouldReturnSetValues(LocalDay day, Instant start, Instant end) {
|
||||
LocalDayPlan plan = new LocalDayPlanImpl(day, start, end);
|
||||
|
||||
assertThat(plan.day()).isEqualTo(day);
|
||||
@@ -40,9 +44,18 @@ public class LocalDayPlanTest {
|
||||
|
||||
@ParameterizedTest
|
||||
@MethodSource("provideLocalDPDataset")
|
||||
void ldToString_shouldReturnStringContainingLocalDateAndTimeZone(LocalDay day, Instant start, Instant end) {
|
||||
void ldpToString_shouldReturnStringContainingLocalDateAndTimeZone(LocalDay day, Instant start, Instant end) {
|
||||
LocalDayPlan plan = new LocalDayPlanImpl(day, start, end);
|
||||
|
||||
assertThat(plan.toString()).contains(day.zone().toString(), day.date().toString());
|
||||
}
|
||||
|
||||
@Test
|
||||
void ldpFindMatchingFreeSlotsOnEmptyDay() {
|
||||
LocalDayPlan plan = TestData.emptyWorkingDay();
|
||||
|
||||
List<TimeSlot> freeSlots = plan.findGapsFitting(Duration.ofHours(2));
|
||||
|
||||
assertThat(freeSlots.size()).isEqualTo(1);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -160,7 +160,21 @@ public class CustomLinkedListTest {
|
||||
|
||||
}
|
||||
|
||||
private CustomLinkedList<String> initPopulatedList(String[] initData) {
|
||||
@Test
|
||||
void cllFind_shouldFindCorrectItem() {
|
||||
CustomLinkedList<String> list = initPopulatedList("Ahoj", "ja", "jsem", "kkt");
|
||||
|
||||
CustomLinkedList<String> foundItems = list.find(i -> i.length() == 4);
|
||||
|
||||
assertThat(foundItems.size()).isEqualTo(2);
|
||||
|
||||
assertThat(foundItems.contains("Ahoj")).isTrue();
|
||||
assertThat(foundItems.contains("jsem")).isTrue();
|
||||
assertThat(foundItems.contains("kkt")).isFalse();
|
||||
|
||||
}
|
||||
|
||||
private CustomLinkedList<String> initPopulatedList(String... initData) {
|
||||
CustomLinkedList<String> list = new CustomLinkedListImpl<>();
|
||||
Stream.of(initData).forEach(list::add);
|
||||
return list;
|
||||
|
||||
Reference in New Issue
Block a user