Example #1
0
 def test_mapping_in_groups(self):
     items = [self.SampleObject(i % 3, i + 1, i + 2) for i in range(10)]
     ordered = utils.dict_by_attr(items, 'a')
     self.assertEqual([0, 1, 2], ordered.keys())
     self.assertEqual([(0, 1, 2), (0, 4, 5), (0, 7, 8), (0, 10, 11)], ordered[0])
     self.assertEqual([(1, 2, 3), (1, 5, 6), (1, 8, 9), ], ordered[1])
     self.assertEqual([(2, 3, 4), (2, 6, 7), (2, 9, 10), ], ordered[2])
Example #2
0
def cache_conflicts(semester_year=None, semester_month=None, semester=None, sql=True, stdout=False):
    assert (semester_year and semester_month) or semester, "Semester year & month must be provided or the semester object."
    import sys
    # trash existing conflict data...
    if not semester:
        semester = courses.Semester.objects.get(year=semester_year, month=semester_month)
    #SectionConflict.objects.filter(semester=semester).delete()
    Syncer = Synchronizer(SectionConflict, SectionConflict.objects.values_list('id', flat=True))

    sections = courses.Section.objects .select_related('course', 'semester') \
            .by_semester(semester).prefetch_periods()
    section_courses = dict_by_attr(sections, 'course')

    mapping = {}
    for id, sid1, sid2 in SectionConflict.objects.filter(semester=semester).values_list('id', 'section1', 'section2'):
        mapping[(sid1, sid2)] = id

    conflicts = []

    def log(msg):
        sys.stdout.write(msg)
        sys.stdout.flush()

    def perform_insert(conflicts):
        SectionConflict.objects.bulk_create(conflicts)

    count = 0
    for course1, course2 in itertools.combinations(section_courses.keys(), 2):
        for section1, section2 in itertools.product(section_courses[course1], section_courses[course2]):
            if section1.conflicts_with(section2):
                if section1.id > section2.id:
                    section1, section2 = section2, section1

                count += 1
                if sql:
                    if count % 10000 == 0:
                        perform_insert(conflicts)
                        conflicts = []
                        log('.')
                    if mapping.get((section1.id, section2.id), None) is None:
                        conflicts.append(
                            SectionConflict(section1=section1, section2=section2, semester=semester)
                        )
                    else:
                        Syncer.exclude_id(mapping[(section1.id, section2.id)])
                else:
                    log('C')
                    Syncer.get_or_create(
                        section1=section1,
                        section2=section2,
                        semester=semester,
                    )

    if sql and conflicts:
        perform_insert(conflicts)
        log('.')

    log('\n')
    Syncer.trim(semester=semester)
    log('\n')
Example #3
0
def schedules(request, id=None, version=None):
    selection = None
    if id:
        selection = Selection.objects.get(id=id)
        section_ids = selection.section_ids
    else:
        section_ids = int_list(request.REQUEST.getlist('section_id'))

    created = False
    if not selection:
        selection, created = Selection.objects.get_or_create(
            section_ids=section_ids)

    sections = SectionProxy.objects.filter(id__in=section_ids) \
        .select_related('course').prefetch_periods()
    selected_courses = dict_by_attr(sections, 'course')
    conflict_cache = ConflictCache(
        SectionConflict.objects.as_dictionary([s.id for s in sections]))

    # if check flag given, return only if we have a schedule or not.
    if request.REQUEST.get('check'):
        return {'context': has_schedule(selected_courses, conflict_cache)}

    # check the cache
    if not created and selection.api_cache:
        return {'context': json.loads(selection.api_cache)}

    schedules = compute_schedules(selected_courses, conflict_cache)

    periods = set(p for s in sections for p in s.get_periods())
    timerange, dow_used = period_stats(periods)

    # note: if you change this, caches will have to be updated somehow
    context = {
        'time_range':
        timerange,
        'schedules':
        schedules,
        'course_ids':
        list(set(c.id for c in selected_courses.keys())),
        'section_ids':
        list(
            set(s.id for sections in selected_courses.values()
                for s in sections)),
        'days_of_the_week':
        list(DAYS),
        'id':
        selection.id,
    }

    selection.api_cache = json.dumps(context)
    selection.save()

    return {'context': context}
