Beispiel #1
0
    def student_view(self, context=None):
        """
        The primary view of the PeerInstructionXBlock, shown to students when viewing courses.
        """
        # convert key into integers as json.dump and json.load convert integer dictionary key into string
        self.sys_selected_answers = {int(k): v for k, v in self.sys_selected_answers.items()}

        # generate a random seed for student
        student_item = self.get_student_item_dict()
        random.seed(student_item['student_id'])

        answers = self.get_answers_for_student()
        html = ""
        html += self.resource_string("static/html/ubcpi.html")

        frag = Fragment(html)
        frag.add_css(self.resource_string("static/css/ubcpi.css"))
        frag.add_javascript_url("//ajax.googleapis.com/ajax/libs/angularjs/1.3.13/angular.js")
        frag.add_javascript_url("//ajax.googleapis.com/ajax/libs/angularjs/1.3.13/angular-messages.js")
        frag.add_javascript_url("//ajax.googleapis.com/ajax/libs/angularjs/1.3.13/angular-sanitize.js")
        frag.add_javascript_url("//ajax.googleapis.com/ajax/libs/angularjs/1.3.13/angular-cookies.js")
        frag.add_javascript_url("//cdnjs.cloudflare.com/ajax/libs/d3/3.3.13/d3.min.js")
        frag.add_javascript(self.resource_string("static/js/src/d3-pibar.js"))
        frag.add_javascript(self.resource_string("static/js/src/ubcpi.js"))
        frag.add_javascript(self.resource_string("static/js/src/ubcpi-answer-result-directive.js"))
        frag.add_javascript(self.resource_string("static/js/src/ubcpi-barchart-directive.js"))

        # convert image URLs
        question = deepcopy(self.question_text)
        question.update({'image_url': self.get_asset_url(question.get('image_url'))})

        options = deepcopy(self.options)
        for option in options:
            if option.get('image_url'):
                option.update({'image_url': self.get_asset_url(option.get('image_url'))})

        js_vals = {
            'answer_original': answers.get_vote(0),
            'rationale_original': answers.get_rationale(0),
            'answer_revised': answers.get_vote(1),
            'rationale_revised': answers.get_rationale(1),
            'display_name': self.display_name,
            'question_text': question,
            'options': options,
            'rationale_size': self.rationale_size,
            'all_status': {'NEW': STATUS_NEW, 'ANSWERED': STATUS_ANSWERED, 'REVISED': STATUS_REVISED},
        }
        if answers.has_revision(0) and not answers.has_revision(1):
            js_vals['other_answers'] = get_other_answers(
                self.sys_selected_answers, self.seeds, self.get_student_item_dict, self.algo, self.options)

        # reveal the correct answer in the end
        if answers.has_revision(1):
            js_vals['correct_answer'] = self.correct_answer
            js_vals['correct_rationale'] = self.correct_rationale

        # Pass the answer to out Javascript
        frag.initialize_js('PeerInstructionXBlock', js_vals)

        return frag
Beispiel #2
0
    def get_persisted_data(self):
        """
        Formats a usable dict based on what data the user has persisted
        Adds the other answers and correct answer/rationale when needed
        """
        answers = self.get_answers_for_student()
        ret = {
            "answer_original": answers.get_vote(0),
            "rationale_original": answers.get_rationale(0),
            "answer_revised": answers.get_vote(1),
            "rationale_revised": answers.get_rationale(1),
        }
        if answers.has_revision(0) and not answers.has_revision(1):
            ret['other_answers'] = get_other_answers(
                self.sys_selected_answers, self.seeds, self.get_student_item_dict, self.algo, self.options)

        # reveal the correct answer in the end
        if answers.has_revision(1):
            ret['correct_answer'] = self.correct_answer
            ret['correct_rationale'] = self.correct_rationale

        return ret
Beispiel #3
0
    def get_persisted_data(self):
        """
        Formats a usable dict based on what data the user has persisted
        Adds the other answers and correct answer/rationale when needed
        """
        answers = self.get_answers_for_student()
        ret = {
            "answer_original": answers.get_vote(0),
            "rationale_original": answers.get_rationale(0),
            "answer_revised": answers.get_vote(1),
            "rationale_revised": answers.get_rationale(1),
        }
        if answers.has_revision(0) and not answers.has_revision(1):
            ret['other_answers'] = get_other_answers(
                self.sys_selected_answers, self.seeds, self.get_student_item_dict, self.algo, self.options)

        # reveal the correct answer in the end
        if answers.has_revision(1):
            ret['correct_answer'] = self.correct_answer
            ret['correct_rationale'] = self.correct_rationale

        return ret
