Ejemplo n.º 1
0
def grade_page_visits(fctx, flow_session, answer_visits, force_regrade=False):
    for i in range(len(answer_visits)):
        answer_visit = answer_visits[i]

        if answer_visit is not None:
            answer_visit.is_graded_answer = True
            answer_visit.save()

        else:
            page_data = flow_session.page_data.get(ordinal=i)
            page = instantiate_flow_page_with_ctx(fctx, page_data)

            if not page.expects_answer():
                continue

            # Create a synthetic visit to attach a grade
            answer_visit = FlowPageVisit()
            answer_visit.flow_session = flow_session
            answer_visit.page_data = page_data
            answer_visit.is_synthetic = True
            answer_visit.answer = None
            answer_visit.is_graded_answer = True
            answer_visit.save()

            answer_visits[i] = answer_visit

        if (answer_visit is not None
                and (not answer_visit.grades.count() or force_regrade)):
            grade_page_visit(answer_visit,
                    graded_at_git_commit_sha=fctx.flow_commit_sha)
Ejemplo n.º 2
0
def grade_page_visits(fctx, flow_session, answer_visits):
    for i in range(len(answer_visits)):
        answer_visit = answer_visits[i]

        if answer_visit is not None:
            answer_visit.is_graded_answer = True
            answer_visit.save()

        else:
            page_data = flow_session.page_data.get(ordinal=i)
            page = instantiate_flow_page_with_ctx(fctx, page_data)

            if not page.expects_answer():
                continue

            # Create a synthetic visit to attach a grade
            answer_visit = FlowPageVisit()
            answer_visit.flow_session = flow_session
            answer_visit.page_data = page_data
            answer_visit.is_synthetic = True
            answer_visit.answer = None
            answer_visit.is_graded_answer = True
            answer_visit.save()

            answer_visits[i] = answer_visit

        if answer_visit is not None:
            grade_page_visit(answer_visit)
Ejemplo n.º 3
0
def count_answered_gradable(fctx, flow_session, answer_visits):
    all_page_data = FlowPageData.objects.filter(flow_session=flow_session, ordinal__isnull=False).order_by("ordinal")

    answered_count = 0
    unanswered_count = 0
    for i, page_data in enumerate(all_page_data):
        assert i == page_data.ordinal

        if answer_visits[i] is not None:
            answer_data = answer_visits[i].answer
        else:
            answer_data = None

        page = instantiate_flow_page_with_ctx(fctx, page_data)
        if page.expects_answer() and page.is_answer_gradable():
            if answer_data is None:
                unanswered_count += 1
            else:
                answered_count += 1

    return (answered_count, unanswered_count)
