Example #1
0
    def retrieve(self, request, pk):
        """
        Get the difficult questions for a particular quiz.
        """
        group_id = request.GET.get("group_id", None)
        # Only return logs when the learner has submitted the Quiz OR
        # the coach has deactivated the Quiz. Do not return logs when Quiz is still
        # in-progress.
        queryset = ExamAttemptLog.objects.filter(
            Q(examlog__closed=True) | Q(examlog__exam__active=False),
            examlog__exam=pk)
        if group_id is not None:
            queryset = HierarchyRelationsFilter(queryset).filter_by_hierarchy(
                ancestor_collection=group_id, target_user=F("user"))
            collection_id = group_id
        else:
            collection_id = Exam.objects.get(pk=pk).collection_id
        data = queryset.values("item",
                               "content_id").annotate(correct=Sum("correct"))

        # Instead of inferring the totals from the number of logs, use the total
        # number of people who submitted (if quiz is active) or started the exam
        # (if quiz is inactive) as our guide, as people who started the exam
        # but did not attempt the question are still important.
        total = (HierarchyRelationsFilter(
            ExamLog.objects.filter(Q(closed=True) | Q(exam__active=False),
                                   exam_id=pk)).filter_by_hierarchy(
                                       ancestor_collection=collection_id,
                                       target_user=F("user")).count())
        for datum in data:
            datum["total"] = total
        return Response(data)
Example #2
0
    def retrieve(self, request, pk):
        """
        Get the difficult questions for a particular quiz.
        """
        group_id = request.GET.get("group_id", None)
        queryset = ExamAttemptLog.objects.filter(examlog__exam=pk)
        if group_id is not None:
            queryset = HierarchyRelationsFilter(queryset).filter_by_hierarchy(
                ancestor_collection=group_id, target_user=F("user")
            )
            collection_id = group_id
        else:
            collection_id = Exam.objects.get(pk=pk).collection_id
        data = queryset.values("item", "content_id").annotate(correct=Sum("correct"))

        # Instead of inferring the totals from the number of logs, use the total
        # number of people who took the exam as our guide, as people who started the exam
        # but did not attempt the question are still important.
        total = (
            HierarchyRelationsFilter(ExamLog.objects.filter(exam_id=pk))
            .filter_by_hierarchy(
                ancestor_collection=collection_id, target_user=F("user")
            )
            .count()
        )
        for datum in data:
            datum["total"] = total
        return Response(data)
Example #3
0
def get_or_create_classroom_users(**options):
    classroom = options["classroom"]
    n_users = options["n_users"]
    user_data = options["user_data"]
    facility = options["facility"]
    device_name = options.get("device_name", "")
    verbosity = options.get("verbosity", 1)

    # The headers in the user_data.csv file that we use to generate user Full Names
    # Note, we randomly pick from these to give deliberately varied (and sometimes idiosyncratic)
    # Full names - because we should never assume that users have names like us
    user_data_name_fields = ["GivenName", "MiddleInitial", "Surname"]

    n_in_classroom = (HierarchyRelationsFilter(
        FacilityUser.objects.all()).filter_by_hierarchy(
            ancestor_collection=classroom, target_user=F("id")).count())

    # Only generate new users if there are fewer users than requested.
    current_year = datetime.datetime.now().year
    n_to_create = n_users - n_in_classroom
    if n_to_create > 0:
        logger_info(
            "Generating {n} user object(s) for class: {classroom} in facility: {facility}"
            .format(n=n_to_create, classroom=classroom, facility=facility),
            verbosity=verbosity,
        )
        for i in range(0, n_to_create):
            # Get the first base data that does not have a matching user already
            base_data = user_data[n_in_classroom + i]
            # Randomly create the name from 1 to 3 of the three user name fields
            name = " ".join([
                base_data[key] for key in random.sample(
                    user_data_name_fields, random.randint(1, 3))
                if base_data[key]
            ])
            if device_name:
                # If specified, prepend the device name to the user.
                name = "{0} {1}".format(device_name, name)
            # calculate birth year
            birth_year = str(current_year - int(base_data["Age"]))
            # randomly assign gender
            gender = random.choice(demographics.choices)[0]
            user = FacilityUser.objects.create(
                facility=facility,
                full_name=name,
                username=base_data["Username"],
                gender=gender,
                birth_year=birth_year,
            )
            # Set a dummy password so that if we want to login as this learner later, we can.
            user.set_password("password")
            user.save()

            # Add the user to the current classroom
            classroom.add_member(user)

    return HierarchyRelationsFilter(
        FacilityUser.objects.all()).filter_by_hierarchy(
            target_user=F("id"), ancestor_collection=classroom)[0:n_users]