Beispiel #4
0
    def get_persisted_data(self, other_answers):
        """
        Formats a usable dict based on what data the user has persisted
        Adds the other answers and correct answer/rationale when needed
        """
        answers = self.get_answers_for_student()
        pool_count = get_other_answers_count(self.sys_selected_answers, self.seeds, self.get_student_item_dict)
        ret = {
            "answer_original": answers.get_vote(0),
            "rationale_original": answers.get_rationale(0),
            "answer_revised": answers.get_vote(1),
            "rationale_revised": answers.get_rationale(1),
        }
        if answers.has_revision(0) and not answers.has_revision(1):
            # If no persisted peer answers, generate new ones.
            # Could happen if a student completed Step 1 before ubcpi upgraded to persist peer answers.
            if not other_answers:
                ret['other_answers'] = get_other_answers(
                    self.sys_selected_answers, self.seeds, self.get_student_item_dict, self.algo, self.options)
            else:
                ret['other_answers'] = other_answers

            ret['alt_answers_available'] = {}
            # count how many answers we are showing for each option
            showing_count = {}
            for ans in ret['other_answers'].get('answers', []):
                if ans.get('option', None) is not None:
                    showing_count[ans['option']] = showing_count.get(ans['option'], 0) + 1
            for key in pool_count:
                ret['alt_answers_available'][key] = True if pool_count[key] > showing_count.get(key, 0) else False

        # reveal the correct answer in the end
        if answers.has_revision(1):
            ret['correct_answer'] = self.correct_answer
            ret['correct_rationale'] = self.correct_rationale

        return ret
Beispiel #5
0
    def submit_answer(self, data, suffix=''):
        """
        Answer submission handler to process the student answers
        """
        # convert key into integers as json.dump and json.load convert integer dictionary key into string
        self.sys_selected_answers = {int(k): v for k, v in self.sys_selected_answers.items()}
        self.record_response(data['q'], data['rationale'], data['status'])
        answers = self.get_answers_for_student()
        ret = {
            "answer_original": answers.get_vote(0),
            "rationale_original": answers.get_rationale(0),
            "answer_revised": answers.get_vote(1),
            "rationale_revised": answers.get_rationale(1),
        }
        if answers.has_revision(0) and not answers.has_revision(1):
            ret['other_answers'] = get_other_answers(
                self.sys_selected_answers, self.seeds, self.get_student_item_dict, self.algo, self.options)

        # reveal the correct answer in the end
        if answers.has_revision(1):
            ret['correct_answer'] = self.correct_answer
            ret['correct_rationale'] = self.correct_rationale

        return ret
Beispiel #6
0
    def record_response(self, answer, rationale, status):
        """
        Store response from student to the backend

        Args:
            answer (int): the option index that student responded
            rationale (str): the rationale text
            status (int): the progress status for this student. Possible values are:
                STATUS_NEW, STATUS_ANSWERED, STATUS_REVISED

        Raises:
            PermissionDenied: if we got an invalid status
        """
        answers = self.get_answers_for_student()
        stats = self.get_current_stats()
        truncated_rationale, was_truncated = truncate_rationale(rationale)
        corr_ans_text = ''
        if self.correct_answer == len(self.options):    # handle scenario with no correct answer
            corr_ans_text = 'n/a'
        else:
            corr_ans_text = self.options[self.correct_answer].get('text'),
        event_dict = {
            'answer': answer,
            'answer_text': self.options[answer].get('text'),
            'rationale': truncated_rationale,
            'correct_answer': self.correct_answer,
            'correct_answer_text': corr_ans_text,
            'correct_rationale': self.correct_rationale,
            'truncated': was_truncated
        }
        if not answers.has_revision(0) and status == STATUS_NEW:
            student_item = self.get_student_item_dict()
            sas_api.add_answer_for_student(student_item, answer, rationale)
            num_resp = stats['original'].setdefault(answer, 0)
            stats['original'][answer] = num_resp + 1
            offer_answer(
                self.sys_selected_answers, answer, rationale,
                student_item['student_id'], self.algo, self.options)
            self.other_answers_shown = get_other_answers(
                self.sys_selected_answers, self.seeds, self.get_student_item_dict, self.algo, self.options)
            event_dict['other_student_responses'] = self.other_answers_shown
            self.publish_event_from_dict(
                self.event_namespace + '.original_submitted',
                event_dict
            )
            return event_dict['other_student_responses']
        elif answers.has_revision(0) and not answers.has_revision(1) and status == STATUS_ANSWERED:
            sas_api.add_answer_for_student(self.get_student_item_dict(), answer, rationale)
            num_resp = stats['revised'].setdefault(answer, 0)
            stats['revised'][answer] = num_resp + 1

            # Fetch the grade
            grade = self.get_grade()

            # Send the grade
            self.runtime.publish(self, 'grade', {'value': grade, 'max_value': 1})

            self.publish_event_from_dict(
                    self.event_namespace + '.revised_submitted',
                    event_dict
            )
        else:
            raise PermissionDenied
