def test_time_info(self): due_date = datetime.datetime(2000, 4, 14, 10, tzinfo=UTC) grace_pd_string = '1 day 12 hours 59 minutes 59 seconds' timeinfo = TimeInfo(due_date, grace_pd_string) self.assertEqual( timeinfo.close_date, due_date + Timedelta().from_json(grace_pd_string) )
def __init__(self, *args, **kwargs): super(PeerGradingModule, self).__init__(*args, **kwargs) # Copy this to a new variable so that we can edit it if needed. # We need to edit it if the linked module cannot be found, so # we can revert to panel model. self.use_for_single_location_local = self.use_for_single_location # We need to set the location here so the child modules can use it. self.runtime.set('location', self.location) if (self.runtime.open_ended_grading_interface): self.peer_gs = PeerGradingService( self.system.open_ended_grading_interface, self.system.render_template) else: self.peer_gs = MockPeerGradingService() if self.use_for_single_location_local: linked_descriptors = self.descriptor.get_required_module_descriptors( ) if len(linked_descriptors) == 0: error_msg = "Peer grading module {0} is trying to use single problem mode without " "a location specified.".format(self.location) log.error(error_msg) # Change module over to panel mode from single problem mode. self.use_for_single_location_local = False else: self.linked_problem = self.system.get_module( linked_descriptors[0]) try: self.timeinfo = TimeInfo(get_extended_due_date(self), self.graceperiod) except Exception: log.error( "Error parsing due date information in location {0}".format( self.location)) raise self.display_due_date = self.timeinfo.display_due_date try: self.student_data_for_location = json.loads( self.student_data_for_location) except Exception: # pylint: disable=broad-except # OK with this broad exception because we just want to continue on any error pass
def __init__(self, system, location, definition, descriptor, instance_state=None, shared_state=None, metadata=None, static_data=None, **kwargs): """ Definition file should have one or many task blocks, a rubric block, and a prompt block: Sample file: <combinedopenended attempts="10000"> <rubric> Blah blah rubric. </rubric> <prompt> Some prompt. </prompt> <task> <selfassessment> <hintprompt> What hint about this problem would you give to someone? </hintprompt> <submitmessage> Save Succcesful. Thanks for participating! </submitmessage> </selfassessment> </task> <task> <openended min_score_to_attempt="1" max_score_to_attempt="1"> <openendedparam> <initial_display>Enter essay here.</initial_display> <answer_display>This is the answer.</answer_display> <grader_payload>{"grader_settings" : "ml_grading.conf", "problem_id" : "6.002x/Welcome/OETest"}</grader_payload> </openendedparam> </openended> </task> </combinedopenended> """ self.instance_state = instance_state self.display_name = instance_state.get('display_name', "Open Ended") self.rewrite_content_links = static_data.get('rewrite_content_links', "") # We need to set the location here so the child modules can use it system.set('location', location) self.system = system # Tells the system which xml definition to load self.current_task_number = instance_state.get('current_task_number', 0) # This loads the states of the individual children self.task_states = instance_state.get('task_states', []) # Overall state of the combined open ended module self.state = instance_state.get('state', self.INITIAL) self.student_attempts = instance_state.get('student_attempts', 0) self.weight = instance_state.get('weight', 1) # Allow reset is true if student has failed the criteria to move to the # next child task self.ready_to_reset = instance_state.get('ready_to_reset', False) self.attempts = self.instance_state.get('attempts', MAX_ATTEMPTS) self.is_scored = self.instance_state.get('is_graded', IS_SCORED) in TRUE_DICT self.accept_file_upload = self.instance_state.get( 'accept_file_upload', ACCEPT_FILE_UPLOAD) in TRUE_DICT self.skip_basic_checks = self.instance_state.get( 'skip_spelling_checks', SKIP_BASIC_CHECKS) in TRUE_DICT due_date = self.instance_state.get('due', None) grace_period_string = self.instance_state.get('graceperiod', None) try: self.timeinfo = TimeInfo(due_date, grace_period_string) except Exception: log.error( "Error parsing due date information in location {0}".format( location)) raise self.display_due_date = self.timeinfo.display_due_date self.rubric_renderer = CombinedOpenEndedRubric(system, True) rubric_string = stringify_children(definition['rubric']) self._max_score = self.rubric_renderer.check_if_rubric_is_parseable( rubric_string, location, MAX_SCORE_ALLOWED) # Static data is passed to the child modules to render self.static_data = { 'max_score': self._max_score, 'max_attempts': self.attempts, 'prompt': definition['prompt'], 'rubric': definition['rubric'], 'display_name': self.display_name, 'accept_file_upload': self.accept_file_upload, 'close_date': self.timeinfo.close_date, 's3_interface': self.system.s3_interface, 'skip_basic_checks': self.skip_basic_checks, } self.task_xml = definition['task_xml'] self.location = location self.setup_next_task()
def peer_grading(self, _data=None): ''' Show a peer grading interface ''' # call problem list service success = False error_text = "" problem_list = [] try: problem_list_dict = self.peer_gs.get_problem_list( self.course_id, self.system.anonymous_student_id) success = problem_list_dict['success'] if 'error' in problem_list_dict: error_text = problem_list_dict['error'] problem_list = problem_list_dict['problem_list'] except GradingServiceError: # This is a student_facing_error error_text = EXTERNAL_GRADER_NO_CONTACT_ERROR log.error(error_text) success = False # catch error if if the json loads fails except ValueError: # This is a student_facing_error error_text = "Could not get list of problems to peer grade. Please notify course staff." log.error(error_text) success = False except Exception: log.exception("Could not contact peer grading service.") success = False good_problem_list = [] for problem in problem_list: problem_location = Location(problem['location']) try: descriptor = self._find_corresponding_module_for_location( problem_location) except (NoPathToItem, ItemNotFoundError): continue if descriptor: problem['due'] = get_extended_due_date(descriptor) grace_period = descriptor.graceperiod try: problem_timeinfo = TimeInfo(problem['due'], grace_period) except Exception: log.error( "Malformed due date or grace period string for location {0}" .format(problem_location)) raise if self._closed(problem_timeinfo): problem['closed'] = True else: problem['closed'] = False else: # if we can't find the due date, assume that it doesn't have one problem['due'] = None problem['closed'] = False good_problem_list.append(problem) ajax_url = self.ajax_url html = self.system.render_template( 'peer_grading/peer_grading.html', { 'course_id': self.course_id, 'ajax_url': ajax_url, 'success': success, 'problem_list': good_problem_list, 'error_text': error_text, # Checked above 'staff_access': False, 'use_single_location': self.use_for_single_location_local, }) return html
def __init__(self, system, location, definition, descriptor, instance_state=None, shared_state=None, metadata=None, static_data=None, **kwargs): """ Definition file should have one or many task blocks, a rubric block, and a prompt block. See DEFAULT_DATA in combined_open_ended_module for a sample. """ self.instance_state = instance_state self.display_name = instance_state.get('display_name', "Open Ended") # We need to set the location here so the child modules can use it system.set('location', location) self.system = system # Tells the system which xml definition to load self.current_task_number = instance_state.get('current_task_number', 0) # This loads the states of the individual children self.task_states = instance_state.get('task_states', []) # Overall state of the combined open ended module self.state = instance_state.get('state', self.INITIAL) self.student_attempts = instance_state.get('student_attempts', 0) self.weight = instance_state.get('weight', 1) # Allow reset is true if student has failed the criteria to move to the next child task self.ready_to_reset = instance_state.get('ready_to_reset', False) self.max_attempts = instance_state.get('max_attempts', MAX_ATTEMPTS) self.is_scored = instance_state.get('graded', IS_SCORED) in TRUE_DICT self.accept_file_upload = instance_state.get('accept_file_upload', ACCEPT_FILE_UPLOAD) in TRUE_DICT self.skip_basic_checks = instance_state.get('skip_spelling_checks', SKIP_BASIC_CHECKS) in TRUE_DICT if system.open_ended_grading_interface: self.peer_gs = PeerGradingService(system.open_ended_grading_interface, system) else: self.peer_gs = MockPeerGradingService() self.required_peer_grading = instance_state.get('required_peer_grading', 3) self.peer_grader_count = instance_state.get('peer_grader_count', 3) self.min_to_calibrate = instance_state.get('min_to_calibrate', 3) self.max_to_calibrate = instance_state.get('max_to_calibrate', 6) due_date = instance_state.get('due', None) grace_period_string = instance_state.get('graceperiod', None) try: self.timeinfo = TimeInfo(due_date, grace_period_string) except Exception: log.error("Error parsing due date information in location {0}".format(location)) raise self.display_due_date = self.timeinfo.display_due_date self.rubric_renderer = CombinedOpenEndedRubric(system, True) rubric_string = stringify_children(definition['rubric']) self._max_score = self.rubric_renderer.check_if_rubric_is_parseable(rubric_string, location, MAX_SCORE_ALLOWED) # Static data is passed to the child modules to render self.static_data = { 'max_score': self._max_score, 'max_attempts': self.max_attempts, 'prompt': definition['prompt'], 'rubric': definition['rubric'], 'display_name': self.display_name, 'accept_file_upload': self.accept_file_upload, 'close_date': self.timeinfo.close_date, 's3_interface': self.system.s3_interface, 'skip_basic_checks': self.skip_basic_checks, 'control': { 'required_peer_grading': self.required_peer_grading, 'peer_grader_count': self.peer_grader_count, 'min_to_calibrate': self.min_to_calibrate, 'max_to_calibrate': self.max_to_calibrate, } } self.task_xml = definition['task_xml'] self.location = location self.setup_next_task()