
import heapq

from angular_flask.logging import logging
from angular_flask.classtime.schedule import Schedule

class ScheduleGenerator(object):
    """
    Class which builds optimal schedules out of
    course listings.
    """
    def __init__(self, cal, term, course_ids):
        """
        course_ids should be a list of integers representing the
        courses which should be in the schedule
        """
        logging.info('Creating ScheduleGenerator with course ids {}'.format(course_ids))
        self._course_ids = course_ids
        self._schedules = None

        self._cal = cal
        self._cal.select_current_term(term)

    def get_schedules(self):
        """Returns schedule objects generated from
        the courses passed upon initialization
        """
        self._generate_schedules()
        return self._schedules

    def _generate_schedules(self):
        """
        Generates good schedules based on the course list
        provided on initialization.

        The schedule generated returned will *not* be one
        of the schedules already in self.generated_schedules

        Backtracking - just do a depth-first search of the
        courses
        - maintain them in a priority queue with the sort
          order governed by their "score" regarding to
          whatever cost functions we define
        """
        logging.info('Generating schedules for course ids {}'.format(self._course_ids))
        components = self._cal.get_components_for_course_ids(self._course_ids)
        logging.debug('Components to schedule: {}'.format(len(components)))

        HEAP_SIZE = 50

        components = sorted(components, key=lambda component: len(component))
        candidates = [Schedule()]
        for i, component in zip(range(len(components)), components):
            logging.debug('Scheduling Course {}:{} ({}/{})'.format(
                          component[0].get('course'), component[0].get('component'),
                          i+1, len(components)))
            for sched in candidates[:]:
                for section in component:
                    if sched.conflicts(section):
                        continue
                    new_candidate = sched.add_section_and_deepcopy(section)
                    if len(candidates) > HEAP_SIZE:
                        heapq.heapreplace(candidates, new_candidate)
                    else:
                        heapq.heappush(candidates, new_candidate)
            logging.debug('# Candidates: {}'.format(len(candidates)))

        if len(candidates) > 0:
            self._schedules = [heapq.heappop(candidates) for _ in range(5)]
        else:
            self._schedules = None

@@ -411,97 +411,8 @@
 %22%22%22%0A
-        logging.info('Creating ScheduleGenerator with course ids %7B%7D'.format(course_ids))%0A
     
@@ -445,16 +445,16 @@
 rse_ids%0A
+
         
@@ -1448,17 +1448,30 @@
 .debug('
-C
+There are %7B%7D c
 omponent
@@ -1483,20 +1483,16 @@
 schedule
-: %7B%7D
 '.format
@@ -1766,17 +1766,18 @@
 se %7B%7D:%7B%7D
- 
+%5Ct
 (%7B%7D/%7B%7D)'
@@ -2199,16 +2199,17 @@
 dates) %3E
+=
  HEAP_SI
@@ -2404,9 +2404,10 @@
 ug('
-#
+%7B%7D
  Can
@@ -2417,12 +2417,8 @@
 ates
-: %7B%7D
 '.fo

improve logging