diff --git a/walkthroughs/week-5-tdd/project/src/main/java/com/google/sps/FindMeetingQuery.java b/walkthroughs/week-5-tdd/project/src/main/java/com/google/sps/FindMeetingQuery.java index c8e4c4f..8ef5cbd 100644 --- a/walkthroughs/week-5-tdd/project/src/main/java/com/google/sps/FindMeetingQuery.java +++ b/walkthroughs/week-5-tdd/project/src/main/java/com/google/sps/FindMeetingQuery.java @@ -28,28 +28,45 @@ public final class FindMeetingQuery { public int compare(Event a, Event b) { return Long.compare(a.getWhen().start(), b.getWhen().start()); }}; - - public Collection query(Collection eventCollection, MeetingRequest request) { + + public Collection query(Collection eventCollection, MeetingRequest request) { + Collection attendees = new ArrayList(); + attendees.addAll(request.getOptionalAttendees()); + attendees.addAll(request.getAttendees()); + if (request.getOptionalAttendees().isEmpty()) { + attendees.removeAll(request.getOptionalAttendees()); + } + if (request.getAttendees().isEmpty()) { + attendees.removeAll(request.getAttendees()); + } + if (queryHelper(eventCollection, request, attendees).isEmpty()) { + attendees.removeAll(request.getOptionalAttendees()); + return queryHelper(eventCollection, request, attendees); + } + return queryHelper(eventCollection, request, attendees); + } + + private static Collection queryHelper(Collection groupOfEvents, MeetingRequest request, Collection attendees) { // Too long of a request if (request.getDuration() > TimeRange.WHOLE_DAY.duration()) { return Collections.emptyList(); } - // No events or attendees - List events = new ArrayList(eventCollection); - List meetingAttendees = new ArrayList(request.getAttendees()); - if (events.isEmpty() || meetingAttendees.isEmpty()) { + // No events + List events = new ArrayList(groupOfEvents); + if (events.isEmpty()) { return Arrays.asList(TimeRange.WHOLE_DAY); } + // Ignores unattended events List importantEvents = new ArrayList(); for (Event event : events) { - if (!Collections.disjoint(event.getAttendees(), request.getAttendees())) { + if (!Collections.disjoint(event.getAttendees(), attendees)) { importantEvents.add(event); } } - + // If the list of important events is empty, return the whole day if (importantEvents.isEmpty()) { return Arrays.asList(TimeRange.WHOLE_DAY); @@ -62,7 +79,7 @@ public Collection query(Collection eventCollection, MeetingReq List acceptableMeetingTimes = new ArrayList(); // Add the event that starts first - acceptableMeetingTimes.add(TimeRange.fromStartEnd(0, importantEvents.get(0).getWhen().start(), false)); + acceptableMeetingTimes.add(TimeRange.fromStartEnd(TimeRange.START_OF_DAY, importantEvents.get(0).getWhen().start(), false)); // Set the end time and start time as the end of the first event int latestEventEnd = importantEvents.get(0).getWhen().end(); @@ -72,7 +89,7 @@ public Collection query(Collection eventCollection, MeetingReq for (Event event : importantEvents) { start = event.getWhen().start(); - if (start > latestEventEnd) { + if (start >= latestEventEnd) { if (rangeLessThanDuration(TimeRange.fromStartEnd(latestEventEnd, start, false), request.getDuration())) { acceptableMeetingTimes.add(TimeRange.fromStartEnd(latestEventEnd, start, false)); latestEventEnd = event.getWhen().end(); @@ -80,7 +97,7 @@ public Collection query(Collection eventCollection, MeetingReq latestEventEnd = event.getWhen().end(); } - if (start < latestEventEnd) { + if (start <= latestEventEnd) { if (latestEventEnd < event.getWhen().end()) { latestEventEnd = event.getWhen().end(); if (rangeLessThanDuration(TimeRange.fromStartEnd(latestEventEnd, start, false), request.getDuration())) { @@ -110,11 +127,12 @@ public Collection query(Collection eventCollection, MeetingReq } } - return acceptableMeetingTimes; + return acceptableMeetingTimes; } // Check if the meeting duration fits within a given time range private static boolean rangeLessThanDuration(TimeRange range, long meetingDuration) { return (range.duration() >= meetingDuration); } + } diff --git a/walkthroughs/week-5-tdd/project/src/test/java/com/google/sps/FindMeetingQueryTest.java b/walkthroughs/week-5-tdd/project/src/test/java/com/google/sps/FindMeetingQueryTest.java index 9235153..8ae83fe 100644 --- a/walkthroughs/week-5-tdd/project/src/test/java/com/google/sps/FindMeetingQueryTest.java +++ b/walkthroughs/week-5-tdd/project/src/test/java/com/google/sps/FindMeetingQueryTest.java @@ -34,15 +34,20 @@ public final class FindMeetingQueryTest { // Some people that we can use in our tests. private static final String PERSON_A = "Person A"; private static final String PERSON_B = "Person B"; + private static final String PERSON_C = "Person C"; // All dates are the first day of the year 2020. private static final int TIME_0800AM = TimeRange.getTimeInMinutes(8, 0); private static final int TIME_0830AM = TimeRange.getTimeInMinutes(8, 30); + private static final int TIME_0845AM = TimeRange.getTimeInMinutes(8, 45); private static final int TIME_0900AM = TimeRange.getTimeInMinutes(9, 0); private static final int TIME_0930AM = TimeRange.getTimeInMinutes(9, 30); private static final int TIME_1000AM = TimeRange.getTimeInMinutes(10, 0); + private static final int TIME_1030AM = TimeRange.getTimeInMinutes(10, 30); private static final int TIME_1100AM = TimeRange.getTimeInMinutes(11, 00); - + private static final int TIME_1130AM = TimeRange.getTimeInMinutes(11, 30); + + private static final int DURATION_15_MINUTES = 15; private static final int DURATION_30_MINUTES = 30; private static final int DURATION_60_MINUTES = 60; private static final int DURATION_90_MINUTES = 90; @@ -209,16 +214,16 @@ public void justEnoughRoom() { // Options : |-----| Collection events = Arrays.asList( - new Event("Event 1", TimeRange.fromStartEnd(TimeRange.START_OF_DAY, TIME_0830AM, false), + new Event("Event 1", TimeRange.fromStartEnd(TimeRange.START_OF_DAY, TIME_0900AM, false), Arrays.asList(PERSON_A)), - new Event("Event 2", TimeRange.fromStartEnd(TIME_0900AM, TimeRange.END_OF_DAY, true), + new Event("Event 2", TimeRange.fromStartEnd(TIME_0930AM, TimeRange.END_OF_DAY, true), Arrays.asList(PERSON_A))); MeetingRequest request = new MeetingRequest(Arrays.asList(PERSON_A), DURATION_30_MINUTES); Collection actual = query.query(events, request); Collection expected = - Arrays.asList(TimeRange.fromStartDuration(TIME_0830AM, DURATION_30_MINUTES)); + Arrays.asList(TimeRange.fromStartDuration(TIME_0900AM, DURATION_30_MINUTES)); Assert.assertEquals(expected, actual); } @@ -270,5 +275,114 @@ public void notEnoughRoom() { Assert.assertEquals(expected, actual); } -} + + @Test + public void optionalAttendeeConsidered() { + // The optional attendee has gaps that allow a meeting with the required attendees + Collection events = Arrays.asList( + new Event("Event 1", TimeRange.fromStartDuration(TIME_1000AM, DURATION_30_MINUTES), + Arrays.asList(PERSON_A)), + new Event("Event 2", TimeRange.fromStartDuration(TIME_1100AM, DURATION_30_MINUTES), + Arrays.asList(PERSON_B)), + new Event("Event 3", TimeRange.fromStartDuration(TIME_1030AM, DURATION_30_MINUTES), + Arrays.asList(PERSON_C))); + + MeetingRequest request = + new MeetingRequest(Arrays.asList(PERSON_A, PERSON_B), DURATION_30_MINUTES); + request.addOptionalAttendee(PERSON_C); + + Collection actual = query.query(events, request); + Collection expected = Arrays.asList( + TimeRange.fromStartEnd(TimeRange.START_OF_DAY, TIME_1000AM, false), + TimeRange.fromStartEnd(TIME_1130cAM, TimeRange.END_OF_DAY, true)); + + Assert.assertEquals(expected, actual); + } + + @Test + public void optionalAttendeeNotConsidered() { + // Optional attendee has no time to meet and is therefore not considered + Collection events = Arrays.asList( + new Event("Event 1", TimeRange.fromStartDuration(TIME_0800AM, DURATION_30_MINUTES), + Arrays.asList(PERSON_A)), + new Event("Event 2", TimeRange.fromStartDuration(TIME_0900AM, DURATION_30_MINUTES), + Arrays.asList(PERSON_B)), + new Event("Event 3",TimeRange.WHOLE_DAY, Arrays.asList(PERSON_C))); + + MeetingRequest request = + new MeetingRequest(Arrays.asList(PERSON_A, PERSON_B), DURATION_30_MINUTES); + request.addOptionalAttendee(PERSON_C); + + Collection actual = query.query(events, request); + Collection expected = Arrays.asList( + TimeRange.fromStartEnd(TimeRange.START_OF_DAY, TIME_0800AM, false), + TimeRange.fromStartEnd(TIME_0830AM, TIME_0900AM, false), + TimeRange.fromStartEnd(TIME_0930AM, TimeRange.END_OF_DAY, true)); + + Assert.assertEquals(expected, actual); + } + + @Test + public void noRoomForOptionalAttendee() { + // Optional Attendee has a meeting that results in the time slot available + // for attendees being too small + Collection events = Arrays.asList( + new Event("Event 1", TimeRange.fromStartEnd(TimeRange.START_OF_DAY, TIME_0830AM, false), + Arrays.asList(PERSON_A)), + new Event("Event 2", TimeRange.fromStartEnd(TIME_0900AM, TimeRange.END_OF_DAY, true), + Arrays.asList(PERSON_A)), + new Event("Event 3", TimeRange.fromStartEnd(TIME_0830AM, TIME_0845AM, true), + Arrays.asList(PERSON_B))); + + MeetingRequest request = new MeetingRequest(Arrays.asList(PERSON_A), DURATION_30_MINUTES); + request.addOptionalAttendee(PERSON_B); + + Collection actual = query.query(events, request); + Collection expected = Arrays.asList( + TimeRange.fromStartDuration(TIME_0830AM, DURATION_30_MINUTES)); + Assert.assertEquals(expected, actual); + } + + @Test + public void twoOptionalAttendeesWithGaps() { + // Only two optional attendees are considered who have gaps in their schedule + Collection events = Arrays.asList( + new Event("Event 1", TimeRange.fromStartDuration(TIME_0800AM, DURATION_30_MINUTES), + Arrays.asList(PERSON_A)), + new Event("Event 2", TimeRange.fromStartDuration(TIME_0900AM, DURATION_30_MINUTES), + Arrays.asList(PERSON_B))); + + MeetingRequest request = new MeetingRequest(Arrays.asList(), DURATION_30_MINUTES); + request.addOptionalAttendee(PERSON_A); + request.addOptionalAttendee(PERSON_B); + + Collection actual = query.query(events, request); + Collection expected = Arrays.asList( + TimeRange.fromStartEnd(TimeRange.START_OF_DAY, TIME_0800AM, false), + TimeRange.fromStartEnd(TIME_0830AM, TIME_0900AM, false), + TimeRange.fromStartEnd(TIME_0930AM, TimeRange.END_OF_DAY, true)); + + Assert.assertEquals(expected, actual); + } + + @Test + public void twoOptionalAttendeesWithNoGaps() { + // Only two optional attendees and no gaps during the day + Collection events = Arrays.asList( + new Event("Event 1", TimeRange.fromStartEnd(TimeRange.START_OF_DAY, TIME_0830AM, false), + Arrays.asList(PERSON_A)), + new Event("Event 2", TimeRange.fromStartEnd(TIME_0900AM, TimeRange.END_OF_DAY, true), + Arrays.asList(PERSON_B))); + + MeetingRequest request = new MeetingRequest(Arrays.asList(PERSON_A, PERSON_B), DURATION_60_MINUTES); + request.addOptionalAttendee(PERSON_A); + request.addOptionalAttendee(PERSON_B); + + Collection actual = query.query(events, request); + Collection expected = Arrays.asList(); + + Assert.assertEquals(expected, actual); + } + +} diff --git a/walkthroughs/week-5-tdd/project/src/test/java/com/google/sps/MeetingRequestTest.java b/walkthroughs/week-5-tdd/project/src/test/java/com/google/sps/MeetingRequestTest.java index 757ae68..bc2a8f3 100644 --- a/walkthroughs/week-5-tdd/project/src/test/java/com/google/sps/MeetingRequestTest.java +++ b/walkthroughs/week-5-tdd/project/src/test/java/com/google/sps/MeetingRequestTest.java @@ -37,8 +37,8 @@ public final class MeetingRequestTest { @Test public void CantAddOptionalAttendeeWhoIsAlsoMandatory() { - MeetingRequest request = new MeetingRequest(Arrays.asList(PERSON_A), DURATION_1_HOUR); - request.addOptionalAttendee(PERSON_A); + MeetingRequest request = new MeetingRequest(Arrays.asList(PERSON_C), DURATION_1_HOUR); + request.addOptionalAttendee(PERSON_C); int actual = request.getOptionalAttendees().size(); int expected = 0;