Commit 595f6a2f by Xavier Antoviaque

Merge pull request #70 from dragonfi/assessment-event-tracking

Assessment event tracking
parents 115817e9 a7c7b0e5
...@@ -76,7 +76,7 @@ class MentoringBlock(XBlockWithLightChildren): ...@@ -76,7 +76,7 @@ class MentoringBlock(XBlockWithLightChildren):
default=0, scope=Scope.user_state, enforce_type=True) default=0, scope=Scope.user_state, enforce_type=True)
max_attempts = Integer(help="Number of max attempts for this questions", default=0, max_attempts = Integer(help="Number of max attempts for this questions", default=0,
scope=Scope.content, enforce_type=True) scope=Scope.content, enforce_type=True)
mode = String(help="Mode of the mentoring. 'standard' or 'accessment'", mode = String(help="Mode of the mentoring. 'standard' or 'assessment'",
default='standard', scope=Scope.content) default='standard', scope=Scope.content)
step = Integer(help="Keep track of the student assessment progress.", step = Integer(help="Keep track of the student assessment progress.",
default=0, scope=Scope.user_state, enforce_type=True) default=0, scope=Scope.user_state, enforce_type=True)
...@@ -145,26 +145,20 @@ class MentoringBlock(XBlockWithLightChildren): ...@@ -145,26 +145,20 @@ class MentoringBlock(XBlockWithLightChildren):
@XBlock.json_handler @XBlock.json_handler
def publish_event(self, data, suffix=''): def publish_event(self, data, suffix=''):
try: try:
event_type = data.pop('event_type') event_type = data.pop('event_type')
except KeyError as e: except KeyError as e:
return {'result': 'error', 'message': 'Missing event_type in JSON data'} return {'result': 'error', 'message': 'Missing event_type in JSON data'}
self._publish_event(event_type, data)
def _publish_event(self, event_type, data):
data['user_id'] = self.scope_ids.user_id data['user_id'] = self.scope_ids.user_id
data['component_id'] = self._get_unique_id() data['component_id'] = self.url_name
self.runtime.publish(self, event_type, data) self.runtime.publish(self, event_type, data)
return {'result':'success'} return {'result':'success'}
def _get_unique_id(self):
try:
unique_id = self.location.name
except AttributeError:
# workaround for xblock workbench
unique_id = self.parent.replace('.', '-')
return unique_id
@property @property
def title(self): def title(self):
""" """
...@@ -251,9 +245,7 @@ class MentoringBlock(XBlockWithLightChildren): ...@@ -251,9 +245,7 @@ class MentoringBlock(XBlockWithLightChildren):
raw_score = self.score[0] raw_score = self.score[0]
self.runtime.publish(self, 'xblock.mentoring.submitted', { self._publish_event('xblock.mentoring.submitted', {
'user_id': self.scope_ids.user_id,
'component_id': self._get_unique_id(),
'num_attempts': self.num_attempts, 'num_attempts': self.num_attempts,
'submitted_answer': submissions, 'submitted_answer': submissions,
'grade': raw_score, 'grade': raw_score,
...@@ -297,6 +289,8 @@ class MentoringBlock(XBlockWithLightChildren): ...@@ -297,6 +289,8 @@ class MentoringBlock(XBlockWithLightChildren):
child.save() child.save()
completed = child_result['completed'] completed = child_result['completed']
event_data = {}
(raw_score, score, correct, incorrect) = self.score (raw_score, score, correct, incorrect) = self.score
if current_child == self.steps[-1]: if current_child == self.steps[-1]:
log.info(u'Last assessment step submitted: {}'.format(submissions)) log.info(u'Last assessment step submitted: {}'.format(submissions))
...@@ -306,10 +300,17 @@ class MentoringBlock(XBlockWithLightChildren): ...@@ -306,10 +300,17 @@ class MentoringBlock(XBlockWithLightChildren):
'max_value': 1, 'max_value': 1,
'score_type': 'proficiency', 'score_type': 'proficiency',
}) })
event_data['final_grade'] = raw_score
self.num_attempts += 1 self.num_attempts += 1
self.completed = True self.completed = True
event_data['exercise_id'] = current_child.name
event_data['num_attempts'] = self.num_attempts
event_data['submitted_answer'] = submissions
self._publish_event('xblock.mentoring.assessment.submitted', event_data)
return { return {
'completed': completed, 'completed': completed,
'attempted': self.attempted, 'attempted': self.attempted,
......
...@@ -99,6 +99,10 @@ function MentoringAssessmentView(runtime, element, mentoring) { ...@@ -99,6 +99,10 @@ function MentoringAssessmentView(runtime, element, mentoring) {
++active_child; ++active_child;
while (1) { while (1) {
var child = mentoring.displayChild(active_child, options); var child = mentoring.displayChild(active_child, options);
mentoring.publish_event({
event_type: 'xblock.mentoring.assessment.shown',
exercise_id: $(child).attr('name')
});
if ((typeof child !== 'undefined') || active_child == mentoring.children.length-1) if ((typeof child !== 'undefined') || active_child == mentoring.children.length-1)
break; break;
++active_child; ++active_child;
......
<mentoring url_name="{{ url_name }}" display_name="Nav tooltip title" weight="1" mode="assessment">
<title>Default Title</title>
<html>
<p>What is your goal?</p>
</html>
<answer name="goal" />
<mcq name="mcq_1_1" type="choices">
<question>Do you like this MCQ?</question>
<choice value="yes">Yes</choice>
<choice value="maybenot">Maybe not</choice>
<choice value="understand">I don't understand</choice>
</mcq>
<mcq name="mcq_1_2" type="rating" low="Not good at all" high="Extremely good">
<question>How much do you rate this MCQ?</question>
<choice value="notwant">I don't want to rate it</choice>
</mcq>
<mrq name="mrq_1_1" type="choices">
<question>What do you like in this MRQ?</question>
<choice value="elegance">Its elegance</choice>
<choice value="beauty">Its beauty</choice>
<choice value="gracefulness">Its gracefulness</choice>
<choice value="bugs">Its bugs</choice>
</mrq>
</mentoring>
...@@ -94,10 +94,11 @@ def get_scenarios_from_path(scenarios_path, include_identifier=False): ...@@ -94,10 +94,11 @@ def get_scenarios_from_path(scenarios_path, include_identifier=False):
identifier = template[:-4] identifier = template[:-4]
title = identifier.replace('_', ' ').title() title = identifier.replace('_', ' ').title()
template_path = os.path.join(scenarios_path, template) template_path = os.path.join(scenarios_path, template)
scenario = unicode(render_template(template_path, {"url_name": identifier}))
if not include_identifier: if not include_identifier:
scenarios.append((title, load_resource(template_path))) scenarios.append((title, scenario))
else: else:
scenarios.append((identifier, title, load_resource(template_path))) scenarios.append((identifier, title, scenario))
return scenarios return scenarios
......
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