Example #4
0
    def full_select(self, year=None, month=None, amount=None):
        """Returns all courses in the given queryset, plus Sections, Periods, and SectionPeriod data.

        Optionally can have all related data to be filtered by semester year and month.

        Since this operation performs multiple selects and merges the resulting queries, the queryset
        is actively evaluated.
        """
        from courses.models import SectionPeriod
        sps = SectionPeriod.objects.by_courses(self, year,
                                               month).select_related(
                                                   'period', 'section',
                                                   'section__course__id')

        # TODO: optimize into one loop
        sid2sps = dict_by_attr(sps, 'section_id')
        sid2periods = dict_by_attr(sps, 'section_id', 'period')
        cid2sections = dict_by_attr([sp.section for sp in sps], 'course.id')
        cid2sps = dict_by_attr(sps, 'section.course.id')

        for sp in sps:
            set_prefetch_cache(sp.section, 'section_times',
                               sid2sps.get(sp.section.id, []))
            set_prefetch_cache(sp.section, 'periods',
                               sid2periods.get(sp.section.id, []))

        def section_key(section):
            return section.number

        result = []
        courses = self
        if amount is not None:
            courses[:amount]
        for course in courses:
            sections = sorted(set(cid2sections.get(course.id, [])),
                              key=section_key)
            for section in sections:
                section.course = course
            set_prefetch_cache(course, 'sections', sections)
            result.append(course)
        return result
Example #5
0
File: views.py Project: jinz/YACS
def schedules(request, slug=None, version=None):
    selection = None
    if slug:
        selection = Selection.objects.get(slug=slug)
        section_ids = selection.section_ids
    else:
        section_ids = int_list(request.GET.getlist('section_id'))

    created = False
    if not selection:
        selection, created = Selection.objects.get_or_create(
            section_ids=section_ids)

    sections = SectionProxy.objects.filter(id__in=section_ids) \
        .select_related('course').prefetch_periods()
    selected_courses = dict_by_attr(sections, 'course')
    conflict_cache = ConflictCache(
        SectionConflict.objects.as_dictionary([s.id for s in sections]))

    # if check flag given, return only if we have a schedule or not.
    if request.GET.get('check'):
        return {'context': has_schedule(selected_courses, conflict_cache)}

    # check the cache
    if not created and selection.api_cache:
        print selection.api_cache
        return {'context': json.loads(selection.api_cache)}

    schedules = compute_schedules(selected_courses, conflict_cache)
    print schedules

    periods = set(p for s in sections for p in s.get_periods())
    timerange, dow_used = period_stats(periods)

    # note: if you change this, caches will have to be updated somehow
    context = {
        'time_range': timerange,
        'schedules': schedules,
        'course_ids': list(set(
            c.id for c in selected_courses.keys())),
        'section_ids': list(set(
            s.id
                for sections in selected_courses.values()
                for s in sections
        )),
        'days_of_the_week': list(DAYS),
        'id': selection.slug
    }

    selection.api_cache = json.dumps(context)
    selection.save()

    return {'context': context}
Example #6
0
    def full_select(self, year=None, month=None, amount=None):
        """Returns all courses in the given queryset, plus Sections, Periods, and SectionPeriod data.

        Optionally can have all related data to be filtered by semester year and month.

        Since this operation performs multiple selects and merges the resulting queries, the queryset
        is actively evaluated.
        """
        from courses.models import SectionPeriod

        sps = SectionPeriod.objects.by_courses(self, year, month).select_related(
            "period", "section", "section__course__id"
        )

        # TODO: optimize into one loop
        sid2sps = dict_by_attr(sps, "section_id")
        sid2periods = dict_by_attr(sps, "section_id", "period")
        cid2sections = dict_by_attr([sp.section for sp in sps], "course.id")
        cid2sps = dict_by_attr(sps, "section.course.id")

        for sp in sps:
            set_prefetch_cache(sp.section, "section_times", sid2sps.get(sp.section.id, []))
            set_prefetch_cache(sp.section, "periods", sid2periods.get(sp.section.id, []))

        def section_key(section):
            return section.number

        result = []
        courses = self
        if amount is not None:
            courses[:amount]
        for course in courses:
            sections = sorted(set(cid2sections.get(course.id, [])), key=section_key)
            for section in sections:
                section.course = course
            set_prefetch_cache(course, "sections", sections)
            result.append(course)
        return result
Example #7
0
 def test_mapping(self):
     items = [self.SampleObject(i, i + 1, i + 2) for i in range(10)]
     ordered = utils.dict_by_attr(items, 'a')
     self.assertEqual([0, 1, 2, 3, 4, 5, 6, 7, 8, 9], ordered.keys())
     self.assertEqual([(0, 1, 2)], ordered[0])
     self.assertEqual([(1, 2, 3)], ordered[1])
     self.assertEqual([(2, 3, 4)], ordered[2])
     self.assertEqual([(3, 4, 5)], ordered[3])
     self.assertEqual([(4, 5, 6)], ordered[4])
     self.assertEqual([(5, 6, 7)], ordered[5])
     self.assertEqual([(6, 7, 8)], ordered[6])
     self.assertEqual([(7, 8, 9)], ordered[7])
     self.assertEqual([(8, 9, 10)], ordered[8])
     self.assertEqual([(9, 10, 11)], ordered[9])