Ejemplo n.º 4
0
Archivo: api.py Proyecto: vain01/relate
def get_flow_session_content(api_ctx, course_identifier):
    # type: (APIContext, Text) -> http.HttpResponse

    if not api_ctx.has_permission(pperm.view_gradebook):
        raise PermissionDenied("token role does not have required permissions")

    try:
        session_id_str = api_ctx.request.GET["flow_session_id"]
    except KeyError:
        raise APIError("must specify flow_id GET parameter")

    session_id = int(session_id_str)

    flow_session = get_object_or_404(FlowSession, id=session_id)

    if flow_session.course != api_ctx.course:
        raise PermissionDenied(
                "session's course does not match auth context")

    from course.content import get_course_repo
    from course.flow import adjust_flow_session_page_data, assemble_answer_visits

    with get_course_repo(api_ctx.course) as repo:
        from course.utils import FlowContext, instantiate_flow_page_with_ctx
        fctx = FlowContext(repo, api_ctx.course, flow_session.flow_id)

        adjust_flow_session_page_data(repo, flow_session, api_ctx.course.identifier,
                fctx.flow_desc)

        from course.flow import get_all_page_data
        all_page_data = get_all_page_data(flow_session)
        answer_visits = assemble_answer_visits(flow_session)

        pages = []
        for i, page_data in enumerate(all_page_data):
            page = instantiate_flow_page_with_ctx(fctx, page_data)

            assert i == page_data.page_ordinal

            page_data_json = dict(
                    ordinal=i,
                    page_type=page_data.page_type,
                    group_id=page_data.group_id,
                    page_id=page_data.page_id,
                    page_data=page_data.data,
                    title=page_data.title,
                    bookmarked=page_data.bookmarked,
                    )
            answer_json = None
            grade_json = None

            visit = answer_visits[i]
            if visit is not None:
                from course.page.base import PageContext
                pctx = PageContext(api_ctx.course, repo, fctx.course_commit_sha,
                        flow_session)
                norm_bytes_answer_tup = page.normalized_bytes_answer(
                        pctx, page_data.data, visit.answer)

                # norm_answer needs to be JSON-encodable
                norm_answer = None  # type: Any

                if norm_bytes_answer_tup is not None:
                    answer_file_ext, norm_bytes_answer = norm_bytes_answer_tup

                    if answer_file_ext in [".txt", ".py"]:
                        norm_answer = norm_bytes_answer.decode("utf-8")
                    elif answer_file_ext == ".json":
                        import json
                        norm_answer = json.loads(norm_bytes_answer)
                    else:
                        from base64 import b64encode
                        norm_answer = [answer_file_ext,
                                       b64encode(norm_bytes_answer).decode("utf-8")]

                answer_json = dict(
                    visit_time=visit.visit_time.isoformat(),
                    remote_address=repr(visit.remote_address),
                    user=visit.user.username if visit.user is not None else None,
                    impersonated_by=(visit.impersonated_by.username
                        if visit.impersonated_by is not None else None),
                    is_synthetic_visit=visit.is_synthetic,
                    answer_data=visit.answer,
                    answer=norm_answer,
                    )

                grade = visit.get_most_recent_grade()
                if grade is not None:
                    grade_json = dict(
                        grader=(grade.grader.username
                                if grade.grader is not None else None),
                        grade_time=grade.grade_time.isoformat(),
                        graded_at_git_commit_sha=grade.graded_at_git_commit_sha,
                        max_points=grade.max_points,
                        correctness=grade.correctness,
                        feedback=grade.feedback)

            pages.append({
                "page": page_data_json,
                "answer": answer_json,
                "grade": grade_json,
                })

    result = {
        "session": flow_session_to_json(flow_session),
        "pages": pages,
        }

    return http.JsonResponse(result, safe=False)
