Exemple #1
0
 def _fulfill_content_milestones(user, course_key, content_key):
     """
     Internal helper to handle milestone fulfillments for the specified content module
     """
     # Fulfillment Use Case: Entrance Exam
     # If this module is part of an entrance exam, we'll need to see if the student
     # has reached the point at which they can collect the associated milestone
     if milestones_helpers.is_entrance_exams_enabled():
         course = modulestore().get_course(course_key)
         content = modulestore().get_item(content_key)
         entrance_exam_enabled = getattr(course, 'entrance_exam_enabled', False)
         in_entrance_exam = getattr(content, 'in_entrance_exam', False)
         if entrance_exam_enabled and in_entrance_exam:
             # We don't have access to the true request object in this context, but we can use a mock
             request = RequestFactory().request()
             request.user = user
             exam_pct = get_entrance_exam_score(request, course)
             if exam_pct >= course.entrance_exam_minimum_score_pct:
                 exam_key = UsageKey.from_string(course.entrance_exam_id)
                 relationship_types = milestones_helpers.get_milestone_relationship_types()
                 content_milestones = milestones_helpers.get_course_content_milestones(
                     course_key,
                     exam_key,
                     relationship=relationship_types['FULFILLS']
                 )
                 # Add each milestone to the user's set...
                 user = {'id': request.user.id}
                 for milestone in content_milestones:
                     milestones_helpers.add_user_milestone(user, milestone)
Exemple #2
0
def evaluate_entrance_exam(course_grade, user):
    """
    Evaluates any entrance exam milestone relationships attached
    to the given course. If the course_grade meets the
    minimum score required, the dependent milestones will be marked
    fulfilled for the user.
    """
    course = course_grade.course
    if milestones_helpers.is_entrance_exams_enabled() and getattr(
            course, 'entrance_exam_enabled', False):
        if get_entrance_exam_content(user, course):
            exam_chapter_key = get_entrance_exam_usage_key(course)
            exam_score_ratio = get_entrance_exam_score_ratio(
                course_grade, exam_chapter_key)
            if exam_score_ratio >= course.entrance_exam_minimum_score_pct:
                relationship_types = milestones_helpers.get_milestone_relationship_types(
                )
                content_milestones = milestones_helpers.get_course_content_milestones(
                    course.id,
                    exam_chapter_key,
                    relationship=relationship_types['FULFILLS'])
                # Mark each entrance exam dependent milestone as fulfilled by the user.
                for milestone in content_milestones:
                    milestones_helpers.add_user_milestone({'id': user.id},
                                                          milestone)
Exemple #3
0
def _filter_entrance_exam_grader(graders):
    """
    If the entrance exams feature is enabled we need to hide away the grader from
    views/controls like the 'Grade as' dropdown that allows a course author to select
    the grader type for a given section of a course
    """
    if is_entrance_exams_enabled():
        graders = [grader for grader in graders if grader.get('type') != u'Entrance Exam']
    return graders
Exemple #4
0
def course_has_entrance_exam(course):
    """
    Checks to see if a course is properly configured for an entrance exam
    """
    if not is_entrance_exams_enabled():
        return False
    if not course.entrance_exam_enabled:
        return False
    if not course.entrance_exam_id:
        return False
    return True
def course_has_entrance_exam(course):
    """
    Checks to see if a course is properly configured for an entrance exam
    """
    if not is_entrance_exams_enabled():
        return False
    if not course.entrance_exam_enabled:
        return False
    if not course.entrance_exam_id:
        return False
    return True
Exemple #6
0
def evaluate_entrance_exam(course_grade, user):
    """
    Evaluates any entrance exam milestone relationships attached
    to the given course. If the course_grade meets the
    minimum score required, the dependent milestones will be marked
    fulfilled for the user.
    """
    course = course_grade.course_data.course
    if milestones_helpers.is_entrance_exams_enabled() and getattr(course, 'entrance_exam_enabled', False):
        if get_entrance_exam_content(user, course):
            exam_chapter_key = get_entrance_exam_usage_key(course)
            exam_score_ratio = get_entrance_exam_score_ratio(course_grade, exam_chapter_key)
            if exam_score_ratio >= course.entrance_exam_minimum_score_pct:
                relationship_types = milestones_helpers.get_milestone_relationship_types()
                content_milestones = milestones_helpers.get_course_content_milestones(
                    course.id,
                    exam_chapter_key,
                    relationship=relationship_types['FULFILLS']
                )
                # Mark each entrance exam dependent milestone as fulfilled by the user.
                for milestone in content_milestones:
                    milestones_helpers.add_user_milestone({'id': user.id}, milestone)
