def make_student(self, block, name, **state): answer = {} for key in ("sha1", "mimetype", "filename"): if key in state: answer[key] = state.pop(key) score = state.pop("score", None) user = User(username=name) user.save() profile = UserProfile(user=user, name=name) profile.save() module = StudentModule( module_state_key=block.location, student=user, course_id=self.course_id, state=json.dumps(state) ) module.save() anonymous_id = anonymous_id_for_user(user, self.course_id) item = StudentItem(student_id=anonymous_id, course_id=self.course_id, item_id=block.block_id, item_type="sga") item.save() if answer: student_id = block.student_submission_id(anonymous_id) submission = submissions_api.create_submission(student_id, answer) if score is not None: submissions_api.set_score(submission["uuid"], score, block.max_score()) else: submission = None self.addCleanup(item.delete) self.addCleanup(profile.delete) self.addCleanup(module.delete) self.addCleanup(user.delete) return {"module": module, "item": item, "submission": submission}
def setUp(self): """ Fixtures. """ due = datetime.datetime(2010, 5, 12, 2, 42, tzinfo=utc) course = CourseFactory.create() week1 = ItemFactory.create(due=due, parent=course) week2 = ItemFactory.create(due=due, parent=course) homework = ItemFactory.create(parent=week1, due=due) user = UserFactory.create() StudentModule(state='{}', student_id=user.id, course_id=course.id, module_state_key=week1.location).save() StudentModule(state='{}', student_id=user.id, course_id=course.id, module_state_key=homework.location).save() self.course = course self.week1 = week1 self.homework = homework self.week2 = week2 self.user = user self.extended_due = functools.partial(get_extended_due, course, student=user)
def make_student(self, block, name, make_state=True, **state): """ Create a student along with submission state. """ answer = {} module = None for key in ('sha1', 'mimetype', 'filename', 'finalized'): if key in state: answer[key] = state.pop(key) score = state.pop('score', None) with transaction.atomic(): user = User(username=name, email='{}@example.com'.format(name)) user.save() profile = UserProfile(user=user, name=name) profile.save() if make_state: module = StudentModule( module_state_key=block.location, student=user, course_id=self.course_id, state=json.dumps(state)) module.save() anonymous_id = anonymous_id_for_user(user, self.course_id) item = StudentItem( student_id=anonymous_id, course_id=self.course_id, item_id=block.block_id, item_type='sga') item.save() if answer: student_id = block.get_student_item_dict(anonymous_id) submission = submissions_api.create_submission(student_id, answer) if score is not None: submissions_api.set_score( submission['uuid'], score, block.max_score()) else: submission = None self.addCleanup(item.delete) self.addCleanup(profile.delete) self.addCleanup(user.delete) if make_state: self.addCleanup(module.delete) return { 'module': module, 'item': item, 'submission': submission } return { 'item': item, 'submission': submission }
def make_student(self, block, name, make_state=True, **state): """ Create a student along with submission state. """ answer = {} module = None for key in ('sha1', 'mimetype', 'filename', 'finalized'): if key in state: answer[key] = state.pop(key) score = state.pop('score', None) with transaction.atomic(): user = User(username=name) user.save() profile = UserProfile(user=user, name=name) profile.save() if make_state: module = StudentModule( module_state_key=block.location, student=user, course_id=self.course_id, state=json.dumps(state)) module.save() anonymous_id = anonymous_id_for_user(user, self.course_id) item = StudentItem( student_id=anonymous_id, course_id=self.course_id, item_id=block.block_id, item_type='sga') item.save() if answer: student_id = block.get_student_item_dict(anonymous_id) submission = submissions_api.create_submission(student_id, answer) if score is not None: submissions_api.set_score( submission['uuid'], score, block.max_score()) else: submission = None self.addCleanup(item.delete) self.addCleanup(profile.delete) self.addCleanup(user.delete) if make_state: self.addCleanup(module.delete) return { 'module': module, 'item': item, 'submission': submission } return { 'item': item, 'submission': submission }
def setUp(self): """ Fixtures. """ super(TestDataDumps, self).setUp() due = datetime.datetime(2010, 5, 12, 2, 42, tzinfo=utc) course = CourseFactory.create() week1 = ItemFactory.create(due=due, parent=course) week2 = ItemFactory.create(due=due, parent=course) week3 = ItemFactory.create(due=due, parent=course) homework = ItemFactory.create(parent=week1, due=due) user1 = UserFactory.create() StudentModule(state='{}', student_id=user1.id, course_id=course.id, module_state_key=week1.location).save() StudentModule(state='{}', student_id=user1.id, course_id=course.id, module_state_key=week2.location).save() StudentModule(state='{}', student_id=user1.id, course_id=course.id, module_state_key=week3.location).save() StudentModule(state='{}', student_id=user1.id, course_id=course.id, module_state_key=homework.location).save() user2 = UserFactory.create() StudentModule(state='{}', student_id=user2.id, course_id=course.id, module_state_key=week1.location).save() StudentModule(state='{}', student_id=user2.id, course_id=course.id, module_state_key=homework.location).save() user3 = UserFactory.create() StudentModule(state='{}', student_id=user3.id, course_id=course.id, module_state_key=week1.location).save() StudentModule(state='{}', student_id=user3.id, course_id=course.id, module_state_key=homework.location).save() self.course = course self.week1 = week1 self.homework = homework self.week2 = week2 self.user1 = user1 self.user2 = user2
def create_course_reference_data(course_key): """ Populates DB with test data """ user = UserFactory() group = GroupFactory() CourseGroupRelationship(course_id=course_key, group=group).save() StudentGradebook( user=user, course_id=course_key, grade=0.9, proforma_grade=0.91, progress_summary='test', grade_summary='test', grading_policy='test', ).save() StudentProgress(user=user, course_id=course_key, completions=1).save() CourseModuleCompletion(user=user, course_id=course_key, content_id='test', stage='test').save() CourseEnrollment(user=user, course_id=course_key).save() CourseAccessRole(user=user, course_id=course_key, org='test', role='TA').save() handouts_usage_key = course_key.make_usage_key('course_info', 'handouts') StudentModule(student=user, course_id=course_key, module_state_key=handouts_usage_key).save() CourseAggregatedMetaData(id=course_key, total_assessments=10, total_modules=20).save() structure_json = '{"test": true}' course_structure, created = CourseStructure.objects.get_or_create( course_id=course_key, defaults={'structure_json': structure_json} ) if not created: course_structure.structure_json = structure_json course_structure.save() CourseOverview.get_from_id(course_key)
def _get_modules_to_update(course_id, usage_keys, student_identifier, filter_fcn, override_score_task=False): """ Fetches a StudentModule instances for a given `course_id`, `student` object, and `usage_keys`. StudentModule instances are those that match the specified `course_id` and `module_state_key`. If `student_identifier` is not None, it is used as an additional filter to limit the modules to those belonging to that student. If `student_identifier` is None, performs update on modules for all students on the specified problem. The matched instances are then applied `filter_fcn` if not None. It filters out the matched instances. It takes one argument, which is the query being filtered, and returns the filtered version of the query. If `override_score_task` is True and we there were not matching instances of StudentModule, try to create those instances. This is only for override scores and the use case is for learners that have missed the deadline. Arguments: course_id(str): The unique identifier for the course. usage_keys(list): List of UsageKey objects student_identifier(str): Identifier for a student or None. The identifier can be either username or email filter_fcn: If it is not None, it is applied to the query that has been constructed. override_score_task (bool): Optional argument which indicates if it is an override score or not. """ def get_student(): """ Fetches student instance if an identifier is provided, else return None """ if student_identifier is None: return None student_identifier_type = 'email' if '@' in student_identifier else 'username' student_query_params = {student_identifier_type: student_identifier} return User.objects.get(**student_query_params) module_query_params = { 'course_id': course_id, 'module_state_keys': usage_keys } # give the option of updating an individual student. If not specified, # then updates all students who have responded to a problem so far student = get_student() if student: module_query_params['student_id'] = student.id student_modules = StudentModule.get_state_by_params(**module_query_params) if filter_fcn is not None: student_modules = filter_fcn(student_modules) can_create_student_modules = (override_score_task and (student_modules.count() == 0) and student is not None) if can_create_student_modules: student_modules = [ StudentModule.objects.get_or_create(course_id=course_id, student=student, module_state_key=key)[0] for key in usage_keys ] return student_modules
def make_student_module(self, block, name, **state): user = User(username=name) user.save() profile = UserProfile(user=user, name=name) profile.save() module = StudentModule( module_state_key=block.location, student=user, course_id=self.course_id, state=json.dumps(state)) module.save() self.addCleanup(profile.delete) self.addCleanup(module.delete) self.addCleanup(user.delete) return module
def make_student(self, block, name, **state): answer = {} for key in ('sha1', 'mimetype', 'filename'): if key in state: answer[key] = state.pop(key) score = state.pop('score', None) user = User(username=name) user.save() profile = UserProfile(user=user, name=name) profile.save() module = StudentModule( module_state_key=block.location, student=user, course_id=self.course_id, state=json.dumps(state)) module.save() anonymous_id = anonymous_id_for_user(user, self.course_id) item = StudentItem( student_id=anonymous_id, course_id=self.course_id, item_id=block.block_id, item_type='sga') item.save() if answer: student_id = block.student_submission_id(anonymous_id) submission = submissions_api.create_submission(student_id, answer) if score is not None: submissions_api.set_score( submission['uuid'], score, block.max_score()) else: submission = None self.addCleanup(item.delete) self.addCleanup(profile.delete) self.addCleanup(module.delete) self.addCleanup(user.delete) return { 'module': module, 'item': item, 'submission': submission, }
def _get_modules_to_update(course_id, usage_keys, student_identifier, filter_fcn, override_score_task=False): """ Fetches a StudentModule instances for a given `course_id`, `student` object, and `usage_keys`. StudentModule instances are those that match the specified `course_id` and `module_state_key`. If `student_identifier` is not None, it is used as an additional filter to limit the modules to those belonging to that student. If `student_identifier` is None, performs update on modules for all students on the specified problem. The matched instances are then applied `filter_fcn` if not None. It filters out the matched instances. It takes one argument, which is the query being filtered, and returns the filtered version of the query. If `override_score_task` is True and we there were not matching instances of StudentModule, try to create those instances. This is only for override scores and the use case is for learners that have missed the deadline. Arguments: course_id(str): The unique identifier for the course. usage_keys(list): List of UsageKey objects student_identifier(str): Identifier for a student or None. The identifier can be either username or email filter_fcn: If it is not None, it is applied to the query that has been constructed. override_score_task (bool): Optional argument which indicates if it is an override score or not. """ def get_student(): """ Fetches student instance if an identifier is provided, else return None """ if student_identifier is None: return None student_identifier_type = 'email' if '@' in student_identifier else 'username' student_query_params = {student_identifier_type: student_identifier} return User.objects.get(**student_query_params) module_query_params = {'course_id': course_id, 'module_state_keys': usage_keys} # give the option of updating an individual student. If not specified, # then updates all students who have responded to a problem so far student = get_student() if student: module_query_params['student_id'] = student.id student_modules = StudentModule.get_state_by_params(**module_query_params) if filter_fcn is not None: student_modules = filter_fcn(student_modules) can_create_student_modules = (override_score_task and (student_modules.count() == 0) and student is not None) if can_create_student_modules: student_modules = [ StudentModule.objects.get_or_create(course_id=course_id, student=student, module_state_key=key)[0] for key in usage_keys ] return student_modules
def generate_dummy_submission(student, block, course_key): """ Generates a random answers for a specified user and block The currently supported blocks are poll and survey """ location = block.location answer = {} if block.category == 'poll': # Possible answers come in this format: # ('G', {'img': None, 'img_alt': None, 'label': 'Green'}) # and we only need the 'G' bit for saving the answer possible_answers = [answer for answer, _ in block.answers] # Answer format for StudentModule model: # {"submissions_count": 1, "choice": "R"} choice = random.choice(possible_answers) answer = { "submissions_count": 1, "choice": choice, } elif block.category == 'survey': # Questions come in this format: # ('enjoy', {'img': None, 'img_alt': None, 'label': 'Are you enjoying the course?'}) # and we only need the 'enjoy' part questions = [question for question, _ in block.questions] # This happens similarly with answers possible_answers = [answer for answer, _ in block.answers] # Answer format for StudentModule model: # {"submissions_count": 1, "choices": {"enjoy": "Y", "learn": "Y", "recommend": "N"}} choices = { key: random.choice(possible_answers) for key in questions } answer = { "submissions_count": 1, "choices": choices, } return StudentModule( module_type='problem', module_state_key=location, student=student, course_id=course_key, state=json.dumps(answer), )
def transform_block_filters(self, usage_info, block_structure): all_library_children = set() all_selected_children = set() for block_key in block_structure: if block_key.block_type != 'library_content': continue library_children = block_structure.get_children(block_key) if library_children: all_library_children.update(library_children) selected = [] mode = block_structure.get_xblock_field(block_key, 'mode') max_count = block_structure.get_xblock_field( block_key, 'max_count') # Retrieve "selected" json from LMS MySQL database. state_dict = get_student_module_as_dict( usage_info.user, usage_info.course_key, block_key) for selected_block in state_dict.get('selected', []): # Add all selected entries for this user for this # library module to the selected list. block_type, block_id = selected_block usage_key = usage_info.course_key.make_usage_key( block_type, block_id) if usage_key in library_children: selected.append(selected_block) # Update selected previous_count = len(selected) block_keys = LibraryContentModule.make_selection( selected, library_children, max_count, mode) selected = block_keys['selected'] # Save back any changes if any(block_keys[changed] for changed in ('invalid', 'overlimit', 'added')): state_dict['selected'] = list(selected) StudentModule.save_state( student=usage_info.user, course_id=usage_info.course_key, module_state_key=block_key, defaults={ 'state': json.dumps(state_dict), }, ) # publish events for analytics self._publish_events( block_structure, block_key, previous_count, max_count, block_keys, usage_info.user.id, ) all_selected_children.update( usage_info.course_key.make_usage_key(s[0], s[1]) for s in selected) def check_child_removal(block_key): """ Return True if selected block should be removed. Block is removed if it is part of library_content, but has not been selected for current user, with staff as an exemption. """ if usage_info.has_staff_access: return False if block_key not in all_library_children: return False if block_key in all_selected_children: return False return True return [block_structure.create_removal_filter(check_child_removal)]
def transform_block_filters(self, usage_info, block_structure): all_library_children = set() all_selected_children = set() for block_key in block_structure: if block_key.block_type != 'library_content': continue library_children = block_structure.get_children(block_key) if library_children: all_library_children.update(library_children) selected = [] mode = block_structure.get_xblock_field(block_key, 'mode') max_count = block_structure.get_xblock_field(block_key, 'max_count') # Retrieve "selected" json from LMS MySQL database. state_dict = get_student_module_as_dict(usage_info.user, usage_info.course_key, block_key) for selected_block in state_dict.get('selected', []): # Add all selected entries for this user for this # library module to the selected list. block_type, block_id = selected_block usage_key = usage_info.course_key.make_usage_key(block_type, block_id) if usage_key in library_children: selected.append(selected_block) # Update selected previous_count = len(selected) block_keys = LibraryContentModule.make_selection(selected, library_children, max_count, mode) selected = block_keys['selected'] # Save back any changes if any(block_keys[changed] for changed in ('invalid', 'overlimit', 'added')): state_dict['selected'] = list(selected) random.shuffle(state_dict['selected']) StudentModule.save_state( student=usage_info.user, course_id=usage_info.course_key, module_state_key=block_key, defaults={ 'state': json.dumps(state_dict), }, ) # publish events for analytics self._publish_events( block_structure, block_key, previous_count, max_count, block_keys, usage_info.user.id, ) all_selected_children.update(usage_info.course_key.make_usage_key(s[0], s[1]) for s in selected) def check_child_removal(block_key): """ Return True if selected block should be removed. Block is removed if it is part of library_content, but has not been selected for current user, with staff as an exemption. """ if usage_info.has_staff_access: return False if block_key not in all_library_children: return False if block_key in all_selected_children: return False return True return [block_structure.create_removal_filter(check_child_removal)]
def setUp(self): """ Fixtures. """ due = datetime.datetime(2010, 5, 12, 2, 42, tzinfo=utc) course = CourseFactory.create() week1 = ItemFactory.create(due=due) week2 = ItemFactory.create(due=due) week3 = ItemFactory.create(due=due) course.children = [ week1.location.url(), week2.location.url(), week3.location.url() ] homework = ItemFactory.create(parent_location=week1.location, due=due) week1.children = [homework.location.url()] user1 = UserFactory.create() StudentModule(state='{}', student_id=user1.id, course_id=course.id, module_state_key=week1.location.url()).save() StudentModule(state='{}', student_id=user1.id, course_id=course.id, module_state_key=week2.location.url()).save() StudentModule(state='{}', student_id=user1.id, course_id=course.id, module_state_key=week3.location.url()).save() StudentModule(state='{}', student_id=user1.id, course_id=course.id, module_state_key=homework.location.url()).save() user2 = UserFactory.create() StudentModule(state='{}', student_id=user2.id, course_id=course.id, module_state_key=week1.location.url()).save() StudentModule(state='{}', student_id=user2.id, course_id=course.id, module_state_key=homework.location.url()).save() user3 = UserFactory.create() StudentModule(state='{}', student_id=user3.id, course_id=course.id, module_state_key=week1.location.url()).save() StudentModule(state='{}', student_id=user3.id, course_id=course.id, module_state_key=homework.location.url()).save() self.course = course self.week1 = week1 self.homework = homework self.week2 = week2 self.user1 = user1 self.user2 = user2