def create_schedules(courses: List[CourseFilter], term: str, unavailable_times: List[UnavailableTime], include_full: bool, num_schedules: int = 10) -> List[Tuple[int]]: """ Generates and returns a schedule containing the courses provided as an argument. Args: courses: A list of (subject, course num) tuples to create schedules for term: Term code to create a schedule for unavailable_times: List of times the user doesn't want any classes include_full: Whether or not to include classes with no seats in schedules num_schedules: Max number of schedules to generate, will always try to make at least 1 Returns: List of tuples each containing section ids of a valid schedule. These can be used by our API to efficiently query sections. """ # meetings: Tuple of dicts mapping sections to meetings for each course meetings = tuple( _get_meetings(course, term, include_full, unavailable_times) for course in courses) # Get valid section ids for each course valid_choices = tuple(tuple(section_ids) for section_ids in meetings) schedules = [] # Generate random arrangements of sections and create schedules for schedule in random_product(*valid_choices): if _schedule_valid(meetings, schedule): schedules.append(schedule) if len(schedules) >= num_schedules: break return schedules
def test_random_product_handles_empty_iterables(self): """ Tests that random_product generates nothing and doesn't throw an error if the provided iterables are empty """ # Arrange arrs = [] num_products = 100 # Act random_product_set = set(random_product(*arrs, limit=num_products)) # Assert self.assertFalse(random_product_set)
def test_random_product_gets_all_products(self): """ Tests that random_product generates all unique products if there are less than or equal to the limit parameter products possible """ # Arrange arrs = [list(range(10)) for _ in range(4)] num_schedules = 10_000 # Act random_product_set = set(random_product(*arrs, limit=num_schedules)) product_set = set(product(*arrs)) # Assert self.assertEqual(random_product_set, product_set)
def test_random_product_handles_empty_iterable(self): """ Tests that random_product generates nothing and doesn't throw an error if an iterable provided is empty """ # Arrange arrs = [list(range(10)) for _ in range(3)] arrs.append([]) num_products = 1_000 # Act random_product_set = set(random_product(*arrs, limit=num_products)) # Assert self.assertFalse(random_product_set)
def test_random_product_gets_unique_products(self): """ Tests that random_product gets only unique products if there are more than the provided limit parameter possible """ # Arrange arrs = [list(range(10)) for _ in range(4)] num_products = 9_999 # Act random_product_set = set(random_product(*arrs, limit=num_products)) product_set = set(product(*arrs)) intersection = random_product_set.intersection(product_set) # Assert self.assertEqual(len(random_product_set), num_products) self.assertEqual(len(intersection), num_products)