Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions problem_builder/answer.py
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,9 @@ def get_results(self, previous_response=None):
'score': 1 if self.status == 'correct' else 0,
}

def get_last_result(self):
return self.get_results(None) if self.student_input else {}

def submit(self, submission):
"""
The parent block is handling a student submission, including a new answer for this
Expand Down
3 changes: 3 additions & 0 deletions problem_builder/mcq.py
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,9 @@ def calculate_results(self, submission):
def get_results(self, previous_result):
return self.calculate_results(previous_result['submission'])

def get_last_result(self):
return self.get_results({'submission': self.student_choice}) if self.student_choice else {}

def submit(self, submission):
log.debug(u'Received MCQ submission: "%s"', submission)
result = self.calculate_results(submission)
Expand Down
69 changes: 52 additions & 17 deletions problem_builder/mentoring.py
Original file line number Diff line number Diff line change
Expand Up @@ -435,6 +435,57 @@ def get_results(self, queries, suffix=''):
"""
Gets detailed results in the case of extended feedback.

Right now there are two ways to get results-- through the template upon loading up
the mentoring block, or after submission of an AJAX request like in
submit or get_results here.
"""
if self.mode == 'standard':
results, completed, show_message = self._get_standard_results()
mentoring_completed = completed
else:
if not self.show_extended_feedback():
return {
'results': [],
'error': 'Extended feedback results cannot be obtained.'
}

results, completed, show_message = self._get_assessment_results(queries)
mentoring_completed = True

result = {
'results': results,
'completed': completed,
'step': self.step,
'max_attempts': self.max_attempts,
'num_attempts': self.num_attempts,
}

if show_message:
result['message'] = self.get_message(mentoring_completed)

return result

def _get_standard_results(self):
"""
Gets previous submissions results as if submit was called with exactly the same values as last time.
"""
results = []
completed = True
show_message = bool(self.student_results)

# In standard mode, all children is visible simultaneously, so need collecting responses from all of them
for child_id in self.steps:
child = self.runtime.get_block(child_id)
child_result = child.get_last_result()
results.append([child.name, child_result])
completed = completed and (child_result.get('status', None) == 'correct')

return results, completed, show_message

def _get_assessment_results(self, queries):
"""
Gets detailed results in the case of extended feedback.

It may be a good idea to eventually have this function get results
in the general case instead of loading them in the template in the future,
and only using it for extended feedback situations.
Expand All @@ -444,14 +495,8 @@ def get_results(self, queries, suffix=''):
submit or get_results here.
"""
results = []
if not self.show_extended_feedback():
return {
'results': [],
'error': 'Extended feedback results cannot be obtained.'
}
completed = True
choices = dict(self.student_results)
step = self.step
# Only one child should ever be of concern with this method.
for child_id in self.steps:
child = self.runtime.get_block(child_id)
Expand All @@ -464,17 +509,7 @@ def get_results(self, queries, suffix=''):
completed = choices[child.name]['status']
break

# The 'completed' message should always be shown in this case, since no more attempts are available.
message = self.get_message(True)

return {
'results': results,
'completed': completed,
'message': message,
'step': step,
'max_attempts': self.max_attempts,
'num_attempts': self.num_attempts,
}
return results, completed, True

@XBlock.json_handler
def submit(self, submissions, suffix=''):
Expand Down
16 changes: 13 additions & 3 deletions problem_builder/mrq.py
Original file line number Diff line number Diff line change
Expand Up @@ -81,14 +81,20 @@ def describe_choice_correctness(self, choice_value):
return self._(u"Ignored")
return self._(u"Not Acceptable")

def get_results(self, previous_result):
def get_results(self, previous_result, only_selected=False):
"""
Get the results a student has already submitted.
"""
result = self.calculate_results(previous_result['submissions'])
result = self.calculate_results(previous_result['submissions'], only_selected)
result['completed'] = True
return result

def get_last_result(self):
if self.student_choices:
return self.get_results({'submissions': self.student_choices}, only_selected=True)
else:
return {}

def submit(self, submissions):
log.debug(u'Received MRQ submissions: "%s"', submissions)

Expand All @@ -98,13 +104,17 @@ def submit(self, submissions):
log.debug(u'MRQ submissions result: %s', result)
return result

def calculate_results(self, submissions):
def calculate_results(self, submissions, only_selected=False):
score = 0
results = []

for choice in self.custom_choices:
choice_completed = True
choice_tips_html = []
choice_selected = choice.value in submissions
if not choice_selected and only_selected:
continue

if choice.value in self.required_choices:
if not choice_selected:
choice_completed = False
Expand Down
13 changes: 7 additions & 6 deletions problem_builder/public/js/answer.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,12 +31,13 @@ function AnswerBlock(runtime, element) {
// Display of checkmark would be redundant.
return
}

if (result.status === "correct") {
checkmark.addClass('checkmark-correct icon-ok fa-check');
}
else {
checkmark.addClass('checkmark-incorrect icon-exclamation fa-exclamation');
if (result.status) {
if (result.status === "correct") {
checkmark.addClass('checkmark-correct icon-ok fa-check');
}
else {
checkmark.addClass('checkmark-incorrect icon-exclamation fa-exclamation');
}
}
},

Expand Down
19 changes: 13 additions & 6 deletions problem_builder/public/js/mentoring_standard_view.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,6 @@ function MentoringStandardView(runtime, element, mentoring) {
messagesDOM.prepend('<div class="title1">' + gettext('Feedback') + '</div>');
messagesDOM.show();
}

submitDOM.attr('disabled', 'disabled');
}

function handleSubmitError(jqXHR, textStatus, errorThrown) {
Expand All @@ -45,12 +43,10 @@ function MentoringStandardView(runtime, element, mentoring) {

mentoring.setContent(messagesDOM, errMsg);
messagesDOM.show();

submitDOM.attr('disabled', 'disabled');
}
}

function calculate_results(handler_name) {
function calculate_results(handler_name, disable_submit) {
var data = {};
var children = mentoring.children;
for (var i = 0; i < children.length; i++) {
Expand All @@ -64,10 +60,19 @@ function MentoringStandardView(runtime, element, mentoring) {
submitXHR.abort();
}
submitXHR = $.post(handlerUrl, JSON.stringify(data)).success(handleSubmitResults).error(handleSubmitError);

if (disable_submit) {
var disable_submit_callback = function(){ submitDOM.attr('disabled', 'disabled'); };
submitXHR.success(disable_submit_callback).error(disable_submit_callback);
}
}

function get_results(){
calculate_results('get_results', false);
}

function submit() {
calculate_results('submit');
calculate_results('submit', true);
}

function clearResults() {
Expand Down Expand Up @@ -97,6 +102,8 @@ function MentoringStandardView(runtime, element, mentoring) {
mentoring.initChildren(options);
mentoring.renderDependency();

get_results();

var submitPossible = submitDOM.length > 0;
if (submitPossible) {
mentoring.renderAttempts();
Expand Down
7 changes: 7 additions & 0 deletions problem_builder/tests/integration/base_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,13 @@ def click_submit(self, mentoring):
submit.click()
self.wait_until_disabled(submit)

def click_choice(self, container, choice_text):
""" Click on the choice label with the specified text """
for label in container.find_elements_by_css_selector('.choice label'):
if choice_text in label.text:
label.click()
break


class MentoringBaseTest(SeleniumBaseTest, PopupCheckMixin):
module_name = __name__
Expand Down
Loading