Beispiel #7
0
    def student_view(self, context=None):
        """
        The primary view of the PeerInstructionXBlock, shown to students when viewing courses.
        """
        # convert key into integers as json.dump and json.load convert integer dictionary key into string
        self.sys_selected_answers = {int(k): v for k, v in self.sys_selected_answers.items()}

        # generate a random seed for student
        student_item = self.get_student_item_dict()
        random.seed(student_item['student_id'])

        answers = self.get_answers_for_student()
        html = ""
        html += self.resource_string("static/html/ubcpi.html")

        frag = Fragment(html)
        frag.add_css(self.resource_string("static/css/ubcpi.css"))
        frag.add_javascript_url("//ajax.googleapis.com/ajax/libs/angularjs/1.3.13/angular.js")
        frag.add_javascript_url("//ajax.googleapis.com/ajax/libs/angularjs/1.3.13/angular-messages.js")
        frag.add_javascript_url("//ajax.googleapis.com/ajax/libs/angularjs/1.3.13/angular-sanitize.js")
        frag.add_javascript_url("//ajax.googleapis.com/ajax/libs/angularjs/1.3.13/angular-cookies.js")
        frag.add_javascript_url("//cdnjs.cloudflare.com/ajax/libs/angular-gettext/2.3.8/angular-gettext.min.js")
        frag.add_javascript_url("//cdnjs.cloudflare.com/ajax/libs/d3/3.3.13/d3.min.js")
        frag.add_javascript(self.resource_string("static/js/src/d3-pibar.js"))
        frag.add_javascript(self.resource_string("static/js/src/ubcpi.js"))
        frag.add_javascript(self.resource_string("static/js/src/ubcpi-answer-result-directive.js"))
        frag.add_javascript(self.resource_string("static/js/src/ubcpi-barchart-directive.js"))
        frag.add_javascript(self.resource_string("static/js/src/translations.js"))

        # convert image URLs
        question = deepcopy(self.question_text)
        question.update({'image_url': self.get_asset_url(question.get('image_url'))})

        options = deepcopy(self.options)
        for option in options:
            if option.get('image_url'):
                option.update({'image_url': self.get_asset_url(option.get('image_url'))})

        js_vals = {
            'answer_original': answers.get_vote(0),
            'rationale_original': answers.get_rationale(0),
            'answer_revised': answers.get_vote(1),
            'rationale_revised': answers.get_rationale(1),
            'display_name': self.ugettext(self.display_name),
            'question_text': question,
            'weight': self.weight,
            'options': options,
            'rationale_size': self.rationale_size,
            'user_role': self.get_user_role(),
            'all_status': {'NEW': STATUS_NEW, 'ANSWERED': STATUS_ANSWERED, 'REVISED': STATUS_REVISED},
            'lang': translation.get_language(),
        }
        if answers.has_revision(0) and not answers.has_revision(1):
            js_vals['other_answers'] = get_other_answers(
                self.sys_selected_answers, self.seeds, self.get_student_item_dict, self.algo, self.options)

        # reveal the correct answer in the end
        if answers.has_revision(1):
            js_vals['correct_answer'] = self.correct_answer
            js_vals['correct_rationale'] = self.correct_rationale

        # Pass the answer to out Javascript
        frag.initialize_js('PeerInstructionXBlock', js_vals)

        self.publish_event_from_dict(self.event_namespace + '.accessed', {})

        return frag