Example #4
0
    def retrieve(self, request, pk):
        """
        Get the difficult questions for a particular exercise.
        pk maps to the content_id of the exercise in question.
        """
        classroom_id = request.GET.get("classroom_id", None)
        group_id = request.GET.get("group_id", None)
        lesson_id = request.GET.get("lesson_id", None)
        queryset = AttemptLog.objects.filter(masterylog__summarylog__content_id=pk)
        if lesson_id is not None:
            collection_ids = Lesson.objects.get(
                id=lesson_id
            ).lesson_assignments.values_list("collection_id", flat=True)
            if group_id is not None:
                if (
                    group_id not in collection_ids
                    and classroom_id not in collection_ids
                ):
                    # In the special case that the group is not in the lesson assignments
                    # nor the containing classroom, just return an empty queryset.
                    queryset = AttemptLog.objects.none()
            else:
                # Only filter by all the collections in the lesson if we are not also
                # filtering by a specific group. Otherwise the group should be sufficient.
                base_queryset = queryset
                # Set starting queryset to null, then OR.
                queryset = AttemptLog.objects.none()
                for collection_id in collection_ids:
                    queryset |= HierarchyRelationsFilter(
                        base_queryset
                    ).filter_by_hierarchy(
                        ancestor_collection=collection_id, target_user=F("user")
                    )
                queryset = queryset.distinct()
        if group_id is not None:
            collection_id = group_id or classroom_id
            queryset = HierarchyRelationsFilter(queryset).filter_by_hierarchy(
                ancestor_collection=collection_id, target_user=F("user")
            )

        data = (
            queryset.values("item")
            .annotate(total=Count("correct"))
            .annotate(correct=Sum("correct"))
        )
        return Response(data)
Example #5
0
    def get_assignments(self, instance):
        """
        Returns all Exams and Lessons (and progress) assigned to the requesting User
        """
        current_user = self.context["request"].user

        # Return only active Lessons that are assigned to the requesting user's groups
        # TODO move this to a permission_class on Lesson
        lesson_assignments = HierarchyRelationsFilter(
            LessonAssignment.objects.all()
        ).filter_by_hierarchy(
            target_user=current_user, ancestor_collection=F("collection")
        )
        filtered_lessons = Lesson.objects.filter(
            lesson_assignments__in=lesson_assignments,
            is_active=True,
            collection=instance,
        ).distinct()

        exam_assignments = HierarchyRelationsFilter(
            ExamAssignment.objects.all()
        ).filter_by_hierarchy(
            target_user=current_user, ancestor_collection=F("collection")
        )

        filtered_exams = (
            Exam.objects.filter(assignments__in=exam_assignments, collection=instance)
            .filter(Q(active=True) | Q(examlogs__user=current_user))
            .distinct()
        )

        return {
            "lessons": LessonProgressSerializer(
                filtered_lessons, many=True, context={"user": current_user}
            ).data,
            "exams": ExamProgressSerializer(
                filtered_exams, many=True, context={"user": current_user}
            ).data,
        }
Example #6
0
 def filter_learner_group(self, queryset, name, value):
     return HierarchyRelationsFilter(queryset).filter_by_hierarchy(
         ancestor_collection=value, target_user=F("user"))
Example #7
0
 def filter_collection(self, queryset, name, collection):
     return HierarchyRelationsFilter(queryset).filter_by_hierarchy(
         target_user=F("user"), ancestor_collection=collection)