def get_scaled_average(self, rounding=2, boost=True): """ Convert to scaled grade first, then average Burke Software does not endorse this as a precise way to calculate averages """ grade_total = 0.0 total_credits = 0.0 grades = self.student.grade_set.filter( marking_period=self.marking_period, grade__isnull=False, course_section__course__course_type__weight__gt=0, enrollment__is_active=True, ) for grade in grades: grade_value = float(grade.optimized_grade_to_scale(letter=False)) if grade_value > 0 and boost: # only add boost for non-failing grades grade_value += float(grade.course_section.course.course_type.boost) num_credits = float(grade.course_section.course.credits) grade_total += grade_value * num_credits total_credits += num_credits if total_credits > 0: average = grade_total / total_credits return round_as_decimal(average, rounding) else: return None
def get_scaled_multiple_mp_average(student, marking_periods, rounding=2): if (type(marking_periods) is list and marking_periods and type(marking_periods[0]) is ecwsp.schedule.models.MarkingPeriod): marking_periods = [ mp.id for mp in marking_periods ] enrollments = ecwsp.schedule.models.CourseEnrollment.objects.filter( user=student, course_section__course__course_type__weight__gt=0, course_section__marking_period__in=marking_periods) total_credits = 0.0 num_courses = 0 total_grade = 0.0 for enrollment in enrollments.distinct(): grade = enrollment.get_average_for_marking_periods(marking_periods, numeric=True) if grade != None: grade = float(grade) num_credits = float(enrollment.course_section.course.credits) if grade > 0: # only add boost for non-failing grades grade += float(enrollment.course_section.course.course_type.boost) total_grade += grade * num_credits total_credits += num_credits num_courses += 1 if num_courses > 0: average = total_grade / total_credits return round_as_decimal(average, rounding) else: return None
def calculate_gpa(self, date_report=None, rounding=2): """ Use StudentYearGrade calculation No further weighting needed. """ total = Decimal(0) years_with_grade = 0 grade_years = self.studentyeargrade_set.filter( year__markingperiod__show_reports=True) if date_report: grade_years = grade_years.filter(year__start_date__lt=date_report) for grade_year in grade_years.distinct(): grade = grade_year.calculate_grade(date_report=date_report) if grade: # Is this an incomplete complete year? if date_report and date_report < grade_year.year.end_date: # This year hasn't finished. What fraction is complete? all_mps = grade_year.year.markingperiod_set.count() complete_mps = grade_year.year.markingperiod_set.filter( end_date__lte=date_report).count() fraction = Decimal(complete_mps) / all_mps total += grade * grade_year.credits * fraction years_with_grade += grade_year.credits * fraction else: total += grade * grade_year.credits years_with_grade += grade_year.credits if years_with_grade: gpa = total / years_with_grade return round_as_decimal(gpa, decimal_places=rounding)
def calculate_gpa(self, date_report=None, rounding=2): """ Use StudentYearGrade calculation No further weighting needed. """ total = Decimal(0) years_with_grade = 0 grade_years = self.studentyeargrade_set.filter(year__markingperiod__show_reports=True) if date_report: grade_years = grade_years.filter(year__start_date__lt=date_report) for grade_year in grade_years.distinct(): grade = grade_year.calculate_grade(date_report=date_report) if grade: # Is this an incomplete complete year? if date_report and date_report < grade_year.year.end_date: # This year hasn't finished. What fraction is complete? all_mps = grade_year.year.markingperiod_set.count() complete_mps = grade_year.year.markingperiod_set.filter( end_date__lte=date_report).count() fraction = Decimal(complete_mps) / all_mps total += grade * grade_year.credits * fraction years_with_grade += grade_year.credits * fraction else: total += grade * grade_year.credits years_with_grade += grade_year.credits if years_with_grade: gpa = total / years_with_grade return round_as_decimal(gpa, decimal_places=rounding)
def get_grade(self, date_report=None, rounding=2, numeric_scale=False, prescale=False, boost=True): if numeric_scale == False and (date_report is None or date_report >= datetime.date.today()): # Cache will always have the latest grade, so it's fine for # today's date and any future date return self.grade grade = self.calculate_grade(date_report=date_report, prescale=prescale) if numeric_scale == True: grade_scale = self.year.grade_scale if grade_scale and not prescale: grade = grade_scale.to_numeric(grade) if boost: enrollments = self.student.courseenrollment_set.filter( course_section__marking_period__show_reports=True, course_section__marking_period__school_year=self.year, course_section__course__credits__isnull=False, course_section__course__course_type__weight__gt=0, ) if not grade_scale: boost_sum = enrollments.aggregate(boost_sum=Sum( 'course_section__course__course_type__boost') )['boost_sum'] if not boost_sum: boost_sum = 0.0 try: boost_factor = boost_sum / enrollments.count() except ZeroDivisionError: boost_factor = 0.0 else: boost_sum = 0.0 total_credits = 0.0 for enrollment in enrollments: course_credits = enrollment.course_section.course.credits course_boost = enrollment.course_section.course.course_type.boost if enrollment.numeric_grade: course_grade = Decimal(enrollment.numeric_grade) total_credits += float(course_credits) if grade_scale.to_numeric(course_grade) > 0: # only add boost to grades that are not failing... boost_sum += float(course_boost * course_credits) try: boost_factor = boost_sum / total_credits except ZeroDivisionError: boost_factor = None if enrollments.count() > 0 and boost_factor and grade: grade = float(grade) + float(boost_factor) if rounding: grade = round_as_decimal(grade, rounding) return grade
def get_grade(self, date_report=None, rounding=2): if date_report is None or date_report >= datetime.date.today(): # Cache will always have the latest grade, so it's fine for # today's date and any future date return self.grade grade = self.calculate_grade(date_report=date_report) if rounding: grade = round_as_decimal(grade, rounding) return grade
def get_grade(self, date_report=None, rounding=2): """ Get the grade, use cache when no date change present """ if date_report is None or date_report >= datetime.date.today(): # Cache will always have the latest grade, so it's fine for # today's date and any future date grade = self.grade else: grade = self.calculate_grade_real(date_report=date_report) if rounding and isinstance(grade, (int, long, float, complex, Decimal)): return round_as_decimal(grade, rounding) return grade
def get_grade(self, date_report=None, rounding=2, numeric_scale=False, prescale=False, boost=True): if numeric_scale == False and (date_report is None or date_report >= datetime.date.today()): # Cache will always have the latest grade, so it's fine for # today's date and any future date return self.grade grade = self.calculate_grade(date_report=date_report, prescale=prescale) if numeric_scale == True: grade_scale = self.year.grade_scale if grade_scale and not prescale: grade = grade_scale.to_numeric(grade) if boost: enrollments = self.student.courseenrollment_set.filter( course_section__marking_period__show_reports=True, course_section__marking_period__school_year=self.year, course_section__course__credits__isnull=False, course_section__course__course_type__weight__gt=0,) if not grade_scale: boost_sum = enrollments.aggregate(boost_sum=Sum('course_section__course__course_type__boost'))['boost_sum'] if not boost_sum: boost_sum = 0.0 try: boost_factor = boost_sum / enrollments.count() except ZeroDivisionError: boost_factor = 0.0 else: boost_sum = 0.0 total_credits = 0.0 for enrollment in enrollments: course_credits = enrollment.course_section.course.credits course_boost = enrollment.course_section.course.course_type.boost if enrollment.numeric_grade: course_grade = Decimal(enrollment.numeric_grade) total_credits += float(course_credits) if grade_scale.to_numeric(course_grade) > 0: # only add boost to grades that are not failing... boost_sum += float(course_boost*course_credits) try: boost_factor = boost_sum / total_credits except ZeroDivisionError: boost_factor = None if enrollments.count() > 0 and boost_factor and grade: grade = float(grade) + float(boost_factor) if rounding: grade = round_as_decimal(grade, rounding) return grade
def get_gpa(self, rounding=2, numeric_scale=False, boost=True): """ Get cached gpa but with rounding and scale options """ gpa = self.gpa if numeric_scale == True: # Get the scale for the last year the student was active in grade_scale = GradeScale.objects.filter( schoolyear__markingperiod__coursesection__courseenrollment__user=self).last() if grade_scale: gpa = grade_scale.to_numeric(gpa) enrollments = self.courseenrollment_set.filter( course_section__course__course_type__weight__gt=0) if boost: boost_sum = enrollments.aggregate(boost_sum=Sum('course_section__course__course_type__boost'))['boost_sum'] boost_factor = boost_sum / enrollments.count() gpa += boost_factor if rounding: gpa = round_as_decimal(gpa, rounding) return gpa
def get_grade(self, date_report=None, rounding=2, letter=False): """ Get the grade, use cache when no date change present date_report: rounding: Round to this many decimal places letter: Convert to letter grade scale """ if date_report is None or date_report >= datetime.date.today(): # Cache will always have the latest grade, so it's fine for # today's date and any future date if self.numeric_grade: grade = self.numeric_grade else: grade = self.grade else: grade = self.calculate_grade_real(date_report=date_report) if rounding and isinstance(grade, (int, long, float, complex, Decimal)): grade = round_as_decimal(grade, rounding) if letter == True and isinstance(grade, (int, long, float, complex, Decimal)): return self.optimized_grade_to_scale(grade) return grade
def get_average(self, rounding=2): """ Returns cached average """ return round_as_decimal(self.grade, rounding)