Commit a3c5bffd by Sven Marnach

Add grading functionality.

parent d872ded2
......@@ -71,15 +71,32 @@ class ActiveTableXBlock(StudioEditableXBlockMixin, XBlock):
scope=Scope.content,
default=1.0,
)
max_score = Float(
display_name='Maximum score',
help='The number of points students will be awarded when solving all fields correctly. '
'For partially correct attempts, the score will be pro-rated.',
scope=Scope.settings,
default=1.0,
)
editable_fields = [
'table_definition', 'help_text', 'column_widths', 'row_heights', 'default_tolerance'
'display_name',
'table_definition',
'help_text',
'column_widths',
'row_heights',
'default_tolerance',
'max_score',
]
# Dictionary mapping cell ids to the student answers.
answers = Dict(scope=Scope.user_state)
# Number of correct answers.
num_correct_answers = Integer(scope=Scope.user_state)
# The number of points awarded.
score = Float(scope=Scope.user_state)
has_score = True
def __init__(self, *args, **kwargs):
super(ActiveTableXBlock, self).__init__(*args, **kwargs)
......@@ -152,6 +169,8 @@ class ActiveTableXBlock(StudioEditableXBlockMixin, XBlock):
frag.initialize_js('ActiveTableXBlock', dict(
num_correct_answers=self.num_correct_answers,
num_total_answers=len(self.answers) if self.answers is not None else None,
score=self.score,
max_score=self.max_score,
))
return frag
......@@ -161,15 +180,23 @@ class ActiveTableXBlock(StudioEditableXBlockMixin, XBlock):
This handler is called when the "Check" button is clicked.
"""
correct_dict = {
correct = {
cell_id: self.response_cells[cell_id].check_response(value)
for cell_id, value in data.iteritems()
}
# Since the previous statement executed without error, the data is well-formed enough to be
# stored. We now know it's a dictionary and all the keys are valid cell ids.
self.answers = data
self.num_correct_answers = sum(correct_dict.itervalues())
return correct_dict
self.num_correct_answers = sum(correct.itervalues())
self.score = self.num_correct_answers * self.max_score / len(correct)
self.runtime.publish(self, 'grade', dict(value=self.score, max_value=self.max_score))
return dict(
correct=correct,
num_correct_answers=self.num_correct_answers,
num_total_answers=len(correct),
score=self.score,
max_score=self.max_score,
)
def validate_field_data(self, validation, data):
"""Validate the data entered by the user.
......
......@@ -3,25 +3,25 @@ function ActiveTableXBlock(runtime, element, init_args) {
var checkHandlerUrl = runtime.handlerUrl(element, 'check_answers');
function updateStatus(num_total, num_correct) {
function updateStatus(data) {
var $status = $('.status', element);
var $status_message = $('.status-message', element);
if (num_total == num_correct) {
if (data.num_total_answers == data.num_correct_answers) {
$status.removeClass('incorrect').addClass('correct');
$status.text('correct');
$status_message.text('Great job!');
$status_message.text('Great job! (' + data.score + '/' + data.max_score + ' points)');
} else {
$status.removeClass('correct').addClass('incorrect');
$status.text('incorrect');
$status_message.text(
'You have ' + num_correct + ' out of ' + num_total + ' cells correct.'
'You have ' + data.num_correct_answers + ' out of ' + data.num_total_answers +
' cells correct. (' + data.score + '/' + data.max_score + ' points)'
);
}
}
function markResponseCells(correct_dict) {
var num_total = 0, num_correct = 0;
$.each(correct_dict, function(cell_id, correct) {
function markResponseCells(data) {
$.each(data.correct, function(cell_id, correct) {
var $cell = $('#' + cell_id, element);
$cell.removeClass('right-answer wrong-answer unchecked');
if (correct) {
......@@ -31,10 +31,8 @@ function ActiveTableXBlock(runtime, element, init_args) {
$cell.addClass('wrong-answer');
$cell.prop('title', 'incorrect');
}
num_total += 1;
num_correct += correct;
});
updateStatus(num_total, num_correct);
updateStatus(data);
}
function checkAnswers(e) {
......@@ -58,7 +56,5 @@ function ActiveTableXBlock(runtime, element, init_args) {
$('#activetable-help-button', element).click(toggleHelp);
$('.action .check', element).click(checkAnswers);
if (init_args.num_total_answers) {
updateStatus(init_args.num_total_answers, init_args.num_correct_answers);
}
if (init_args.num_total_answers) updateStatus(init_args);
}
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