Exemple #1
0
    def __init__(self, request, course_identifier, flow_identifier,
            flow_session=None):
        CoursePageContext.__init__(self, request, course_identifier)

        self.flow_session = flow_session
        self.flow_identifier = flow_identifier

        from course.content import get_flow_commit_sha
        from django.core.exceptions import ObjectDoesNotExist

        # Fetch 'current' version of the flow to compute permissions
        # and versioning rules.
        # Fall back to 'old' version if current git version does not
        # contain this flow any more.

        try:
            current_flow_desc_sha = self.course_commit_sha
            current_flow_desc = get_flow_desc(self.repo, self.course,
                    flow_identifier, current_flow_desc_sha)
        except ObjectDoesNotExist:
            if self.flow_session is None:
                raise http.Http404()

            current_flow_desc_sha = self.flow_session.active_git_commit_sha.encode()
            current_flow_desc = get_flow_desc(self.repo, self.course,
                    flow_identifier, current_flow_desc_sha)

        self.flow_commit_sha = get_flow_commit_sha(
                self.course, self.participation,
                current_flow_desc, self.flow_session)
        if self.flow_commit_sha == current_flow_desc_sha:
            self.flow_desc = current_flow_desc
        else:
            self.flow_desc = get_flow_desc(self.repo, self.course,
                flow_identifier, self.flow_commit_sha)

        # {{{ figure out permissions

        from course.views import get_now_or_fake_time
        self.permissions, self.stipulations = get_flow_permissions(
                self.course, self.participation, self.role,
                flow_identifier, current_flow_desc,
                get_now_or_fake_time(request))
Exemple #2
0
    def __init__(self, repo, course, flow_identifier,
            participation=None, flow_session=None):
        """*participation* and *flow_session* are not stored and only used
        to figure out versioning of the flow content.
        """

        self.repo = repo
        self.course = course
        self.flow_identifier = flow_identifier

        from course.content import get_flow_commit_sha
        from django.core.exceptions import ObjectDoesNotExist

        # Fetch 'current' version of the flow to compute permissions
        # and versioning rules.
        # Fall back to 'old' version if current git version does not
        # contain this flow any more.

        self.course_commit_sha = get_course_commit_sha(
                self.course, participation)

        try:
            current_flow_desc_sha = self.course_commit_sha
            self.current_flow_desc = get_flow_desc(self.repo, self.course,
                    flow_identifier, current_flow_desc_sha)
        except ObjectDoesNotExist:
            if flow_session is None:
                raise http.Http404()

            current_flow_desc_sha = flow_session.active_git_commit_sha.encode()
            self.current_flow_desc = get_flow_desc(self.repo, self.course,
                    flow_identifier, current_flow_desc_sha)

        self.flow_commit_sha = get_flow_commit_sha(
                self.course, participation,
                self.current_flow_desc, flow_session)

        if self.flow_commit_sha == current_flow_desc_sha:
            self.flow_desc = self.current_flow_desc
        else:
            self.flow_desc = get_flow_desc(self.repo, self.course,
                flow_identifier, self.flow_commit_sha)
Exemple #3
0
def grade_page_visit(visit, visit_grade_model=FlowPageVisitGrade,
        grade_data=None, graded_at_git_commit_sha=None):
    if not visit.is_graded_answer:
        raise RuntimeError("cannot grade ungraded answer")

    flow_session = visit.flow_session
    course = flow_session.course
    page_data = visit.page_data

    from course.content import (
            get_course_repo,
            get_course_commit_sha,
            get_flow_commit_sha,
            get_flow_desc,
            get_flow_page_desc,
            instantiate_flow_page)

    repo = get_course_repo(course)

    course_commit_sha = get_course_commit_sha(
            course, flow_session.participation)

    flow_desc_pre = get_flow_desc(repo, course,
            flow_session.flow_id, course_commit_sha)

    flow_commit_sha = get_flow_commit_sha(
            course, flow_session.participation, flow_desc_pre,
            visit.flow_session)

    flow_desc = get_flow_desc(repo, course,
            flow_session.flow_id, flow_commit_sha)

    page_desc = get_flow_page_desc(
            flow_session.flow_id,
            flow_desc,
            page_data.group_id, page_data.page_id)

    page = instantiate_flow_page(
            location="flow '%s', group, '%s', page '%s'"
            % (flow_session.flow_id, page_data.group_id, page_data.page_id),
            repo=repo, page_desc=page_desc,
            commit_sha=flow_commit_sha)

    from course.page import PageContext
    grading_page_context = PageContext(
            course=course,
            repo=repo,
            commit_sha=flow_commit_sha)

    answer_feedback = page.grade(
            grading_page_context, visit.page_data.data,
            visit.answer, grade_data=grade_data)

    grade = visit_grade_model()
    grade.visit = visit
    grade.grade_data = grade_data
    grade.max_points = page.max_points(visit.page_data)
    grade.graded_at_git_commit_sha = graded_at_git_commit_sha

    if answer_feedback is not None:
        grade.correctness = answer_feedback.correctness
        grade.feedback = answer_feedback.as_json()

    grade.save()
