Programming Assignment 05: Scheduler
Estimated reading time: 10 minutes
Estimated time to complete: 2–3 hours (plus debugging time)
Prerequisites: Assignment 03
Starter code: scheduler-student.zip
Collaboration: not permitted
Overview
Common complaints among students are that SPIRE is awful, that setting up schedules is awful, and so on. Turns out, common complaints among registrars are that (name-of-University’s-registration-system) is awful, that setting up schedules is awful, and so on. So maybe you can do better?
In this assignment, you’ll write an automated course scheduler, which given a list of students and courses, does its best to put students into their preferred courses while not exceeding their maximum course load (and not exceeding the capacity of any courses).
We’ve provided a large set of unit tests to help with automated testing, though you might also want to write a class with a main
method for interactive testing. The Gradescope autograder includes a few more tests, but they exist primarily to verify you’re not gaming the autograder. If your code can pass the tests we’ve provided, it is likely correct. As before, we’ve disable the timeout code so you can use the debugger, but if your code gets stuck during testing, you might want to uncomment these two lines at the top of each test file:
@Rule
public Timeout globalTimeout = Timeout.seconds(10); // 10 seconds
Goals
- Translate written descriptions of behavior into code.
- Practice writing instance methods.
- Practice interacting with the
List
abstraction. - Test code using unit tests.
Downloading and importing the starter code
As in previous assignments, download and save (but do not decompress) the provided archive file containing the starter code. Then import it into Eclipse in the same way; you should end up with a dna-scheduler-student
project in the “Project Explorer”.
What to do
As usual, look over the files we’ve provided.
The Course
class describes a course, including its name and maximum capacity.
The Student
class represents a single student, their maximum course load, and a list of courses the student would like (in order of preference, most-preferred-to-least).
The Scheduler
class is responsible for maintaining lists of students and courses, and for placing students into courses correctly.
You’ll need to write Course
and Student
before you tackle Scheduler
. These should be straightforward. Notes:
- A student’s preference list might be longer than their maximum load; that’s OK.
- The only thing that might catch you by surprise is the requirement that when these classes return lists (like the
Course.getRoster()
) method, the returned list should not share state with the internal state of theCourse
. How do you guarantee this? By copying the internal state of the roster to a new list and returning the copy.
How can you make this copy? It depends. If your roster is built on the fly from other objects’ state, than the new list you build will automatically be independent. If the roster is a List
instance variable, then copy it using the ArrayList
‘s copy constructor. In other words, by writing something like return new ArrayList<>(this.roster);
.
Then move on to Scheduler
. Some hints:
- To implement
drop
andunenroll
, you may need to add methods toStudent
and/orCourse
. Remember, it’s fine to do so (you can add methods, but you can’t change existing method signatures). - Read the comment for
assignAll
carefully, as correctly implementing the logic of the course assignment algorithm is the hardest part of this assignment. - Notice that there is no constraint on when
scheduleAll
can be run: it might happen after a student is dropped from a course, for example.
Take a look at SchedulerTest.testThree()
to get a sense of how the scheduler works:
- There are already three courses defined (a, b, and c, with capacities 2, 2, and 1, respectively).
testThree
also defines d and e with capacities 2 and 3, respectively. -
There are three students, s, t, and u.
- s wants courses a, b, c, d, e (in that order), up to a maximum load of 3 courses.
- t wants courses c, a, d, e, b, up to 4.
- u wants courses b, a, d, c, e, up to 5.
-
The scheduler gives each student one course (if possible) before giving each student a second course, and so on. So:
- s gets added to a.
- t gets added to c (which is now full).
- u is gets added to b.
At least one schedule was changed, so the scheduler continues:
- s is already in a, and so gets added to b (which is now full).
- t is already in c, and so gets added to a (which is now full).
- u is already in b, cannot be added to a (which is full), and so is added to d.
At least one schedule was changed, so the scheduler continues:
- s is already in a and b, cannot be added to c (which is full), and so is added to d (which is now full.
- t is already in c and a, cannot be added to d (which is full), and so is added to e.
- u is already in b, cannot be added to a (which is full), is already in d, cannot be added to c (which is full), and so is added to e.
At least one schedule was changed, so the scheduler continues:
- s is at max load, so there is nothing to be done for s.
- t is already in c and a, cannot be added to d (which is full), is already in e, and cannot be added to b (which is full) so there is nothing to be done for t.
- u is already in b, cannot be added to a (which is full), is already in d, cannot be added to c (which is full), and is already in e, so there is nothing to be done for u
Nothing was done this round, so the scheduler is done.
The test checks that the students have the right schedules, and that the courses have the right rosters.
Submitting the assignment
When you have completed the changes to your code, you should export an archive file containing the entire Java project. To do this, follow the same steps as from Assignment 01 to produce a .zip
file, and upload it to Gradescope.
Remember, you can resubmit the assignment as many times as you want, until the deadline. If it turns out you missed something and your code doesn’t pass 100% of the tests, you can keep working until it does.