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 569c4eb..4c70f2b 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 @@ -32,7 +32,24 @@ public final class FindMeetingQuery { * @return A collection of available times. */ public Collection query(Collection events, MeetingRequest request) { - List unavailableTimeRanges = getUnavailableTimes(events, request.getAttendees()); + Collection suggestedTimeRanges = findTimeForMeetingRequest(events, request, true); + + if (suggestedTimeRanges.size() == 0 && request.getAttendees().size() != 0) { + suggestedTimeRanges = findTimeForMeetingRequest(events, request, false); + } + + return suggestedTimeRanges; + } + + public Collection findTimeForMeetingRequest(Collection events, MeetingRequest request, + boolean includeOptionalAttendees) { + List attendees = new ArrayList<>(request.getAttendees()); + + if (includeOptionalAttendees) { + attendees.addAll(request.getOptionalAttendees()); + } + + List unavailableTimeRanges = getUnavailableTimes(events, attendees); List suggestedTimeRanges = findAvailableTimeRanges(unavailableTimeRanges, request.getDuration()); return suggestedTimeRanges; 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..d58c149 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,6 +34,7 @@ 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); @@ -43,6 +44,7 @@ public final class FindMeetingQueryTest { private static final int TIME_1000AM = TimeRange.getTimeInMinutes(10, 0); private static final int TIME_1100AM = TimeRange.getTimeInMinutes(11, 00); + 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; @@ -121,6 +123,51 @@ public void everyAttendeeIsConsidered() { Assert.assertEquals(expected, actual); } + @Test + public void optionalAttendeesAreIgnoredIfBusy() { + 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 optionalAttendeesAreConsideredIfAvailable() { + 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.fromStartDuration(TIME_0830AM, 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_0800AM, false), + TimeRange.fromStartEnd(TIME_0930AM, TimeRange.END_OF_DAY, true)); + + Assert.assertEquals(expected, actual); + } + @Test public void overlappingEvents() { // Have an event for each person, but have their events overlap. We should only see two options. @@ -223,6 +270,65 @@ public void justEnoughRoom() { Assert.assertEquals(expected, actual); } + @Test + public void optionalAttendeesIgnoredIfNotEnoughTime() { + 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.fromStartDuration(TIME_0830AM, DURATION_15_MINUTES), + 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 findsTimeWithOnlyOptionalAttendees() { + 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(new ArrayList<>(), 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 findsNoTimeWithOnlyBusyOptionalAttendees() { + 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_0830AM, TimeRange.END_OF_DAY, true), + Arrays.asList(PERSON_B))); + + MeetingRequest request = new MeetingRequest(new ArrayList<>(), DURATION_30_MINUTES); + request.addOptionalAttendee(PERSON_A); + request.addOptionalAttendee(PERSON_B); + + Collection actual = query.query(events, request); + Collection expected = Arrays.asList(); + + Assert.assertEquals(expected, actual); + } + @Test public void ignoresPeopleNotAttending() { // Add an event, but make the only attendee someone different from the person looking to book