Exemple #4
0
def page_analytics(pctx, flow_identifier, group_id, page_id):
    if pctx.role not in [
            participation_role.teaching_assistant,
            participation_role.instructor,
            participation_role.observer,
            ]:
        raise PermissionDenied("must be at least TA to view analytics")

    flow_desc = get_flow_desc(pctx.repo, pctx.course, flow_identifier,
            pctx.course_commit_sha)

    is_multiple_submit = is_flow_multiple_submit(flow_desc)

    page_cache = PageInstanceCache(pctx.repo, pctx.course, flow_identifier)

    visits = (FlowPageVisit.objects
            .filter(
                flow_session__flow_id=flow_identifier,
                page_data__group_id=group_id,
                page_data__page_id=page_id,
                is_graded_answer=True,
                ))

    if is_multiple_submit and connection.features.can_distinct_on_fields:
        visits = (visits
                .distinct("page_data", "visit_time")
                .order_by("page_data", "-visit_time"))

    visits = (visits
            .prefetch_related("flow_session")
            .prefetch_related("page_data"))

    normalized_answer_and_correctness_to_count = {}

    title = None
    body = None
    total_count = 0

    for visit in visits:
        flow_commit_sha = get_flow_commit_sha(
                pctx.course, pctx.participation, flow_desc,
                visit.flow_session)
        page = page_cache.get_page(group_id, page_id, flow_commit_sha)

        from course.page import PageContext
        grading_page_context = PageContext(
                course=pctx.course,
                repo=pctx.repo,
                commit_sha=flow_commit_sha)

        title = page.title(grading_page_context, visit.page_data.data)
        body = page.body(grading_page_context, visit.page_data.data)

        answer_feedback = visit.get_most_recent_feedback()

        if answer_feedback is not None:
            key = (answer_feedback.normalized_answer,
                    answer_feedback.correctness)
            normalized_answer_and_correctness_to_count[key] = \
                    normalized_answer_and_correctness_to_count.get(key, 0) + 1

            total_count += 1

    answer_stats = []
    for (normalized_answer, correctness), count in \
            normalized_answer_and_correctness_to_count.iteritems():
        answer_stats.append(
                AnswerStats(
                    normalized_answer=normalized_answer,
                    correctness=correctness,
                    count=count,
                    percentage=safe_div(100 * count, total_count)))

    answer_stats = sorted(
            answer_stats,
            key=lambda astats: astats.percentage,
            reverse=True)

    return render_course_page(pctx, "course/analytics-page.html", {
        "flow_identifier": flow_identifier,
        "group_id": group_id,
        "page_id": page_id,
        "title": title,
        "body": body,
        "answer_stats_list": answer_stats,
        })
Exemple #5
0
def make_page_answer_stats_list(pctx, flow_identifier):
    flow_desc = get_flow_desc(pctx.repo, pctx.course, flow_identifier,
            pctx.course_commit_sha)

    is_multiple_submit = is_flow_multiple_submit(flow_desc)

    page_cache = PageInstanceCache(pctx.repo, pctx.course, flow_identifier)

    page_info_list = []
    for group_desc in flow_desc.groups:
        for page_desc in group_desc.pages:
            points = 0
            count = 0

            visits = (FlowPageVisit.objects
                    .filter(
                        flow_session__flow_id=flow_identifier,
                        page_data__group_id=group_desc.id,
                        page_data__page_id=page_desc.id,
                        is_graded_answer=True,
                        ))

            if is_multiple_submit and connection.features.can_distinct_on_fields:
                visits = (visits
                        .distinct("page_data")
                        .order_by("page_data", "-visit_time"))

            visits = (visits
                    .prefetch_related("flow_session")
                    .prefetch_related("page_data"))

            title = None
            for visit in visits:
                flow_commit_sha = get_flow_commit_sha(
                        pctx.course, pctx.participation, flow_desc,
                        visit.flow_session)
                page = page_cache.get_page(group_desc.id, page_desc.id,
                        flow_commit_sha)

                from course.page import PageContext
                grading_page_context = PageContext(
                        course=pctx.course,
                        repo=pctx.repo,
                        commit_sha=flow_commit_sha)

                title = page.title(grading_page_context, visit.page_data.data)

                answer_feedback = visit.get_most_recent_feedback()

                if (answer_feedback is not None
                        and answer_feedback.correctness is not None):
                    count += 1
                    points += answer_feedback.correctness

            page_info_list.append(
                    PageAnswerStats(
                        group_id=group_desc.id,
                        page_id=page_desc.id,
                        title=title,
                        average_correctness=safe_div(points, count),
                        answer_count=count,
                        url=reverse(
                            "course.analytics.page_analytics",
                            args=(
                                pctx.course_identifier,
                                flow_identifier,
                                group_desc.id,
                                page_desc.id,
                                ))))

    return page_info_list