Ejemplo n.º 5
0
def get_flow_session_content(api_ctx, course_identifier):
    # type: (APIContext, Text) -> http.HttpResponse

    if not api_ctx.has_permission(pperm.view_gradebook):
        raise PermissionDenied("token role does not have required permissions")

    try:
        session_id_str = api_ctx.request.GET["flow_session_id"]
    except KeyError:
        raise APIError("must specify flow_id GET parameter")

    session_id = int(session_id_str)

    flow_session = get_object_or_404(FlowSession, id=session_id)

    if flow_session.course != api_ctx.course:
        raise PermissionDenied(
                "session's course does not match auth context")

    from course.content import get_course_repo
    from course.flow import adjust_flow_session_page_data, assemble_answer_visits

    with get_course_repo(api_ctx.course) as repo:
        from course.utils import FlowContext, instantiate_flow_page_with_ctx
        fctx = FlowContext(repo, api_ctx.course, flow_session.flow_id)

        adjust_flow_session_page_data(repo, flow_session, api_ctx.course.identifier,
                fctx.flow_desc)

        from course.flow import get_all_page_data
        all_page_data = get_all_page_data(flow_session)
        answer_visits = assemble_answer_visits(flow_session)

        pages = []
        for i, page_data in enumerate(all_page_data):
            page = instantiate_flow_page_with_ctx(fctx, page_data)

            assert i == page_data.page_ordinal

            page_data_json = dict(
                    ordinal=i,
                    page_type=page_data.page_type,
                    group_id=page_data.group_id,
                    page_id=page_data.page_id,
                    page_data=page_data.data,
                    title=page_data.title,
                    bookmarked=page_data.bookmarked,
                    )
            answer_json = None
            grade_json = None

            visit = answer_visits[i]
            if visit is not None:
                from course.page.base import PageContext
                pctx = PageContext(api_ctx.course, repo, fctx.course_commit_sha,
                        flow_session)
                norm_bytes_answer_tup = page.normalized_bytes_answer(
                        pctx, page_data.data, visit.answer)

                # norm_answer needs to be JSON-encodable
                norm_answer = None  # type: Any

                if norm_bytes_answer_tup is not None:
                    answer_file_ext, norm_bytes_answer = norm_bytes_answer_tup

                    if answer_file_ext in [".txt", ".py"]:
                        norm_answer = norm_bytes_answer.decode("utf-8")
                    elif answer_file_ext == ".json":
                        import json
                        norm_answer = json.loads(norm_bytes_answer)
                    else:
                        from base64 import b64encode
                        norm_answer = [answer_file_ext, b64encode(norm_bytes_answer)]

                answer_json = dict(
                    visit_time=visit.visit_time.isoformat(),
                    remote_address=repr(visit.remote_address),
                    user=visit.user.username if visit.user is not None else None,
                    impersonated_by=(visit.impersonated_by.username
                        if visit.impersonated_by is not None else None),
                    is_synthetic_visit=visit.is_synthetic,
                    answer_data=visit.answer,
                    answer=norm_answer,
                    )

                grade = visit.get_most_recent_grade()
                if grade is not None:
                    grade_json = dict(
                        grader=grade.grader,
                        grade_time=grade.grade_time.isoformat(),
                        graded_at_git_commit_sha=grade.graded_at_git_commit_sha,
                        max_points=grade.max_points,
                        correctness=grade.correctness,
                        feedback=grade.feedback)

            pages.append({
                "page": page_data_json,
                "answer": answer_json,
                "grade": grade_json,
                })

    result = {
        "session": flow_session_to_json(flow_session),
        "pages": pages,
        }

    return http.JsonResponse(result, safe=False)
Ejemplo n.º 6
0
def gather_grade_info(fctx, flow_session, answer_visits):
    """
    :returns: a :class:`GradeInfo`
    """

    all_page_data = FlowPageData.objects.filter(flow_session=flow_session, ordinal__isnull=False).order_by("ordinal")

    points = 0
    provisional_points = 0
    max_points = 0
    max_reachable_points = 0
    fully_correct_count = 0
    partially_correct_count = 0
    incorrect_count = 0
    unknown_count = 0

    for i, page_data in enumerate(all_page_data):
        page = instantiate_flow_page_with_ctx(fctx, page_data)

        assert i == page_data.ordinal

        if answer_visits[i] is None:
            # This is true in principle, but early code to deal with survey questions
            # didn't generate synthetic answer visits for survey questions, so this
            # can't actually be enforced.

            # assert not page.expects_answer()
            continue

        if not page.is_answer_gradable():
            continue

        grade = answer_visits[i].get_most_recent_grade()
        assert grade is not None

        feedback = get_feedback_for_grade(grade)

        max_points += grade.max_points

        if feedback is None or feedback.correctness is None:
            unknown_count += 1
            points = None
            continue

        max_reachable_points += grade.max_points

        page_points = grade.max_points * feedback.correctness

        if points is not None:
            points += page_points

        provisional_points += page_points

        if grade.max_points > 0:
            if feedback.correctness == 1:
                fully_correct_count += 1
            elif feedback.correctness == 0:
                incorrect_count += 1
            else:
                partially_correct_count += 1

    return GradeInfo(
        points=points,
        provisional_points=provisional_points,
        max_points=max_points,
        max_reachable_points=max_reachable_points,
        fully_correct_count=fully_correct_count,
        partially_correct_count=partially_correct_count,
        incorrect_count=incorrect_count,
        unknown_count=unknown_count,
    )