예제 #1
0
def benchmark_calculate_course_category_aggregate(student, course, category, marking_period, items=None):
    if items is None:
        items = Item.objects.all()
        save = True
    else:
        # don't store aggregates for every one-off combination of items
        save = False
    items = items.filter(course=course, category=category)
    # if we're passed marking_period=None, we should consider items across the entire duration of the course
    # if we're passed a specific marking period instead, we should consider items matching only that marking period
    if marking_period is not None:
        items = items.filter(marking_period=marking_period)

    calculation_rule = benchmark_find_calculation_rule(course.marking_period.all()[0].school_year)

    # initialize attributes
    criteria = {"course": course, "category": category, "marking_period": marking_period}
    # silly name is silly, and should not be part of the criteria
    silly_name = "G! {} - {} ({}, {})".format(student, category, course, marking_period)
    # don't use get_or_create; otherwise we may end up saving an empty object
    try:
        agg = benchmark_get_or_flush(student.aggregate_set, **criteria)
        created = False
    except Aggregate.DoesNotExist:
        agg = Aggregate(student=student, **criteria)
        created = True
    agg.name = silly_name

    # begin the actual calculations!
    agg.cached_substitution = None
    category_numer = category_denom = Decimal(0)
    if category.allow_multiple_demonstrations:
        for category_item in items.exclude(points_possible=None):
            # Find the highest mark amongst demonstrations and count it as the grade for the item
            best = Mark.objects.filter(student=student, item=category_item).aggregate(Max("mark"))["mark__max"]
            if best is not None:
                calculate_as, display_as = calculation_rule.substitute(category_item, best)
                category_numer += calculate_as
                category_denom += category_item.points_possible
                # yes, agg will just end up with the last substitution, but tough
                if display_as is not None:
                    agg.cached_substitution = display_as

    else:
        for category_mark in (
            Mark.objects.filter(student=student, item__in=items).exclude(mark=None).exclude(item__points_possible=None)
        ):
            calculate_as, display_as = calculation_rule.substitute(category_mark.item, category_mark.mark)
            category_numer += calculate_as
            category_denom += category_mark.item.points_possible
            if display_as is not None:
                agg.cached_substitution = display_as
    if category_denom:
        agg.cached_value = category_numer / category_denom * agg._fallback_points_possible()
    else:
        agg.cached_value = None
    if save:
        agg.save()
    return agg, created
예제 #2
0
def benchmark_calculate_course_category_aggregate(student,
                                                  course_section,
                                                  category,
                                                  marking_period,
                                                  items=None):
    if items is None:
        items = Item.objects.all()
        save = True
    else:
        # don't store aggregates for every one-off combination of items
        save = False
    items = items.filter(course_section=course_section, category=category)
    # if we're passed marking_period=None, we should consider items across the entire duration of the course section
    # if we're passed a specific marking period instead, we should consider items matching only that marking period
    if marking_period is not None:
        items = items.filter(marking_period=marking_period)

    calculation_rule = benchmark_find_calculation_rule(
        course_section.marking_period.all()[0].school_year)

    # initialize attributes
    criteria = {
        'course_section': course_section,
        'category': category,
        'marking_period': marking_period
    }
    # silly name is silly, and should not be part of the criteria
    silly_name = 'G! {} - {} ({}, {})'.format(student, category,
                                              course_section, marking_period)
    # don't use get_or_create; otherwise we may end up saving an empty object
    try:
        agg = benchmark_get_or_flush(student.aggregate_set, **criteria)
        created = False
    except Aggregate.DoesNotExist:
        agg = Aggregate(student=student, **criteria)
        created = True
    agg.name = silly_name

    # begin the actual calculations!
    agg.cached_substitution = None
    category_numer = category_denom = Decimal(0)
    if category.allow_multiple_demonstrations:
        for category_item in items.exclude(points_possible=None):
            # Find the highest mark amongst demonstrations and count it as the grade for the item
            best = Mark.objects.filter(student=student,
                                       item=category_item).aggregate(
                                           Max('mark'))['mark__max']
            if best is not None:
                calculate_as, display_as = calculation_rule.substitute(
                    category_item, best)
                category_numer += calculate_as
                category_denom += category_item.points_possible
                # yes, agg will just end up with the last substitution, but tough
                if display_as is not None:
                    agg.cached_substitution = display_as

    else:
        for category_mark in Mark.objects.filter(
                student=student, item__in=items).exclude(mark=None).exclude(
                    item__points_possible=None):
            calculate_as, display_as = calculation_rule.substitute(
                category_mark.item, category_mark.mark)
            category_numer += calculate_as
            category_denom += category_mark.item.points_possible
            if display_as is not None:
                agg.cached_substitution = display_as
    if category_denom:
        agg.cached_value = category_numer / category_denom * agg._fallback_points_possible(
        )
    else:
        agg.cached_value = None
    if save:
        agg.save()
    return agg, created