From 56e134b75e5ff847a520f8ffe9985f92fface1f6 Mon Sep 17 00:00:00 2001 From: Michael Aspinwall Date: Mon, 15 Jun 2020 21:23:38 +0000 Subject: [PATCH 1/6] Add initial algorithm for calendar, most tests pass but working on 2 more --- .../src/main/java/com/google/sps/Event.java | 5 +- .../java/com/google/sps/FindMeetingQuery.java | 48 ++++++++++++++++++- 2 files changed, 50 insertions(+), 3 deletions(-) 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..88d49c8 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,54 @@ package com.google.sps; -import java.util.Collection; +import java.util.*; 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(); + Set attendees = new HashSet(request.getAttendees()); + for (Event event : events) { + Set curAttendees = new HashSet(attendees); + curAttendees.retainAll(event.getAttendees()); + if (!(curAttendees.isEmpty())){ + allEvents.add(event); + } + } + Collections.sort(allEvents); + + 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 ((i != allEvents.size() - 1) && curTime.overlaps(allEvents.get(i+1).getWhen())) { + cont = true; + } else { + start = curTime.end(); + cont = false; + } + + if (i == allEvents.size() - 1) { + TimeRange curRange = TimeRange.fromStartEnd(start, 1440, false); + if ((long) curRange.duration() >= request.getDuration()) { + times.add(curRange); + } + + } + } + if (allEvents.size() == 0) { + times.add(TimeRange.fromStartEnd(0, 1440, false)); + } + return times; } + + } From 4472f20f67b557962ecdca632c6e8d9a3bc40d08 Mon Sep 17 00:00:00 2001 From: Michael Aspinwall Date: Mon, 15 Jun 2020 22:13:50 +0000 Subject: [PATCH 2/6] Add a maximizing function for nested times --- .../src/main/java/com/google/sps/FindMeetingQuery.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) 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 88d49c8..5e44584 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 @@ -15,6 +15,7 @@ package com.google.sps; import java.util.*; +import java.lang.Math; public final class FindMeetingQuery { public Collection query(Collection events, MeetingRequest request) { @@ -43,9 +44,10 @@ public Collection query(Collection events, MeetingRequest requ } if ((i != allEvents.size() - 1) && curTime.overlaps(allEvents.get(i+1).getWhen())) { + start = Math.max(curTime.end(), start); cont = true; } else { - start = curTime.end(); + start = Math.max(curTime.end(), start); cont = false; } @@ -57,7 +59,7 @@ public Collection query(Collection events, MeetingRequest requ } } - if (allEvents.size() == 0) { + if (allEvents.size() == 0 && request.getDuration() <= 1440) { times.add(TimeRange.fromStartEnd(0, 1440, false)); } return times; From 31773a40f7f3ccc89ca269cec8fefeb5852556d9 Mon Sep 17 00:00:00 2001 From: Michael Aspinwall Date: Tue, 16 Jun 2020 17:14:03 +0000 Subject: [PATCH 3/6] Remove magic numbers and add comments --- .../main/java/com/google/sps/FindMeetingQuery.java | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) 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 5e44584..0a44405 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 @@ -22,6 +22,7 @@ public Collection query(Collection events, MeetingRequest requ long duration = request.getDuration(); ArrayList allEvents = new ArrayList(); Set attendees = new HashSet(request.getAttendees()); + //Add all events that attendees go to for (Event event : events) { Set curAttendees = new HashSet(attendees); curAttendees.retainAll(event.getAttendees()); @@ -41,29 +42,28 @@ public Collection query(Collection events, MeetingRequest requ 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, 1440, false); + 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() <= 1440) { - times.add(TimeRange.fromStartEnd(0, 1440, false)); + 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; } - - } From f102abca3c029c5f00718891b63501cf690d2cc8 Mon Sep 17 00:00:00 2001 From: Michael Aspinwall Date: Wed, 17 Jun 2020 17:43:24 +0000 Subject: [PATCH 4/6] Added optional attendees to the calendar request --- .../java/com/google/sps/FindMeetingQuery.java | 21 +++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) 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 0a44405..de81ecc 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 @@ -21,17 +21,35 @@ public final class FindMeetingQuery { public Collection query(Collection events, MeetingRequest request) { 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); + allEvents.add(event); + } + if(!(curAttendeesOptional.isEmpty())){ + allEventsOptional.add(event); } + } Collections.sort(allEvents); + Collections.sort(allEventsOptional); + ArrayList timesOptional = getTimes(allEventsOptional, request); + if (!(timesOptional.isEmpty())){ + 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; @@ -58,7 +76,6 @@ public Collection query(Collection events, MeetingRequest requ if ((long) curRange.duration() >= request.getDuration()) { times.add(curRange); } - } } if (allEvents.size() == 0 && request.getDuration() <= TimeRange.END_OF_DAY) { From 45835d05a478e65fe5ade6cc512c2acbe4dd9654 Mon Sep 17 00:00:00 2001 From: Michael Aspinwall Date: Wed, 17 Jun 2020 18:24:46 +0000 Subject: [PATCH 5/6] add 3 tests for optional attendee functionality --- .../com/google/sps/FindMeetingQueryTest.java | 70 +++++++++++++++++++ 1 file changed, 70 insertions(+) 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..0b7b518 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,73 @@ 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); + } + } From 444b7a0889e276c5e4d7fa788d9a48c49e1be988 Mon Sep 17 00:00:00 2001 From: Michael Aspinwall Date: Wed, 17 Jun 2020 20:19:30 +0000 Subject: [PATCH 6/6] Added more tests, fixed a small issue --- .../java/com/google/sps/FindMeetingQuery.java | 2 +- .../com/google/sps/FindMeetingQueryTest.java | 46 +++++++++++++++++++ 2 files changed, 47 insertions(+), 1 deletion(-) 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 de81ecc..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 @@ -42,7 +42,7 @@ public Collection query(Collection events, MeetingRequest requ Collections.sort(allEvents); Collections.sort(allEventsOptional); ArrayList timesOptional = getTimes(allEventsOptional, request); - if (!(timesOptional.isEmpty())){ + if (!(timesOptional.isEmpty()) || request.getAttendees().size() == 0){ return timesOptional; } ArrayList times = getTimes(allEvents, request); 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 0b7b518..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 @@ -340,5 +340,51 @@ public void disregardIfNoFit() { 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); + } + }