def create_xblock(parent_locator, user, category, display_name, boilerplate=None, is_entrance_exam=False):
    """
    Performs the actual grunt work of creating items/xblocks -- knows nothing about requests, views, etc.
    """
    store = modulestore()
    usage_key = usage_key_with_run(parent_locator)
    with store.bulk_operations(usage_key.course_key):
        parent = store.get_item(usage_key)
        dest_usage_key = usage_key.replace(category=category, name=uuid4().hex)

        # get the metadata, display_name, and definition from the caller
        metadata = {}
        data = None
        template_id = boilerplate
        if template_id:
            clz = parent.runtime.load_block_type(category)
            if clz is not None:
                template = clz.get_template(template_id)
                if template is not None:
                    metadata = template.get('metadata', {})
                    data = template.get('data')

        if display_name is not None:
            metadata['display_name'] = display_name

        # We should use the 'fields' kwarg for newer module settings/values (vs. metadata or data)
        fields = {}

        # Entrance Exams: Chapter module positioning
        child_position = None
        if is_entrance_exams_enabled():
            if category == 'chapter' and is_entrance_exam:
                fields['is_entrance_exam'] = is_entrance_exam
                fields['in_entrance_exam'] = True  # Inherited metadata, all children will have it
                child_position = 0

        # TODO need to fix components that are sending definition_data as strings, instead of as dicts
        # For now, migrate them into dicts here.
        if isinstance(data, basestring):
            data = {'data': data}

        created_block = store.create_child(
            user.id,
            usage_key,
            dest_usage_key.block_type,
            block_id=dest_usage_key.block_id,
            fields=fields,
            definition_data=data,
            metadata=metadata,
            runtime=parent.runtime,
            position=child_position,
        )

        # Entrance Exams: Grader assignment
        if is_entrance_exams_enabled():
            course_key = usage_key.course_key
            course = store.get_course(course_key)
            if hasattr(course, 'entrance_exam_enabled') and course.entrance_exam_enabled:
                if category == 'sequential' and parent_locator == course.entrance_exam_id:
                    # Clean up any pre-existing entrance exam graders
                    remove_entrance_exam_graders(course_key, user)
                    grader = {
                        "type": GRADER_TYPES['ENTRANCE_EXAM'],
                        "min_count": 0,
                        "drop_count": 0,
                        "short_label": "Entrance",
                        "weight": 0
                    }
                    grading_model = CourseGradingModel.update_grader_from_json(
                        course.id,
                        grader,
                        user
                    )
                    CourseGradingModel.update_section_grader_type(
                        created_block,
                        grading_model['type'],
                        user
                    )

        # VS[compat] cdodge: This is a hack because static_tabs also have references from the course module, so
        # if we add one then we need to also add it to the policy information (i.e. metadata)
        # we should remove this once we can break this reference from the course to static tabs
        if category == 'static_tab':

            dog_stats_api.increment(
                DEPRECATION_VSCOMPAT_EVENT,
                tags=(
                    "location:create_xblock_static_tab",
                    u"course:{}".format(unicode(dest_usage_key.course_key)),
                )
            )

            display_name = display_name or _("Empty")  # Prevent name being None
            course = store.get_course(dest_usage_key.course_key)
            course.tabs.append(
                StaticTab(
                    name=display_name,
                    url_slug=dest_usage_key.name,
                )
            )
            store.update_item(course, user.id)

        return created_block
Exemple #8
0
def create_xblock(parent_locator,
                  user,
                  category,
                  display_name,
                  boilerplate=None,
                  is_entrance_exam=False):
    """
    Performs the actual grunt work of creating items/xblocks -- knows nothing about requests, views, etc.
    """
    store = modulestore()
    usage_key = usage_key_with_run(parent_locator)
    with store.bulk_operations(usage_key.course_key):
        parent = store.get_item(usage_key)
        dest_usage_key = usage_key.replace(category=category, name=uuid4().hex)

        # get the metadata, display_name, and definition from the caller
        metadata = {}
        data = None
        template_id = boilerplate
        if template_id:
            clz = parent.runtime.load_block_type(category)
            if clz is not None:
                template = clz.get_template(template_id)
                if template is not None:
                    metadata = template.get('metadata', {})
                    data = template.get('data')

        if display_name is not None:
            metadata['display_name'] = display_name

        # We should use the 'fields' kwarg for newer module settings/values (vs. metadata or data)
        fields = {}

        # Entrance Exams: Chapter module positioning
        child_position = None
        if is_entrance_exams_enabled():
            if category == 'chapter' and is_entrance_exam:
                fields['is_entrance_exam'] = is_entrance_exam
                fields[
                    'in_entrance_exam'] = True  # Inherited metadata, all children will have it
                child_position = 0

        # TODO need to fix components that are sending definition_data as strings, instead of as dicts
        # For now, migrate them into dicts here.
        if isinstance(data, basestring):
            data = {'data': data}

        created_block = store.create_child(
            user.id,
            usage_key,
            dest_usage_key.block_type,
            block_id=dest_usage_key.block_id,
            fields=fields,
            definition_data=data,
            metadata=metadata,
            runtime=parent.runtime,
            position=child_position,
        )

        # Entrance Exams: Grader assignment
        if is_entrance_exams_enabled():
            course_key = usage_key.course_key
            course = store.get_course(course_key)
            if hasattr(
                    course,
                    'entrance_exam_enabled') and course.entrance_exam_enabled:
                if category == 'sequential' and parent_locator == course.entrance_exam_id:
                    # Clean up any pre-existing entrance exam graders
                    remove_entrance_exam_graders(course_key, user)
                    grader = {
                        "type": GRADER_TYPES['ENTRANCE_EXAM'],
                        "min_count": 0,
                        "drop_count": 0,
                        "short_label": "Entrance",
                        "weight": 0
                    }
                    grading_model = CourseGradingModel.update_grader_from_json(
                        course.id, grader, user)
                    CourseGradingModel.update_section_grader_type(
                        created_block, grading_model['type'], user)

        # VS[compat] cdodge: This is a hack because static_tabs also have references from the course module, so
        # if we add one then we need to also add it to the policy information (i.e. metadata)
        # we should remove this once we can break this reference from the course to static tabs
        if category == 'static_tab':

            dog_stats_api.increment(
                DEPRECATION_VSCOMPAT_EVENT,
                tags=(
                    "location:create_xblock_static_tab",
                    u"course:{}".format(unicode(dest_usage_key.course_key)),
                ))

            display_name = display_name or _(
                "Empty")  # Prevent name being None
            course = store.get_course(dest_usage_key.course_key)
            course.tabs.append(
                StaticTab(
                    name=display_name,
                    url_slug=dest_usage_key.block_id,
                ))
            store.update_item(course, user.id)

        return created_block