Commit bc879077 by Tim Krones

Display score (percentage) and count of correct/partial/incorrect answers.

parent ca1e9f95
......@@ -869,6 +869,12 @@ class MentoringWithExplicitStepsBlock(BaseMentoringBlock, StudioContainerWithNes
""" Get the usage_ids of all of this XBlock's children that are "Questions" """
return list(chain.from_iterable(self.runtime.get_block(step_id).steps for step_id in self.steps))
def get_questions(self):
""" Get all questions associated with this block, cached if possible. """
if getattr(self, "_questions_cache", None) is None:
self._questions_cache = [self.runtime.get_block(question_id) for question_id in self.questions]
return self._questions_cache
@property
def steps(self):
"""
......@@ -880,6 +886,21 @@ class MentoringWithExplicitStepsBlock(BaseMentoringBlock, StudioContainerWithNes
child_isinstance(self, child_id, MentoringStepBlock)
]
def get_steps(self):
""" Get the step children of this block, cached if possible. """
if getattr(self, "_steps_cache", None) is None:
self._steps_cache = [self.runtime.get_block(child_id) for child_id in self.steps]
return self._steps_cache
def answer_mapper(self, answer_status):
steps = self.get_steps()
answer_map = []
for step in steps:
for answer in step.student_results:
if answer[1]['status'] == answer_status:
answer_map.append({'id': answer[0], 'details': answer[1]})
return answer_map
@property
def has_review_step(self):
from .step import ReviewStepBlock
......@@ -900,6 +921,27 @@ class MentoringWithExplicitStepsBlock(BaseMentoringBlock, StudioContainerWithNes
assessment_message = _("Note: you have used all attempts. Continue to the next unit")
return '<p>{}</p>'.format(assessment_message)
@property
def score(self):
questions = self.get_questions()
total_child_weight = sum(float(question.weight) for question in questions)
if total_child_weight == 0:
return Score(0, 0, [], [], [])
steps = self.get_steps()
questions_map = {question.name: question for question in questions}
points_earned = 0
for step in steps:
for question_name, question_results in step.student_results:
question = questions_map.get(question_name)
if question: # Under what conditions would this evaluate to False?
points_earned += question_results['score'] * question.weight
score = points_earned / total_child_weight
correct = self.answer_mapper(CORRECT)
incorrect = self.answer_mapper(INCORRECT)
partially_correct = self.answer_mapper(PARTIAL)
return Score(score, int(round(score * 100)), correct, incorrect, partially_correct)
def get_message_content(self, message_type, or_default=False):
for child_id in self.children:
if child_isinstance(self, child_id, MentoringMessageBlock):
......@@ -938,6 +980,7 @@ class MentoringWithExplicitStepsBlock(BaseMentoringBlock, StudioContainerWithNes
fragment.add_javascript_url(self.runtime.local_resource_url(self, 'public/js/mentoring_with_steps.js'))
fragment.add_resource(loader.load_unicode('templates/html/mentoring_attempts.html'), "text/html")
fragment.add_resource(loader.load_unicode('templates/html/mentoring_assessment_templates.html'), "text/html")
self.include_theme_files(fragment)
......@@ -986,6 +1029,15 @@ class MentoringWithExplicitStepsBlock(BaseMentoringBlock, StudioContainerWithNes
}
@XBlock.json_handler
def get_score(self, data, suffix):
return {
'score': self.score.percentage,
'correct_answers': len(self.score.correct),
'incorrect_answers': len(self.score.incorrect),
'partially_correct_answers': len(self.score.partially_correct),
}
@XBlock.json_handler
def try_again(self, data, suffix=''):
self.active_step = 0
......
......@@ -4,8 +4,10 @@ function MentoringWithStepsBlock(runtime, element) {
function(c) { return c.element.className.indexOf('sb-step') > -1; }
);
var activeStep = $('.mentoring', element).data('active-step');
var gradeTemplate = _.template($('#xblock-grade-template').html());
var attemptsTemplate = _.template($('#xblock-attempts-template').html());
var reviewStep, checkmark, submitDOM, nextDOM, reviewDOM, tryAgainDOM, assessmentMessageDOM, attemptsDOM, submitXHR;
var reviewStep, checkmark, submitDOM, nextDOM, reviewDOM, tryAgainDOM,
assessmentMessageDOM, gradeDOM, attemptsDOM, submitXHR;
function isLastStep() {
return (activeStep === steps.length-1);
......@@ -43,11 +45,25 @@ function MentoringWithStepsBlock(runtime, element) {
});
}
function updateGrade() {
var handlerUrl = runtime.handlerUrl(element, 'get_score');
$.post(handlerUrl, JSON.stringify({}))
.success(function(response) {
gradeDOM.data('score', response.score);
gradeDOM.data('correct_answer', response.correct_answers);
gradeDOM.data('incorrect_answer', response.incorrect_answers);
gradeDOM.data('partially_correct_answer', response.partially_correct_answers);
});
}
function handleResults(response) {
// Update active step so next step is shown on page reload (even if user does not click "Next Step")
updateActiveStep(activeStep+1);
if (response.update_attempts) {
// If step submitted was last step of this mentoring block, update grade and number of attempts used
if (response.attempt_complete) {
updateNumAttempts();
updateGrade();
}
// Update UI
......@@ -96,6 +112,7 @@ function MentoringWithStepsBlock(runtime, element) {
checkmark.removeClass('checkmark-incorrect icon-exclamation fa-exclamation');
hideAllSteps();
assessmentMessageDOM.html('');
gradeDOM.html('');
attemptsDOM.html('');
}
......@@ -117,12 +134,14 @@ function MentoringWithStepsBlock(runtime, element) {
}
function showAssessmentMessage() {
var data = $('.grade', element).data();
var data = gradeDOM.data();
assessmentMessageDOM.html(data.assessment_message);
}
function showReviewStep() {
reviewStep.show();
var data = gradeDOM.data();
gradeDOM.html(gradeTemplate(data));
submitDOM.hide();
nextDOM.hide();
reviewDOM.hide();
......@@ -226,6 +245,7 @@ function MentoringWithStepsBlock(runtime, element) {
tryAgainDOM.on('click', tryAgain);
assessmentMessageDOM = $('.assessment-message', element);
gradeDOM = $('.grade', element);
attemptsDOM = $('.attempts', element);
var options = {
......
......@@ -154,7 +154,7 @@ class MentoringStepBlock(
'message': 'Success!',
'completed': completed,
'results': submit_results,
'update_attempts': self.is_last_step
'attempt_complete': self.is_last_step
}
def reset(self):
......
......@@ -17,6 +17,10 @@
<div class="grade"
data-assessment_message="{{ self.assessment_message }}"
data-score="{{ self.score.percentage }}"
data-correct_answer="{{ self.score.correct|length }}"
data-incorrect_answer="{{ self.score.incorrect|length }}"
data-partially_correct_answer="{{ self.score.partially_correct|length }}">
</div>
<div class="submit">
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment