/// <summary>
        /// Assigns students to rooms for the given course.
        /// </summary>
        /// <param name="course">
        /// The course to schedule for.
        /// </param>
        /// <param name="courseStudents">
        /// The students to try and assign.
        /// </param>
        /// <param name="availableFaculty">
        /// Faculty members that are available for scheduling for this course.
        /// </param>
        /// <param name="labRoom">
        /// If we're scheduling for labs.
        /// </param>
        /// <param name="classRoom">
        /// If we're scheduling for class rooms.
        /// </param>
        /// <param name="instructRoom">
        /// If we're scheduling for instructional rooms.
        /// </param>
        /// <returns>
        /// A list of students that were unable to be scheduled.
        /// </returns>
        private List<Student> AssignStudents(Course course, List<Student> courseStudents, List<Faculty> availableFaculty, bool labRoom, bool classRoom, bool instructRoom, bool library)
        {
            int currentFacultyIndex = 0;
            int requiredHours = course.Requirement.LabHr;

            while (requiredHours > 0)
            {
                int assignedHours = requiredHours > 2 ? 2 : requiredHours;

                // This is the confusing part, we can assign students across different hours if there's too many
                // Now here's the confusing part, we locate a teacher and assign consecutive slots until there's no students
                while (courseStudents.Count > 0)
                {
                    // We can assign either 1 or 2 hour slots, so first see if we can find a 2 hour available lab
                    List<TimeSlot> availability = RequestAvailableRooms(course, labRoom, classRoom, instructRoom, library);

                    // Find the largest available room here
                    TimeSlot largest = FindLargestRoom(availability, courseStudents.Count, assignedHours);

                    // If there is no available slot, we're slightly screwed and will have to forget about scheduling the rest now
                    if (largest == null)
                    {
                        foreach (Student student in courseStudents)
                        {
                            if (!UnscheduledCourses.ContainsKey(student.StudentID))
                                UnscheduledCourses[student.StudentID] = new List<Course>();

                            UnscheduledCourses[student.StudentID].Add(course);
                        }

                        UpdateProgress(string.Format("Failed to schedule {0} students for course {1}", courseStudents.Count, course.Names));
                        return courseStudents;
                    }

                    // Our endDate is the start plus assigned hours
                    DateTime endDate = largest.Start.AddHours(assignedHours);

                    // We've got some slot available, ram everyone into it and keep going
                    Faculty teachingFaculty = availableFaculty[currentFacultyIndex++ % availableFaculty.Count];

                    Schedule newSchedule = new Schedule()
                    {
                        StartTime = largest.Start,
                        EndTime = endDate,
                        CourseID = course.CourseID,
                        RoomID = largest.TargetRoom.RoomID,
                    };
                    CurrentSchedules.Add(newSchedule);
                    Program.Database.Schedules.Add(newSchedule);

                    // Add the teaching faculty time first
                    FacultySchedule facultySchedule = new FacultySchedule()
                    {
                        StartTime = largest.Start,
                        FacultyID = teachingFaculty.FacultyID,
                        RoomID = largest.TargetRoom.RoomID,
                        Schedule = newSchedule,
                    };

                    Program.Database.FacultySchedules.Add(facultySchedule);

                    // Now assign all the students
                    int removedCount = largest.TargetRoom.Capacity > courseStudents.Count ? courseStudents.Count : largest.TargetRoom.Capacity;
                    List<Student> assignedStudents = courseStudents.GetRange(0, removedCount);
                    courseStudents.RemoveRange(0, removedCount);

                    foreach (Student student in assignedStudents)
                    {
                        StudentSchedule studentSchedule = new StudentSchedule()
                        {
                            StudentID = student.StudentID,
                            StartTime = largest.Start,
                            Schedule = newSchedule,
                        };

                        Program.Database.StudentSchedules.Add(studentSchedule);
                    }

                }

                requiredHours -= assignedHours;
            }

            if (courseStudents.Count != 0)
                Console.WriteLine("DUH");

            return courseStudents;
        }
        /// <summary>
        /// Returns a list of time slots available for the given course under the restrictions that it should be a lab room,
        /// class room, instructional room, etc.
        /// </summary>
        /// <param name="course">
        /// The course to account for.
        /// </param>
        /// <param name="labRoom">
        /// Should the room be a lab room?
        /// </param>
        /// <param name="classRoom">
        /// Should the room be a class room?
        /// </param>
        /// <param name="instructRoom">
        /// Should the room be an instructional room?
        /// </param>
        /// <returns>
        /// A list of time slots representing available times at what rooms.
        /// </returns>
        private List<TimeSlot> RequestAvailableRooms(Course course, bool labRoom, bool classRoom, bool instructRoom, bool library)
        {
            List<TimeSlot> availableSlots = new List<TimeSlot>();

            foreach (Room room in Program.Database.Rooms)
            {
                if ((room.RoomID != "Lib" && library) && (!room.Resource.Cad && course.Requirement.Cad) && (!room.Resource.Program && course.Requirement.Program)
                && (!room.Resource.Multi && course.Requirement.Multi) && (!room.Resource.Gaming && course.Requirement.Gaming))
                continue;

                if ((labRoom && !room.Resource.Lab) || (classRoom && !room.Resource.Classroom) || (instructRoom && !room.Resource.Instruct) || (library && !room.RoomID.Contains("Lib")))
                    continue;

                // Figure out where existing schedule usages are
                var usages = from schedule in CurrentSchedules
                             where schedule.RoomID == room.RoomID
                             select schedule;

                // We don't care so much about what's already here, just flag it
                RangedList<Room> usedSlots = new RangedList<Room>();
                usedSlots.Payload = usedSlots.Payload.Distinct().ToList();
                foreach (Schedule schedule in usages)
                {
                    usedSlots.AddRange(schedule.StartTime, schedule.EndTime, room);
                }

                // We start on monday and blow through each day of the week, looking in 1-hour increments for available slots
                DateTime startDate = StartDate();

                for (int day = 0; day < 5; day++)
                {
                    DateTime currentDate = startDate.AddDays(day).AddHours(8.335);
                    DateTime? openStart = currentDate;

                    for (int hour = 0; hour < 8; hour++)
                    {
                        // Is the current date available?
                        RangedList<Room>.PayloadIndex currentSlot = usedSlots.GetIndex(currentDate);

                        if (currentSlot != null)
                        {
                            // We've got to close an availability block
                            if (openStart != null && (DateTime)openStart != currentDate)
                            {
                                DateTime start = (DateTime)openStart;
                                DateTime end = currentDate;

                                // Record our availability range
                                TimeSlot newSlot = new TimeSlot()
                                {
                                    Start = start,
                                    End = end,
                                    TargetRoom = room,
                                };

                                availableSlots.Add(newSlot);
                            }

                            openStart = null; // Not available, move along to the next hour
                        }
                        else
                            if (openStart == null)
                                openStart = currentDate;

                        currentDate = currentDate.AddHours(1);
                    }

                    // This will happen on our first pass because entire days are still available
                    if (openStart != null && (DateTime)openStart != currentDate)
                    {
                        DateTime start = (DateTime)openStart;
                        DateTime end = currentDate;

                        // Record our availability range
                        TimeSlot newSlot = new TimeSlot()
                        {
                            Start = start,
                            End = end,
                            TargetRoom = room,
                        };

                        availableSlots.Add(newSlot);
                    }
                }
            }

            List<TimeSlot> result = availableSlots.Distinct().ToList();
            return result;
        }