示例#1
0
def test_program_prereq_course_scores(mocker, user_application, percent,
                                      courses):
    """
    Test that the `program_prereq_course_scores` property returns the correct program prerequisite course names
    and respective scores of the applicant in those courses, in the correct format.
    """
    mocker.patch('lms.djangoapps.grades.models.emit_course_progress_event')

    test_course_1 = courses['test_course1']
    test_course_2 = courses['test_course2']

    for course in courses.values():
        PersistentCourseGrade.update_or_create(
            user_id=user_application.user_id,
            course_id=course.id,
            percent_grade=percent,
            passed=True)

    MultilingualCourseFactory(course=test_course_1)
    bu_prereq_course = MultilingualCourseGroupFactory(
        is_program_prerequisite=False,
        is_common_business_line_prerequisite=True)
    MultilingualCourseFactory(course=test_course_2,
                              multilingual_course_group=bu_prereq_course)

    score = int(round_away_from_zero(percent * 100))
    course_score_1 = CourseScore(test_course_1.display_name, score)

    expected_prereq_course_scores = [course_score_1]
    actual_prereq_course_scores = user_application.program_prereq_course_scores

    assert expected_prereq_course_scores == actual_prereq_course_scores
示例#2
0
文件: lti_2_util.py 项目: saadow123/1
    def _lti_2_0_result_get_handler(self, request, real_user):  # pylint: disable=unused-argument
        """
        Helper request handler for GET requests to LTI 2.0 result endpoint

        GET handler for lti_2_0_result.  Assumes all authorization has been checked.

        Arguments:
            request (xblock.django.request.DjangoWebobRequest):  Request object (unused)
            real_user (django.contrib.auth.models.User):  Actual user linked to anon_id in request path suffix

        Returns:
            webob.response:  response to this request, in JSON format with status 200 if success
        """
        base_json_obj = {
            "@context": "http://purl.imsglobal.org/ctx/lis/v2/Result",
            "@type": "Result"
        }
        self.system.rebind_noauth_module_to_user(self, real_user)
        if self.module_score is None:  # In this case, no score has been ever set
            return Response(json.dumps(base_json_obj).encode('utf-8'), content_type=LTI_2_0_JSON_CONTENT_TYPE)

        # Fall through to returning grade and comment
        base_json_obj['resultScore'] = round_away_from_zero(self.module_score, 2)
        base_json_obj['comment'] = self.score_comment
        return Response(json.dumps(base_json_obj).encode('utf-8'), content_type=LTI_2_0_JSON_CONTENT_TYPE)
    def _compute_percent(grader_result):
        """
        Computes and returns the grade percentage from the given
        result from the grader.
        """

        # Confused about the addition of .05 here?  See https://openedx.atlassian.net/browse/TNL-6972
        return round_away_from_zero(grader_result['percent'] * 100 + 0.05) / 100
示例#4
0
def convert_float_point_to_percentage(float_value):
    """
    Converts floating point value to percentage value.

    Args:
        float_value (float): Float value which will be converted to percentage.

    Returns:
        int: Percentage value of the float value.
    """
    return int(round_away_from_zero(float_value * 100))
示例#5
0
def test_get_user_scores_for_courses(mock_read, courses):
    """
    Tests that the `get_user_scores_for_courses` returns the course scores for the given
    courses
    """
    user = UserFactory()
    test_course_1 = courses['test_course1']
    test_course_2 = courses['test_course2']
    percent = 0.78

    course_grade = CourseGradeFactory()
    course_grade.percent = percent
    mock_read.return_value = course_grade

    score = int(round_away_from_zero(course_grade.percent * 100))
    course_score_1 = CourseScore(test_course_1.display_name, score)
    course_score_2 = CourseScore(test_course_2.display_name, score)

    expected_scores = [course_score_1, course_score_2]
    actual_scores = get_user_scores_for_courses(user,
                                                [test_course_1, test_course_2])

    assert actual_scores == expected_scores
