Answered step by step
Verified Expert Solution
Link Copied!

Question

1 Approved Answer

This time all the files are given to you. The project has a total of six files. -The appointment.py is the module for the appointments

This time all the files are given to you. The project has a total of six files.

-The appointment.py is the module for the appointments classes. We use test_appointment.py to test this module.

-The calendar.py is the module for the calendar class. We use test_calendar.py to test this module.

-The file utility.py and generator.py are modules that have helper methods. You might find something valuable in utility.py.

-You should start by implementing the appointment module requirements. In the appointment module you are given skeleton classes to get started. We implemented the constructors for all of them, but you might need to change the constructor of WorkAppointment and PersonalAppointment. All you need is to validate the start_time and end_time before you create an object.

-In the Appointment abstract class we implemented the priority and __str__ methods for you. However, you should override the priority method for both WorkAppointment and PersonalAppointment where it returns 1 for WorkAppointment and 2 for PersonalAppointment. See the test case test_priority for more information.

-By fixing the constructors of WorkAppointment and PersonalAppointment and implementing the priority method for each, these two classes should be ready. All the remaining work should be in their parent class.

-Next, implement the __lt__ and __gt__ methods for the Appointment class. These are very critical methods, and you should carefully implement them.

<: "before". Appointment a is before appointment b iff the finish time of a is equal or earlier than the start time of b.

>: "after". Appointment a is after appointment b iff the start time of a is equal or after the finish time of b.

-The next method you should implement is the __eq__ method. We say two appointments are equal if they have the same start_time and end_time. The title of the appointment doesn't matter in equality.

-By now you should have implemented all the basic methods. You have two other methods left in Appointment. First, the overlap method where you return True if two appointments overlap. Second, the intersect method where you find the duration of overlap in hours (see utility.py for help).

-We say two appointments overlap if they share the same time. For example, if we have scheduled office hours from 12:00pm to 1:30pm, and scheduled another meeting from 1pm to 2pm, then there is a conflict in our schedule because those appointments overlap in time. Note that you have already implemented methods to determine whether an appointment a is over when appointment b starts (i.e., (a < b) or vice versa (a > b)). You should make use of these rather than coding the same logic again.

-You must also create method intersect for determining the period (in hours) of overlap between two appointments. We gave you a helper method in utility.py that convert duration to hours. You may use it if you want.

-The main difference between overlap and intersect is that the overlap tells you if there is overlap while intersect gives you the duration of overlap. You might find the figures below helpful in understand what overlap means.

-By now if you implemented all the methods for Appointment above correctly, all the test cases in test_appointment.py should pass.

-Next, we need to implement what is left of the Calendar class. All the methods for the Calendar class are written for you. However, the ones that have raise NotImplemented("FIX ME!") mean you should fix the method. As you may have already noticed, the Calendar class is a wrapper class. It wraps the list class. Thus, we need to implement some list methods ourselves.

-First unimplemented method is the __len__ methods. By implementing __len__ we would be able to say len(an instances of Calendar) where we would get the number of elements in the list self.appointments.

-The other methods that you need to implement is the total_intersections method. The main goal of this method is to return the total overlap duration in the whole calendar. Thus, you need to loop through the list of appointments to check for overlap as you implemented it in the class Appointment. We already defined what it means for two appointments to overlap. However, in the calendar you should consider that there might be more than two elements overlapping. Suppose we have appointments a...e with start and finish times as shown on the figure on the left. These appear in the Calendar object in order a, b, c, d, e, that is, in order of their start times (because we can sort them in that order using the sort method). Now consider which appointments a must be compared with. We must compare a with b and then with each subsequent appointment until we reach d. When we reach d and notice that d starts after a is finished, we do not have to look farther. Any appointment object that appears after e in the sorted sequence must also start after a has finished; thus it has no overlap with a. Next consider the set of appointments we must compare b with. We do not need to consider a again, because we have already found that conflict. We must consider the appointments that appear after b in the sorted list, but only until we find one that starts after b has finished. Given this explanation try implementing your search algorithm using two nested loops (for loop inside another one). But it is important that you break the search of the inner loop to achieve a fast search.

-We have created three different test cases for the total_intersections. The first one test the correctness of the search and calculations, while the other two test the performance of the method. We add 10,000 appointment on each to see if you can search them in less than 2 seconds. This is possible if you know when to stop searching for overlap in a given appointment.

