The goal of this assignment is to work with object-oriented programming in Python.
You will be doing your work in Python for this assignment. You may choose to work on this assignment on a hosted environment (e.g. tiger) or on your own local installation of Jupyter and Python. You should use Python 3.8 or higher for your work. To use tiger, use the credentials you received. If you work remotely, make sure to download the .py files to turn in. If you choose to work locally, Anaconda is the easiest way to install and manage Python. If you work locally, you may launch Jupyter Lab either from the Navigator application or via the command-line as jupyter-lab
.
In this assignment, we will be implementing a collection of classes that work together to orchestrate course scheduling in a university setting. There will be a central registrar that coordinates scheduling for students and professors, and a test for whether courses conflict in a person’s schedule. You will need to test your classes to make sure they work properly (See Section 5 for a summary of the items to be implemented and some non-comprehensive test code.)
The assignment is due at 11:59pm on Friday, March 19.
You should submit the completed notebook file required for this assignment on Blackboard. The filename of the notebook should be a6.ipynb
.
Please make sure to follow instructions to receive full credit. Because you will be writing classes and adding to them, you do not need to separate each part of the assignment. Please document any shortcomings with your code. You may put the code for each part into one or more cells.
The first cell of your notebook should be a markdown cell with a line for your name and a line for your Z-ID. If you wish to add other information (the assignment name, a description of the assignment), you may do so after these two lines.
Create four classes related to the people involved in university course scheduling: Academic, Student, GraduateStudent, and Instructor. Academic is the base class which has a first name, last name, and campus_id. It also has a field max_credits
which should be initialized to the default value for the type of person (more on this later in the paragraph). While it will be used as an abstract base class (not intended to be instantiated), you do not need to flag it as such (but may). Student is an Academic that has a level (“Freshman”, …, “Senior”), and GraduateStudent is a Student whose level is always “Graduate”. Instructor is an Academic that has a rank (“Assistant Professor”, …, “Instructor”). You must use inheritance properly here. Each student should have a default maximum number of credits of 16, each graduate student a default maximum of 12, and each instructor a default maximum of 9. Use a class attribute, MAX_CREDITS
to store this default, but only one place in the code should assign to the max_credits field.
self
will look up attributes according to the MRO so with multiple definitions of MAX_CREDITS, it will “do the expected thing”.Create a Course class that stores information about a course: department, course number, course name, section, number of credits, times. The course class also keeps track of the instructor (which may be unassigned) and all students enrolled. Note that times will be submitted as a list of tuples of the form (day : str, start_time : int, end_time : int). Add a method to produce a string representation that lists the department, course number, and section along with the times. Add a check_time_conflicts
static method that given two time structures (list of tuples), checks if any times conflict, returning True if the two lists conflict and False otherwise. Two times conflict if they have meetings on the same day such that the starting time of one meeting is in between the starting and ending times of another meeting. For example, (“Mon”, 11, 13) and (“Mon”, 12, 14) conflict, but (“Mon”, 11, 13) and (“Mon”, 13, 15) do not. Add support for the &
operator to return True if the times of any two courses conflict and False otherwise. The class should have enroll
and drop
methods to add/remove a student from the course.
a < b < c
checks that b
is between a
and c
.Create a Schedule class that tracks all courses an Academic is involved in. The constructor should take an optional list of courses to be added to the schedule. It should have a credits
property (getter only) that returns the sum of the number of credits in all courses. It should have an add_course
method that checks if the course to be added conflicts with other courses. If it does, it should raise an exception alerting the user.
Update the Academic class to add a schedule to each instance plus add_course
and remove_course
methods. The add_course
method should first check if the course to be added will exceed the maximum number of credits for the person. If it doesn’t, it should check whether the course conflicts with the person’s current schedule. If it doesn’t, the course should be added to the schedule. If it does conflict, raise an exception. Override the add_course
method in the Student to enroll (add) the student to the Course and in the Instructor class to set the instructor of the Course. The remove_course
should drop a student from the Course, and unset the instructor of the course. Note that these methods are different!
super()
to use the Academic add/remove_course methods while also doing the (different) extra steps for students/instructors.Create a Registrar class that orchestrates the scheduling process. The registrar should keep track of all academic persons and all courses. It should have add_persons
, add_courses
, add_person_to_course
, remove_person_from_course
, and change_course_time
methods. The add/remove person to/from course methods should take a campus id, department, course_number, and section, and then add the person referenced by the id to the course referenced by the three other pieces of information. You should call the add/remove_course methods, but note that polymorphism will be in effect here, meaning the method called will be different for students and instructors. The change_course_time
method should call a change_time
method implemented in the Course class, and that Course method must check that the proposed new time does not cause any conflicts with any currently enrolled students’ or the assigned instructor’s schedules. If it does, the method should raise an exception. If it doesn’t, the time of the course should be changed.
change_time
must checked enrolled students and the instructor. Remember these are stored in different fields.The final list of classes and methods/properties to be added. Note that all classes should have constructors that properly initialize objects, and the instance fields are not listed here.
The following code should help you test your work:
= Student("z143", "Catherine", "Smith", "Senior")
s1 = Student("z352", "Niraj", "Kumar", "Sophomore")
s2 = GraduateStudent("z785", "Divya", "Bharti")
s3 = GraduateStudent("z982", "James", "O'Brien")
s4
= Instructor("a421", "Jennifer", "Martinez", "Professor")
i1 = Instructor("a572", "Jonathan", "Jones", "Instructor")
i2
= Course("CSCI", 1543, "Programming Principles in Python", 1, 3, [("Mon", 10, 12), ("Wed", 10, 12)])
c1 = Course("CSCI", 1342, "Computer Networks", 2, 4, [("Tue", 14, 16), ("Thu", 14, 16), ("Fri", 12, 13)])
c2 = Course("CSCI", 1352, "Computer Graphics", 1, 3, [("Tue", 10, 12), ("Thu", 10, 12)])
c3 = Course("SOCI", 1230, "Introduction to Sociology", 1, 3, [("Mon", 11, 13), ("Thu", 11, 13)])
c4 = Course("POLS", 1100, "American Politics", 2, 3, [("Tue", 10, 12), ("Thu", 10, 12)])
c5 = Course("SOCI", 1450, "Classical Sociological Theory", 1, 3, [("Mon", 12, 13), ("Wed", 12, 13), ("Fri", 12, 13)])
c6
= Registrar()
r
r.add_persons([s1,s2,s3,s4,i1,i2]) r.add_courses([c1,c2,c3,c4,c5, c6])
"a572", "SOCI", 1230, 1)
r.add_person_to_course("a572", "POLS", 1100, 2) # error due to conflict r.add_person_to_course(
"SOCI", 1230, 1, [("Mon", 9, 11), ("Wed", 9, 11)])
r.change_course_time("a572", "SOCI", 1450, 1)
r.add_person_to_course("a421", "CSCI", 1543, 1)
r.add_person_to_course("a421", "CSCI", 1342, 2)
r.add_person_to_course("a421", "CSCI", 1352, 1) # error due to max credits r.add_person_to_course(
"z785", "SOCI", 1230, 1)
r.add_person_to_course("z785", "CSCI", 1352, 1)
r.add_person_to_course("z143", "CSCI", 1543, 1)
r.add_person_to_course("z143", "CSCI", 1342, 2)
r.add_person_to_course("z143", "SOCI", 1230, 1) # error due to conflict r.add_person_to_course(
"SOCI", 1230, 1, [("Tue", 11, 13), ("Thu", 11, 13)]) # error due to conflict r.change_course_time(
"SOCI", 1230, 1, [("Tue", 12, 14), ("Thu", 12, 14)])
r.change_course_time( "z143", "SOCI", 1230, 1) r.add_person_to_course(