示例#6
0
def get_user_scores_for_courses(user, courses):
    """
    Given a list of courses, return the scores achieved in every single
    course by the given user

    Arguments:
        user (User): User to find the course grades for
        courses (list): List of courses (CourseOverview) for which to find the course grades

    Returns:
         list: list of scores (CourseScore) in the courses
    """
    scores_in_courses = []
    for course_overview in courses:
        course_name = course_overview.display_name
        course_grade = CourseGradeFactory().read(user,
                                                 course_key=course_overview.id)
        course_percentage = int(
            round_away_from_zero(course_grade.percent * 100))

        course_score = CourseScore(course_name, course_percentage)
        scores_in_courses.append(course_score)

    return scores_in_courses
示例#7
0
def get_students_problem_grades(request, csv=False):
    """
    Get a list of students and grades for a particular problem.
    If 'csv' is False, returns a dict of student's name: username: grade: percent.

    If 'csv' is True, returns a header array, and an array of arrays in the format:
    student names, usernames, grades, percents for CSV download.
    """
    module_state_key = BlockUsageLocator.from_string(
        request.GET.get('module_id'))
    csv = request.GET.get('csv')

    # Query for "problem grades" students
    students = models.StudentModule.objects.select_related('student').filter(
        module_state_key=module_state_key,
        module_type__exact='problem',
        grade__isnull=False,
    ).values('student__username', 'student__profile__name', 'grade',
             'max_grade').order_by('student__profile__name')

    results = []
    if not csv:
        # Restrict screen list length
        # Adding 1 so can tell if list is larger than MAX_SCREEN_LIST_LENGTH
        # without doing another select.
        for student in students[0:MAX_SCREEN_LIST_LENGTH + 1]:
            student_dict = {
                'name': student['student__profile__name'],
                'username': student['student__username'],
                'grade': student['grade'],
            }

            student_dict['percent'] = 0
            if student['max_grade'] > 0:
                student_dict['percent'] = round_away_from_zero(
                    student['grade'] * 100 / student['max_grade'])
            results.append(student_dict)

        max_exceeded = False
        if len(results) > MAX_SCREEN_LIST_LENGTH:
            # Remove the last item so list length is exactly MAX_SCREEN_LIST_LENGTH
            del results[-1]
            max_exceeded = True

        response_payload = {
            'results': results,
            'max_exceeded': max_exceeded,
        }
        return JsonResponse(response_payload)
    else:
        tooltip = request.GET.get('tooltip')
        filename = sanitize_filename(tooltip[:tooltip.rfind(' - ')])

        header = [_("Name"), _("Username"), _("Grade"), _("Percent")]
        for student in students:
            percent = 0
            if student['max_grade'] > 0:
                percent = round_away_from_zero(
                    (student['grade'] * 100 / student['max_grade']), 1)
            results.append([
                student['student__profile__name'],
                student['student__username'], student['grade'], percent
            ])

        response = create_csv_response(filename, header, results)
        return response
示例#8
0
def get_d3_section_grade_distrib(course_id, section):
    """
    Returns the grade distribution for the problems in the `section` section in a format for the d3 code.

    `course_id` a string that is the course's ID.

    `section` an int that is a zero-based index into the course's list of sections.

    Navigates to the section specified to find all the problems associated with that section and then finds the grade
    distribution for those problems. Finally returns an object formated the way the d3_stacked_bar_graph.js expects its
    data object to be in.

    If this is requested multiple times quickly for the same course, it is better to call
    get_d3_problem_grade_distrib and pick out the sections of interest.

    Returns an array of dicts with the following keys (taken from d3_stacked_bar_graph.js's documentation)
      'xValue' - Corresponding value for the x-axis
      'stackData' - Array of objects with key, value pairs that represent a bar:
        'color' - Defines what "color" the bar will map to
        'value' - Maps to the height of the bar, along the y-axis
        'tooltip' - (Optional) Text to display on mouse hover
    """

    # Retrieve course object down to problems
    course = modulestore().get_course(course_id, depth=4)

    problem_set = []
    problem_info = {}
    c_subsection = 0
    for subsection in course.get_children()[section].get_children():
        c_subsection += 1
        c_unit = 0
        for unit in subsection.get_children():
            c_unit += 1
            c_problem = 0
            for child in unit.get_children():
                if child.location.block_type == 'problem':
                    c_problem += 1
                    problem_set.append(child.location)
                    problem_info[child.location] = {
                        'id':
                        text_type(child.location),
                        'x_value':
                        "P{0}.{1}.{2}".format(c_subsection, c_unit, c_problem),
                        'display_name':
                        own_metadata(child).get('display_name', ''),
                    }

    # Retrieve grade distribution for these problems
    grade_distrib = get_problem_set_grade_distrib(course_id, problem_set)

    d3_data = []

    # Construct data for each problem to be sent to d3
    for problem in problem_set:
        stack_data = []

        if problem in grade_distrib:  # Some problems have no data because students have not tried them yet.
            max_grade = float(grade_distrib[problem]['max_grade'])
            for (grade,
                 count_grade) in grade_distrib[problem]['grade_distrib']:
                percent = 0.0
                if max_grade > 0:
                    percent = round_away_from_zero((grade * 100.0) / max_grade,
                                                   1)

                # Construct tooltip for problem in grade distibution view
                tooltip = {
                    'type': 'problem',
                    'problem_info_x': problem_info[problem]['x_value'],
                    'count_grade': count_grade,
                    'percent': percent,
                    'problem_info_n': problem_info[problem]['display_name'],
                    'grade': grade,
                    'max_grade': max_grade,
                }

                stack_data.append({
                    'color': percent,
                    'value': count_grade,
                    'tooltip': tooltip,
                })

        d3_data.append({
            'xValue': problem_info[problem]['x_value'],
            'stackData': stack_data,
        })

    return d3_data
