diff --git a/walkthroughs/week-5-tdd/project/src/main/java/com/google/sps/Event.java b/walkthroughs/week-5-tdd/project/src/main/java/com/google/sps/Event.java index 87b1194..4185d57 100644 --- a/walkthroughs/week-5-tdd/project/src/main/java/com/google/sps/Event.java +++ b/walkthroughs/week-5-tdd/project/src/main/java/com/google/sps/Event.java @@ -23,7 +23,7 @@ * Event is the container class for when a specific group of people are meeting and are therefore * busy. Events are considered read-only. */ -public final class Event { +public final class Event implements Comparable{ private final String title; private final TimeRange when; private final Set attendees = new HashSet<>(); @@ -75,6 +75,9 @@ public Set getAttendees() { // internal data. return Collections.unmodifiableSet(attendees); } + public int compareTo(Event eventB) { + return this.getWhen().start() - eventB.getWhen().start(); + } @Override public int hashCode() { 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 dadf069..6ea072a 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 @@ -14,10 +14,73 @@ package com.google.sps; -import java.util.Collection; +import java.util.*; +import java.lang.Math; public final class FindMeetingQuery { public Collection query(Collection events, MeetingRequest request) { - throw new UnsupportedOperationException("TODO: Implement this method."); + long duration = request.getDuration(); + ArrayList allEvents = new ArrayList(); + ArrayList allEventsOptional = new ArrayList(); + Set attendees = new HashSet(request.getAttendees()); + Set allAttendeesOptional = new HashSet(request.getAttendees()); + allAttendeesOptional.addAll(request.getOptionalAttendees()); + //Add all events that attendees go to + for (Event event : events) { + Set curAttendees = new HashSet(attendees); + Set curAttendeesOptional = new HashSet(allAttendeesOptional); + curAttendees.retainAll(event.getAttendees()); + curAttendeesOptional.retainAll(event.getAttendees()); + if (!(curAttendees.isEmpty())){ + allEvents.add(event); + } + if(!(curAttendeesOptional.isEmpty())){ + allEventsOptional.add(event); + } + + } + Collections.sort(allEvents); + Collections.sort(allEventsOptional); + ArrayList timesOptional = getTimes(allEventsOptional, request); + if (!(timesOptional.isEmpty()) || request.getAttendees().size() == 0){ + return timesOptional; + } + ArrayList times = getTimes(allEvents, request); + return times; + } + + private ArrayList getTimes(ArrayList allEvents, MeetingRequest request) { + ArrayList times = new ArrayList(); + int start = 0; + Boolean cont = false; + for (int i = 0; i < allEvents.size(); i++) { + TimeRange curTime = allEvents.get(i).getWhen(); + if (!cont) { + TimeRange curRange = TimeRange.fromStartEnd(start, curTime.start(), false); + if ((long) curRange.duration() >= request.getDuration()) { + times.add(curRange); + } + } + //If next event overlaps with current, make start the greater of the two events + if ((i != allEvents.size() - 1) && curTime.overlaps(allEvents.get(i+1).getWhen())) { + start = Math.max(curTime.end(), start); + cont = true; + } else { + //If it doesn't overlap check gap during next iteration + start = Math.max(curTime.end(), start); + cont = false; + } + //If last event check if end of day is a possible time + if (i == allEvents.size() - 1) { + TimeRange curRange = TimeRange.fromStartEnd(start, TimeRange.END_OF_DAY, true); + if ((long) curRange.duration() >= request.getDuration()) { + times.add(curRange); + } + } + } + if (allEvents.size() == 0 && request.getDuration() <= TimeRange.END_OF_DAY) { + times.add(TimeRange.fromStartEnd(TimeRange.START_OF_DAY, TimeRange.END_OF_DAY, true)); + } + return times; } } 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..666c071 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; @@ -270,5 +272,119 @@ public void notEnoughRoom() { Assert.assertEquals(expected, actual); } + @Test + public void disregardOptionalAttendee() { + 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(TimeRange.START_OF_DAY, TimeRange.END_OF_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 considerOptionalAttendee() { + 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 disregardIfNoFit() { + // Have one person, but make it so that there is just enough room at one point in the day to + // have the meeting. + // + // Events : |--A--| |----A----| + // Day : |---------------------| + // Options : |-----| + + 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 onlyOptionalFit() { + // Have one person, but make it so that there is just enough room at one point in the day to + // have the meeting. + // + // Events : |--A--| |----A----| + // Day : |---------------------| + // Options : |-----| + + 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(), DURATION_30_MINUTES); + request.addOptionalAttendee(PERSON_A); + 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 noMandatoryAttendeesConflict() { + // Have one person, but make it so that there is not enough room at any point in the day to + // have the meeting. + // + // Events : |--A-----| |-----A----| + // Day : |---------------------| + // Options : + + 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))); + + MeetingRequest request = new MeetingRequest(Arrays.asList(), DURATION_60_MINUTES); + request.addOptionalAttendee(PERSON_A); + Collection actual = query.query(events, request); + Collection expected = Arrays.asList(); + + Assert.assertEquals(expected, actual); + } + }