Example #8
0
 def test_mapping_with_value(self):
     items = [self.SampleObject(i, i + 1, i + 2) for i in range(10)]
     ordered = utils.dict_by_attr(items, 'a', 'b')
     self.assertEqual([0, 1, 2, 3, 4, 5, 6, 7, 8, 9], ordered.keys())
     self.assertEqual([1], ordered[0])
     self.assertEqual([2], ordered[1])
     self.assertEqual([3], ordered[2])
     self.assertEqual([4], ordered[3])
     self.assertEqual([5], ordered[4])
     self.assertEqual([6], ordered[5])
     self.assertEqual([7], ordered[6])
     self.assertEqual([8], ordered[7])
     self.assertEqual([9], ordered[8])
     self.assertEqual([10], ordered[9])
Example #9
0
 def test_mapping(self):
     items = [self.SampleObject(i, i + 1, i + 2) for i in range(10)]
     ordered = utils.dict_by_attr(items, 'a')
     self.assertEqual([0, 1, 2, 3, 4, 5, 6, 7, 8, 9], ordered.keys())
     self.assertEqual([(0, 1, 2)], ordered[0])
     self.assertEqual([(1, 2, 3)], ordered[1])
     self.assertEqual([(2, 3, 4)], ordered[2])
     self.assertEqual([(3, 4, 5)], ordered[3])
     self.assertEqual([(4, 5, 6)], ordered[4])
     self.assertEqual([(5, 6, 7)], ordered[5])
     self.assertEqual([(6, 7, 8)], ordered[6])
     self.assertEqual([(7, 8, 9)], ordered[7])
     self.assertEqual([(8, 9, 10)], ordered[8])
     self.assertEqual([(9, 10, 11)], ordered[9])
Example #10
0
 def test_mapping_with_value(self):
     items = [self.SampleObject(i, i + 1, i + 2) for i in range(10)]
     ordered = utils.dict_by_attr(items, 'a', 'b')
     self.assertEqual([0, 1, 2, 3, 4, 5, 6, 7, 8, 9], ordered.keys())
     self.assertEqual([1], ordered[0])
     self.assertEqual([2], ordered[1])
     self.assertEqual([3], ordered[2])
     self.assertEqual([4], ordered[3])
     self.assertEqual([5], ordered[4])
     self.assertEqual([6], ordered[5])
     self.assertEqual([7], ordered[6])
     self.assertEqual([8], ordered[7])
     self.assertEqual([9], ordered[8])
     self.assertEqual([10], ordered[9])
Example #11
0
 def test_mapping_in_groups(self):
     items = [self.SampleObject(i % 3, i + 1, i + 2) for i in range(10)]
     ordered = utils.dict_by_attr(items, 'a')
     self.assertEqual([0, 1, 2], ordered.keys())
     self.assertEqual([(0, 1, 2), (0, 4, 5), (0, 7, 8), (0, 10, 11)],
                      ordered[0])
     self.assertEqual([
         (1, 2, 3),
         (1, 5, 6),
         (1, 8, 9),
     ], ordered[1])
     self.assertEqual([
         (2, 3, 4),
         (2, 6, 7),
         (2, 9, 10),
     ], ordered[2])
Example #12
0
def schedules(request, id=None, version=None):
    selection = None
    if id:
        selection = Selection.objects.get(id=id)
        section_ids = selection.section_ids
    else:
        section_ids = int_list(request.GET.getlist("section_id"))

    created = False
    if not selection:
        selection, created = Selection.objects.get_or_create(section_ids=section_ids)

    sections = SectionProxy.objects.filter(id__in=section_ids).select_related("course").prefetch_periods()
    selected_courses = dict_by_attr(sections, "course")
    conflict_cache = ConflictCache(SectionConflict.objects.as_dictionary([s.id for s in sections]))

    # if check flag given, return only if we have a schedule or not.
    if request.GET.get("check"):
        return {"context": has_schedule(selected_courses, conflict_cache)}

    # check the cache
    if not created and selection.api_cache:
        return {"context": json.loads(selection.api_cache)}

    schedules = compute_schedules(selected_courses, conflict_cache)

    periods = set(p for s in sections for p in s.get_periods())
    timerange, dow_used = period_stats(periods)

    # note: if you change this, caches will have to be updated somehow
    context = {
        "time_range": timerange,
        "schedules": schedules,
        "course_ids": list(set(c.id for c in selected_courses.keys())),
        "section_ids": list(set(s.id for sections in selected_courses.values() for s in sections)),
        "days_of_the_week": list(DAYS),
        "id": selection.id,
    }

    selection.api_cache = json.dumps(context)
    selection.save()

    return {"context": context}
Example #13
0
 def reformat_to_selected_courses(self, sections):
     "Returns a dictionary of a course mapped to its sections objects."
     return dict_by_attr(sections, 'course')