-When you have completed these steps, all the test cases should succeed. Note that this is not an ironclad guarantee that your code is correct. We will use a few more tests, which we do not share with you, in grading. Our extra tests help ensure that you are really solving the problem and not taking shortcuts that provide correct results only for the known tests.

Codes----------------------------------------------------------------------------------

appointment.py

"""

This is a skeleton of the Appointment module.

Most of your implementations should be in the Appointment

class. Only the ones that are special for each subtype

will be implemented in the subtype.

"""

import datetime

import utility

class Appointment:

def __init__(self, title: str, start_time: datetime, end_time: datetime):

if type(self) is Appointment:

raise NotImplementedError("I'm an abstract class!")

self.title = title

self.start_time = start_time

self.end_time = end_time

def priority(self) -> int:

raise NotImplementedError("I'm an abstract class!")

def __str__(self):

return f"{self.start_time} - {self.end_time} | {self.title}"

# more methods here!

class WorkAppointment(Appointment):

def __init__(self, title: str, start_time: datetime, end_time: datetime):

# Make sure you check if the end_time comes before the start time!

super().__init__(title, start_time, end_time)

# more methods here!

class PersonalAppointment(Appointment):

def __init__(self, title: str, start_time: datetime, end_time: datetime):

# Make sure you check if the end_time comes before the start time!

super().__init__(title, start_time, end_time)

# more methods here!

-----------------------------------------------------------------------------------------------------------

calendar.py

"""

This is the Calendar Module.

We gave you some basic methods.

Please implement all the methods that says FIX ME!

"""

from appointment import Appointment

class Calendar:

"""

A Calendar class which is a wrapper of the list (no inheritance).

We only need few functionalities of the list class. Thus, we wrap it instead

of inheriting it.

"""

def __init__(self):

"""

We initialize a Calendar by having an empty list.

It is already done for you!

"""

self.appointments = []

def append(self, element: "Appointment"):

"""

Adding a new appointment to our Calendar!

:param element: A instant of an Appointment class or any of its children.

"""

self.appointments.append(element)

def __str__(self) -> str:

"""

We print a Calendar by having each appointment in a new line

:return: A long list of appointments!

"""

lines = [str(app) for app in self.appointments]

return ' '.join(lines)

def __len__(self) -> int:

"""

By implementing __len__ we then can say len(calendar) which should

return the number of items in our list. Thus, you should 'delegate'

the len of appointment list to this method.

:return: The number of elements in our list of appointments.

"""

raise NotImplemented("FIX ME!")

def sort(self):

"""

Sort the element of the list based on their start time!

You need this to be efficient in calculating the intersections.

"""

self.appointments.sort(key=lambda app: app.start_time)

def total_intersections(self) -> float:

"""

For all the appointments this calendar has.

It should go over all of them checking for conflict.

If there is one, then it should keep track of the intersection total.

Intersections as defined in the Appointment class are the duration of overlap in hour.

This intersection value should be calculated in the Appointment class itself.

This method main goal is to find the total intersection value in an efficient time.

Your algorithm must run in time O(n lg n) where n is max(number of appointments, number of conflicts).

:return: Total intersection time in hours.

"""

raise NotImplemented("FIX ME!")

----------------------------------------------------------------------------------------------utility.py

"""

This is a utility module.

It only has helper methods that you might find useful.

"""

from datetime import timedelta

def convert_timedelta_to_hours(td: timedelta) -> float:

"""

A method that takes a timedelta (a timedelta is duration

representation that you would get if you subtract two

times from each other), and return the duration given

in hours.

:param td: A duration (for example 11 days!)

:return: The duration given in hours.

"""

sec_per_hour = 60 * 60 # minutes * seconds

return td.total_seconds()/sec_per_hour

Step by Step Solution

There are 3 Steps involved in it

Step: 1

blur-text-image

Get Instant Access to Expert-Tailored Solutions

See step-by-step solutions with expert insights and AI powered tools for academic success

Step: 2

blur-text-image

Step: 3

blur-text-image

Ace Your Homework with AI

Get the answers you need in no time with our AI-driven, step-by-step assistance

Get Started

Recommended Textbook for

Databases Illuminated

Authors: Catherine M Ricardo, Susan D Urban

3rd Edition

1284056945, 9781284056945

More Books

Students also viewed these Databases questions