def evaluate_entrance_exam(course, block, user_id): """ Update 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(): entrance_exam_enabled = getattr(course, 'entrance_exam_enabled', False) in_entrance_exam = getattr(block, '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.objects.get(id=user_id) 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.id, 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)
def evaluate_entrance_exam(course, block, user_id): """ Update 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(): entrance_exam_enabled = getattr(course, 'entrance_exam_enabled', False) in_entrance_exam = getattr(block, '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.objects.get(id=user_id) 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.id, 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)
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 ENTRANCE_EXAMS.is_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 _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 settings.FEATURES.get('ENTRANCE_EXAMS', False): 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)
def evaluate_prerequisite(course, subsection_grade, user): """ Evaluates any gating milestone relationships attached to the given subsection. If the subsection_grade meets the minimum score required by dependent subsections, the related milestone will be marked fulfilled for the user. """ prereq_milestone = gating_api.get_gating_milestone( course.id, subsection_grade.location, 'fulfills') if prereq_milestone: gated_content_milestones = defaultdict(list) for milestone in gating_api.find_gating_milestones( course.id, content_key=None, relationship='requires'): gated_content_milestones[milestone['id']].append(milestone) gated_content = gated_content_milestones.get(prereq_milestone['id']) if gated_content: for milestone in gated_content: min_percentage = _get_minimum_required_percentage(milestone) subsection_percentage = _get_subsection_percentage( subsection_grade) if subsection_percentage >= min_percentage: milestones_helpers.add_user_milestone({'id': user.id}, prereq_milestone) else: milestones_helpers.remove_user_milestone({'id': user.id}, prereq_milestone)
def update_milestone(milestone, usage_key, prereq_milestone, user, grade_percentage=None, completion_percentage=None): """ Updates the milestone record based on evaluation of prerequisite met. Arguments: milestone: The gated milestone being evaluated usage_key: Usage key of the prerequisite subsection prereq_milestone: The gating milestone user: The user who has fulfilled milestone grade_percentage: Grade percentage of prerequisite subsection completion_percentage: Completion percentage of prerequisite subsection Returns: True if prerequisite has been met, False if not """ min_score, min_completion = _get_minimum_required_percentage(milestone) if not grade_percentage: grade_percentage = get_subsection_grade_percentage(usage_key, user) if min_score > 0 else 0 if not completion_percentage: completion_percentage = get_subsection_completion_percentage(usage_key, user) if min_completion > 0 else 0 if grade_percentage >= min_score and completion_percentage >= min_completion: milestones_helpers.add_user_milestone({'id': user.id}, prereq_milestone) return True else: milestones_helpers.remove_user_milestone({'id': user.id}, prereq_milestone) return False
def evaluate_prerequisite(course, prereq_content_key, user_id): """ Finds the parent subsection of the content in the course and evaluates any milestone relationships attached to that subsection. If the calculated grade of the prerequisite subsection meets the minimum score required by dependent subsections, the related milestone will be fulfilled for the user. Arguments: user_id (int): ID of User for which evaluation should occur course (CourseModule): The course prereq_content_key (UsageKey): The prerequisite content usage key Returns: None """ xblock = modulestore().get_item(prereq_content_key) sequential = _get_xblock_parent(xblock, 'sequential') if sequential: prereq_milestone = gating_api.get_gating_milestone( course.id, sequential.location.for_branch(None), 'fulfills' ) if prereq_milestone: gated_content_milestones = defaultdict(list) for milestone in gating_api.find_gating_milestones(course.id, None, 'requires'): gated_content_milestones[milestone['id']].append(milestone) gated_content = gated_content_milestones.get(prereq_milestone['id']) if gated_content: user = User.objects.get(id=user_id) score = get_module_score(user, course, sequential) * 100 for milestone in gated_content: # Default minimum score to 100 min_score = 100 requirements = milestone.get('requirements') if requirements: try: min_score = int(requirements.get('min_score')) except (ValueError, TypeError): log.warning( 'Failed to find minimum score for gating milestone %s, defaulting to 100', json.dumps(milestone) ) if score >= min_score: milestones_helpers.add_user_milestone({'id': user_id}, prereq_milestone) else: milestones_helpers.remove_user_milestone({'id': user_id}, prereq_milestone)
def evaluate_prerequisite(course, prereq_content_key, user_id): """ Finds the parent subsection of the content in the course and evaluates any milestone relationships attached to that subsection. If the calculated grade of the prerequisite subsection meets the minimum score required by dependent subsections, the related milestone will be fulfilled for the user. Arguments: user_id (int): ID of User for which evaluation should occur course (CourseModule): The course prereq_content_key (UsageKey): The prerequisite content usage key Returns: None """ xblock = modulestore().get_item(prereq_content_key) sequential = _get_xblock_parent(xblock, 'sequential') if sequential: prereq_milestone = gating_api.get_gating_milestone( course.id, sequential.location.for_branch(None), 'fulfills') if prereq_milestone: gated_content_milestones = defaultdict(list) for milestone in gating_api.find_gating_milestones( course.id, None, 'requires'): gated_content_milestones[milestone['id']].append(milestone) gated_content = gated_content_milestones.get( prereq_milestone['id']) if gated_content: user = User.objects.get(id=user_id) score = get_module_score(user, course, sequential) * 100 for milestone in gated_content: # Default minimum score to 100 min_score = 100 requirements = milestone.get('requirements') if requirements: try: min_score = int(requirements.get('min_score')) except (ValueError, TypeError): log.warning( 'Failed to find minimum score for gating milestone %s, defaulting to 100', json.dumps(milestone)) if score >= min_score: milestones_helpers.add_user_milestone({'id': user_id}, prereq_milestone) else: milestones_helpers.remove_user_milestone( {'id': user_id}, prereq_milestone)
def evaluate_prerequisite(course, user, subsection_usage_key, new_score): """ Finds the parent subsection of the content in the course and evaluates any milestone relationships attached to that subsection. If the calculated grade of the prerequisite subsection meets the minimum score required by dependent subsections, the related milestone will be fulfilled for the user. Arguments: user (User): User for which evaluation should occur course (CourseModule): The course subsection_usage_key (UsageKey): Usage key of the updated subsection new_score (float): New score of the given subsection, in percentage. Returns: None """ prereq_milestone = gating_api.get_gating_milestone(course.id, subsection_usage_key, 'fulfills') if prereq_milestone: gated_content_milestones = defaultdict(list) for milestone in gating_api.find_gating_milestones( course.id, None, 'requires'): gated_content_milestones[milestone['id']].append(milestone) gated_content = gated_content_milestones.get(prereq_milestone['id']) if gated_content: for milestone in gated_content: # Default minimum score to 100 min_score = 100.0 requirements = milestone.get('requirements') if requirements: try: min_score = float(requirements.get('min_score')) except (ValueError, TypeError): log.warning( 'Failed to find minimum score for gating milestone %s, defaulting to 100', json.dumps(milestone)) if new_score >= min_score: milestones_helpers.add_user_milestone({'id': user.id}, prereq_milestone) else: milestones_helpers.remove_user_milestone({'id': user.id}, prereq_milestone)
def evaluate_prerequisite(course, user, subsection_usage_key, new_score): """ Finds the parent subsection of the content in the course and evaluates any milestone relationships attached to that subsection. If the calculated grade of the prerequisite subsection meets the minimum score required by dependent subsections, the related milestone will be fulfilled for the user. Arguments: user (User): User for which evaluation should occur course (CourseModule): The course subsection_usage_key (UsageKey): Usage key of the updated subsection new_score (float): New score of the given subsection, in percentage. Returns: None """ prereq_milestone = gating_api.get_gating_milestone( course.id, subsection_usage_key, 'fulfills' ) if prereq_milestone: gated_content_milestones = defaultdict(list) for milestone in gating_api.find_gating_milestones(course.id, None, 'requires'): gated_content_milestones[milestone['id']].append(milestone) gated_content = gated_content_milestones.get(prereq_milestone['id']) if gated_content: for milestone in gated_content: # Default minimum score to 100 min_score = 100.0 requirements = milestone.get('requirements') if requirements: try: min_score = float(requirements.get('min_score')) except (ValueError, TypeError): log.warning( 'Failed to find minimum score for gating milestone %s, defaulting to 100', json.dumps(milestone) ) if new_score >= min_score: milestones_helpers.add_user_milestone({'id': user.id}, prereq_milestone) else: milestones_helpers.remove_user_milestone({'id': user.id}, prereq_milestone)
def evaluate_prerequisite(course, user, subsection_usage_key, new_score): """ Finds the parent subsection of the content in the course and evaluates any milestone relationships attached to that subsection. If the calculated grade of the prerequisite subsection meets the minimum score required by dependent subsections, the related milestone will be fulfilled for the user. Arguments: course (CourseModule): The course prereq_content_key (UsageKey): The prerequisite content usage key user_id (int): ID of User for which evaluation should occur Returns: None """ prereq_milestone = gating_api.get_gating_milestone(course.id, subsection_usage_key, 'fulfills') if prereq_milestone: gated_content_milestones = defaultdict(list) for milestone in gating_api.find_gating_milestones( course.id, None, 'requires'): gated_content_milestones[milestone['id']].append(milestone) gated_content = gated_content_milestones.get(prereq_milestone['id']) if gated_content: for milestone in gated_content: # Default minimum score to 100 min_score = 100 requirements = milestone.get('requirements') if requirements: try: min_score = int(requirements.get('min_score')) except (ValueError, TypeError): # Use default value of 100 pass if new_score >= min_score: milestones_helpers.add_user_milestone({'id': user.id}, prereq_milestone) else: milestones_helpers.remove_user_milestone({'id': user.id}, prereq_milestone)
def update_milestone(milestone, subsection_grade, prereq_milestone, user_id): """ Updates the milestone record based on evaluation of prerequisite met. Arguments: milestone: The gated milestone being evaluated subsection_grade: The grade of the prerequisite subsection prerequisite_milestone: The gating milestone user_id: The id of the user Returns: True if prerequisite has been met, False if not """ min_percentage = _get_minimum_required_percentage(milestone) subsection_percentage = _get_subsection_percentage(subsection_grade) if subsection_percentage >= min_percentage: milestones_helpers.add_user_milestone({'id': user_id}, prereq_milestone) return True else: milestones_helpers.remove_user_milestone({'id': user_id}, prereq_milestone) return False
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 evaluate_prerequisite(course, subsection_grade, user): """ Evaluates any gating milestone relationships attached to the given subsection. If the subsection_grade meets the minimum score required by dependent subsections, the related milestone will be marked fulfilled for the user. """ prereq_milestone = gating_api.get_gating_milestone(course.id, subsection_grade.location, 'fulfills') if prereq_milestone: gated_content_milestones = defaultdict(list) for milestone in gating_api.find_gating_milestones(course.id, content_key=None, relationship='requires'): gated_content_milestones[milestone['id']].append(milestone) gated_content = gated_content_milestones.get(prereq_milestone['id']) if gated_content: for milestone in gated_content: min_percentage = _get_minimum_required_percentage(milestone) subsection_percentage = _get_subsection_percentage(subsection_grade) if subsection_percentage >= min_percentage: milestones_helpers.add_user_milestone({'id': user.id}, prereq_milestone) else: milestones_helpers.remove_user_milestone({'id': user.id}, prereq_milestone)
def update_milestone(milestone, subsection_grade, prereq_milestone, user_id): """ Updates the milestone record based on evaluation of prerequisite met. Arguments: milestone: The gated milestone being evaluated subsection_grade: The grade of the prerequisite subsection prerequisite_milestone: The gating milestone user_id: The id of the user Returns: True if prerequisite has been met, False if not """ min_percentage = _get_minimum_required_percentage(milestone) subsection_percentage = _get_subsection_percentage(subsection_grade) if subsection_percentage >= min_percentage: milestones_helpers.add_user_milestone({'id': user_id}, prereq_milestone) return True else: milestones_helpers.remove_user_milestone({'id': user_id}, prereq_milestone) return False
def update_milestone(milestone, usage_key, prereq_milestone, user, grade_percentage=None, completion_percentage=None): """ Updates the milestone record based on evaluation of prerequisite met. Arguments: milestone: The gated milestone being evaluated usage_key: Usage key of the prerequisite subsection prereq_milestone: The gating milestone user: The user who has fulfilled milestone grade_percentage: Grade percentage of prerequisite subsection completion_percentage: Completion percentage of prerequisite subsection Returns: True if prerequisite has been met, False if not """ min_score, min_completion = _get_minimum_required_percentage(milestone) if not grade_percentage: grade_percentage = get_subsection_grade_percentage( usage_key, user) if min_score > 0 else 0 if not completion_percentage: completion_percentage = get_subsection_completion_percentage( usage_key, user) if min_completion > 0 else 0 if grade_percentage >= min_score and completion_percentage >= min_completion: milestones_helpers.add_user_milestone({'id': user.id}, prereq_milestone) return True else: milestones_helpers.remove_user_milestone({'id': user.id}, prereq_milestone) return False
def test_add_user_milestone_returns_none_when_app_disabled(self): response = milestones_helpers.add_user_milestone(self.user, self.milestone) self.assertIsNone(response)
def test_add_user_milestone_returns_none_when_app_disabled(self): response = milestones_helpers.add_user_milestone(self.user, self.milestone) self.assertIsNone(response)