Exemple #1
0
 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
Exemple #3
0
    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()