コード例 #1
0
def get_variable_stats(request, variable_name):
    """Returns the most recent values of a variable.

    Parameters:
        variable_name   -   The variable for which to lookup the values.
    """
    # Ensure the request uses the GET method.
    if not request.method == "GET":
        return HttpResponseNotAllowed(['GET'])
    variable = get_object_or_404(Variable, name=variable_name)

    # Retrieve current group context
    try:
       student = Student.objects.get(
            identification=request.session.get("authenticated_user"))
    except Student.DoesNotExist:
        return JsonResponse([], safe=False)

    groups = CourseGroup.get_groups_by_date(date.today(),
            course__url=request.session.get('authenticated_course'),
            members=student)
    if len(groups):
        group = groups[0]
    else:
        return HttpResponseBadRequest("User does not belong to a course group")

    from datetime import timedelta

    # Calculate course-relative time context
    course_datetime_now = group.calculate_course_datetime(timezone.now())
    # Collect relevant value history
    value_history = ValueHistory.objects.filter(variable=variable, group=group,
            course_datetime__lte=course_datetime_now)
    if len(value_history) == 0:
        return JsonResponse([], safe=False)

    # Calculate variable statistics
    statistics = variable.calculate_statistics_from_values(value_history)

    # Placeholder for the viewer's statement, as well as the bin it falls in.
    student_statistic = None
    student_bin = 0

    # Init reference to store the maximum and minimum value found in the
    #  extracted values. These will determine if all statistic values fit
    #  within the existing value bins for this variable.
    max_value = float('-Inf')
    min_value = float('Inf')
    for statistic in statistics:
        if statistic['student'] == student.identification:
            student_statistic = statistic

        # Update the max and min value found if needed.
        value = statistic['value']
        max_value = value if max_value < value else max_value
        min_value = value if min_value > value else min_value

    # Calculate bins
    bin_size = (max_value-min_value)/float(variable.num_bins)
    bin_fn = lambda x: round(min_value + x * bin_size, 2)
    lower_points = map(bin_fn, range(variable.num_bins))
    upper_points = map(bin_fn, range(1, variable.num_bins+1))

    bin_stats = []
    for index in range(variable.num_bins):
        if index == 0:
            assignment_fn = (lambda s: s['value'] <= upper_points[index] and
                    s['value'] >= lower_points[index])
        else:
            assignment_fn = (lambda s: s['value'] <= upper_points[index] and
                    s['value'] > lower_points[index])

        # Check if we found the viewer's bin
        if student_statistic is not None and assignment_fn(student_statistic):
            student_bin = index

        predictions = {}
        for output_variable in Variable.objects.exclude(type='IN').exclude(
                pk=variable.pk).filter(course=group.course).order_by('order'):
            comparing_groups = CourseGroup.objects.filter(
                    valuehistory__variable=output_variable).distinct()
            comparing_students = get_students_by_variable_values(
                    variable, lower_points[index], upper_points[index], index,
                    group__in=comparing_groups)
            predictions[output_variable.name] = get_gauss_params(
                    output_variable, student__in=comparing_students)
            predictions[output_variable.name]['chart'] = output_variable.output_chart
            predictions[output_variable.name]['label'] = output_variable.label
            predictions[output_variable.name]["axis"] = (
                    output_variable.axis_label or output_variable.label)

        bin_stats.append({
            'id': index,
            'lower': lower_points[index],
            'upper': upper_points[index],
            'count': len(filter(assignment_fn, statistics)),
            'predictions': predictions
        });

    return JsonResponse({
            "student_bin": student_bin,
            "bins": bin_stats,
            "label": variable.label,
            "axis": variable.axis_label or variable.label
        },safe=False)
コード例 #2
0
    def update_from_storage(self):
        """Updates the appropriate stats models based on storage date.

        Based on new storage.models.Activity instances new observed values for
        this variable are calculated. These values are added as ValueHistory
        instances.

        The calculation of variable values based on storage data is delegated
        to the `calculate_values_from_activities` function of subclasses. This
        calculation function returns the extracted values as well as the latest
        Activity instance that was used in the calculation. The storage data
        provided is any Activity instance that has been stored after the latest
        consumed Activity instances for this variable.
        """
        # Retrieve new activity instances for this variable.
        from storage.models import Activity
        ignored_objects = IgnoredObject.objects.all().values_list(
                'object_id', flat=True)
        activities = Activity.objects.exclude(
                activity__in=ignored_objects).filter(
                        course=self.course.url,
                        pk__gt=self.last_consumed_activity_pk)
        # Return new ValueHistory instances and the last consumed Activity
        # instance based on the new activities.
        value_history, last_consumed = self.calculate_values_from_activities(
            activities)
        # If no activity was consumed, stop.
        if last_consumed is None:
            return

        annotated_value_history = []
        for value_history_item in value_history:
            # Determine the attached course groups. Technically someone could
            #  be in multiple groups in one course.
            groups = CourseGroup.get_groups_by_date(
                value_history_item.datetime.date(),
                course=self.course)

            if len(groups) == 0:
                continue
            group = groups[0]

            # Determine the attached student
            student_id = value_history_item.student
            student, _created = Student.objects.get_or_create(
                identification=student_id, defaults={"label": student_id})

            group.members.add(student)
            value_history_item.group = group
            # Set course timestamp relative to start
            value_history_item.course_datetime = (
                value_history_item.datetime -
                timezone.make_aware(
                    datetime.combine(group.start_date,
                        datetime.min.time())))
            annotated_value_history.append(value_history_item)

        # Update the database by adding the new ValueHistory instances
        ValueHistory.objects.bulk_create(annotated_value_history)

        # Set the last consumed activity
        self.last_consumed_activity_pk = last_consumed.pk
        self.save()