示例#9
0
def get_d3_problem_grade_distrib(course_id):
    """
    Returns problem grade distribution information for each section, data already in format for d3 function.

    `course_id` the course ID for the course interested in

    Returns an array of dicts in the order of the sections. Each dict has:
      'display_name' - display name for the section
      'data' - data for the d3_stacked_bar_graph function of the grade distribution for that problem
    """

    prob_grade_distrib, total_student_count = get_problem_grade_distribution(
        course_id)
    d3_data = []

    # Retrieve course object down to problems
    course = modulestore().get_course(course_id, depth=4)

    # Iterate through sections, subsections, units, problems
    for section in course.get_children():
        curr_section = {}
        curr_section['display_name'] = own_metadata(section).get(
            'display_name', '')
        data = []
        c_subsection = 0
        for subsection in section.get_children():
            c_subsection += 1
            c_unit = 0
            for unit in subsection.get_children():
                c_unit += 1
                c_problem = 0
                for child in unit.get_children():

                    # Student data is at the problem level
                    if child.location.block_type == 'problem':
                        c_problem += 1
                        stack_data = []

                        # Construct label to display for this problem
                        label = "P{0}.{1}.{2}".format(c_subsection, c_unit,
                                                      c_problem)

                        # Only problems in prob_grade_distrib have had a student submission.
                        if child.location in prob_grade_distrib:

                            # Get max_grade, grade_distribution for this problem
                            problem_info = prob_grade_distrib[child.location]

                            # Get problem_name for tooltip
                            problem_name = own_metadata(child).get(
                                'display_name', '')

                            # Compute percent of this grade over max_grade
                            max_grade = float(problem_info['max_grade'])
                            for (grade,
                                 count_grade) in problem_info['grade_distrib']:
                                percent = 0.0
                                if max_grade > 0:
                                    percent = round_away_from_zero(
                                        (grade * 100.0) / max_grade, 1)

                                # Compute percent of students with this grade
                                student_count_percent = 0
                                if total_student_count.get(child.location,
                                                           0) > 0:
                                    student_count_percent = count_grade * 100 / total_student_count[
                                        child.location]

                                # Tooltip parameters for problem in grade distribution view
                                tooltip = {
                                    'type': 'problem',
                                    'label': label,
                                    'problem_name': problem_name,
                                    'count_grade': count_grade,
                                    'percent': percent,
                                    'grade': grade,
                                    'max_grade': max_grade,
                                    'student_count_percent':
                                    student_count_percent,
                                }

                                # Construct data to be sent to d3
                                stack_data.append({
                                    'color':
                                    percent,
                                    'value':
                                    count_grade,
                                    'tooltip':
                                    tooltip,
                                    'module_url':
                                    text_type(child.location),
                                })

                        problem = {
                            'xValue': label,
                            'stackData': stack_data,
                        }
                        data.append(problem)
        curr_section['data'] = data

        d3_data.append(curr_section)

    return d3_data