Example #14
0
File: views.py Project: jinz/YACS
 def reformat_to_selected_courses(self, sections):
     "Returns a dictionary of a course mapped to its sections objects."
     return dict_by_attr(sections, 'course')
Example #15
0
def cache_conflicts(semester_year=None, semester_month=None, semester=None, sql=True, stdout=False):
    assert (
        semester_year and semester_month
    ) or semester, "Semester year & month must be provided or the semester object."
    import sys

    # trash existing conflict data...
    if not semester:
        semester = courses.Semester.objects.get(year=semester_year, month=semester_month)

    with transaction.atomic():
        # we don't want to increment IDs too quickly (ev 25 minutes)
        Syncer = Synchronizer(SectionConflict, SectionConflict.objects.values_list("id", flat=True))

        sections = courses.Section.objects.select_related("course", "semester").by_semester(semester).prefetch_periods()
        section_courses = dict_by_attr(sections, "course")

        mapping = {}
        for id, sid1, sid2 in SectionConflict.objects.filter(semester=semester).values_list(
            "id", "section1", "section2"
        ):
            mapping[(sid1, sid2)] = id

        conflicts = []

        def log(msg):
            sys.stdout.write(msg)
            sys.stdout.flush()

        def perform_insert(conflicts):
            SectionConflict.objects.bulk_create(conflicts)

        count = 0
        for course1, course2 in itertools.combinations(section_courses.keys(), 2):
            for section1, section2 in itertools.product(section_courses[course1], section_courses[course2]):
                if section1.conflicts_with(section2):
                    if section1.id > section2.id:
                        section1, section2 = section2, section1

                    count += 1
                    if sql:
                        if count % 500 == 0:
                            perform_insert(conflicts)
                            conflicts = []
                            log(".")
                        if (section1.id, section2.id) not in mapping:
                            log("C")
                            conflicts.append(SectionConflict(section1=section1, section2=section2, semester=semester))
                        else:
                            Syncer.exclude_id(mapping[(section1.id, section2.id)])
                    else:
                        log("C")
                        Syncer.get_or_create(section1=section1, section2=section2, semester=semester)

        if sql and conflicts:
            log("C")
            perform_insert(conflicts)

        log("\n")
        Syncer.trim(semester=semester)
        log("\n")
Example #16
0
def cache_conflicts(semester_year=None,
                    semester_month=None,
                    semester=None,
                    sql=True,
                    stdout=False):
    assert (
        semester_year and semester_month
    ) or semester, "Semester year & month must be provided or the semester object."
    import sys
    # trash existing conflict data...
    if not semester:
        semester = courses.Semester.objects.get(year=semester_year,
                                                month=semester_month)

    with transaction.atomic():
        # we don't want to increment IDs too quickly (ev 25 minutes)
        Syncer = Synchronizer(
            SectionConflict,
            SectionConflict.objects.values_list('id', flat=True))

        sections = courses.Section.objects.select_related('course', 'semester') \
            .by_semester(semester).prefetch_periods()
        section_courses = dict_by_attr(sections, 'course')

        mapping = {}
        for id, sid1, sid2 in SectionConflict.objects.filter(
                semester=semester).values_list('id', 'section1', 'section2'):
            mapping[(sid1, sid2)] = id

        conflicts = []

        def log(msg):
            sys.stdout.write(msg)
            sys.stdout.flush()

        def perform_insert(conflicts):
            SectionConflict.objects.bulk_create(conflicts)

        count = 0
        for course1, course2 in itertools.combinations(section_courses.keys(),
                                                       2):
            for section1, section2 in itertools.product(
                    section_courses[course1], section_courses[course2]):
                if section1.conflicts_with(section2):
                    if section1.id > section2.id:
                        section1, section2 = section2, section1

                    count += 1
                    if sql:
                        if count % 500 == 0:
                            perform_insert(conflicts)
                            conflicts = []
                            log('.')
                        if (section1.id, section2.id) not in mapping:
                            log('C')
                            conflicts.append(
                                SectionConflict(section1=section1,
                                                section2=section2,
                                                semester=semester))
                        else:
                            Syncer.exclude_id(mapping[(section1.id,
                                                       section2.id)])
                    else:
                        log('C')
                        Syncer.get_or_create(
                            section1=section1,
                            section2=section2,
                            semester=semester,
                        )

        if sql and conflicts:
            log('C')
            perform_insert(conflicts)

        log('\n')
        Syncer.trim(semester=semester)
        log('\n')
Example #17
0
def selections(request, id, version=None):
    selection = Selection.objects.get(id=id)
    sections = models.Section.objects.filter(id__in=selection.section_ids)
    data = dict_by_attr(sections, "course_id", "id")
    return {"context": {"id": selection.id, "data": data}}