Commit fa39e969 by Bridger Maxwell

Merge

parents d47d95ed 9619bf20
...@@ -108,8 +108,8 @@ class LoncapaModule(XModule): ...@@ -108,8 +108,8 @@ class LoncapaModule(XModule):
return html return html
def __init__(self, xml, item_id, ajax_url=None, track_url=None, state=None): def __init__(self, xml, item_id, ajax_url=None, track_url=None, state=None, track_function=None):
XModule.__init__(self, xml, item_id, ajax_url, track_url, state) XModule.__init__(self, xml, item_id, ajax_url, track_url, state, track_function)
self.attempts = 0 self.attempts = 0
self.max_attempts = None self.max_attempts = None
...@@ -222,22 +222,32 @@ class LoncapaModule(XModule): ...@@ -222,22 +222,32 @@ class LoncapaModule(XModule):
def check_problem(self, get): def check_problem(self, get):
''' Checks whether answers to a problem are correct, and ''' Checks whether answers to a problem are correct, and
returns a map of correct/incorrect answers''' returns a map of correct/incorrect answers'''
event_info = dict()
event_info['state'] = self.lcp.get_state()
event_info['filename'] = self.filename
answers=dict()
# input_resistor_1 ==> resistor_1
for key in get:
answers['_'.join(key.split('_')[1:])]=get[key]
event_info['answers']=answers
# Too late. Cannot submit # Too late. Cannot submit
if self.closed(): if self.closed():
event_info['failure']='closed'
self.tracker('save_problem_check_fail', event_info)
print "cp" print "cp"
raise Http404 raise Http404
# Problem submitted. Student should reset before checking # Problem submitted. Student should reset before checking
# again. # again.
if self.lcp.done and self.rerandomize: if self.lcp.done and self.rerandomize:
event_info['failure']='unreset'
self.tracker('save_problem_check_fail', event_info)
print "cpdr" print "cpdr"
raise Http404 raise Http404
answers=dict()
# input_resistor_1 ==> resistor_1
for key in get:
answers['_'.join(key.split('_')[1:])]=get[key]
try: try:
old_state = self.lcp.get_state() old_state = self.lcp.get_state()
lcp_id = self.lcp.problem_id lcp_id = self.lcp.problem_id
...@@ -262,35 +272,56 @@ class LoncapaModule(XModule): ...@@ -262,35 +272,56 @@ class LoncapaModule(XModule):
js=json.dumps({'correct_map' : correct_map, js=json.dumps({'correct_map' : correct_map,
'success' : success}) 'success' : success})
event_info['correct_map']=correct_map
event_info['success']=success
self.tracker('save_problem_check', event_info)
return js return js
def save_problem(self, get): def save_problem(self, get):
event_info = dict()
event_info['state'] = self.lcp.get_state()
event_info['filename'] = self.filename
answers=dict()
for key in get:
answers['_'.join(key.split('_')[1:])]=get[key]
event_info['answers'] = answers
# Too late. Cannot submit # Too late. Cannot submit
if self.closed(): if self.closed():
print "sp" event_info['failure']='closed'
self.tracker('save_problem_fail', event_info)
return "Problem is closed" return "Problem is closed"
# Problem submitted. Student should reset before saving # Problem submitted. Student should reset before saving
# again. # again.
if self.lcp.done and self.rerandomize: if self.lcp.done and self.rerandomize:
print "spdr" event_info['failure']='done'
self.tracker('save_problem_fail', event_info)
return "Problem needs to be reset prior to save." return "Problem needs to be reset prior to save."
answers=dict()
for key in get:
answers['_'.join(key.split('_')[1:])]=get[key]
self.lcp.student_answers=answers self.lcp.student_answers=answers
self.tracker('save_problem_fail', event_info)
return json.dumps({'success':True}) return json.dumps({'success':True})
def reset_problem(self, get): def reset_problem(self, get):
''' Changes problem state to unfinished -- removes student answers, ''' Changes problem state to unfinished -- removes student answers,
and causes problem to rerender itself. ''' and causes problem to rerender itself. '''
event_info = dict()
event_info['old_state']=self.lcp.get_state()
event_info['filename']=self.filename
if self.closed(): if self.closed():
event_info['failure']='closed'
self.tracker('reset_problem_fail', event_info)
return "Problem is closed" return "Problem is closed"
if not self.lcp.done: if not self.lcp.done:
event_info['failure']='not_done'
self.tracker('reset_problem_fail', event_info)
return "Refresh the page and make an attempt before resetting." return "Refresh the page and make an attempt before resetting."
self.lcp.done=False self.lcp.done=False
...@@ -307,8 +338,7 @@ class LoncapaModule(XModule): ...@@ -307,8 +338,7 @@ class LoncapaModule(XModule):
filename=settings.DATA_DIR+"problems/"+self.filename+".xml" filename=settings.DATA_DIR+"problems/"+self.filename+".xml"
self.lcp=LoncapaProblem(filename, self.item_id, self.lcp.get_state()) self.lcp=LoncapaProblem(filename, self.item_id, self.lcp.get_state())
event_info = self.lcp.get_state() event_info['new_state']=self.lcp.get_state()
event_info.update({'filename':filename}) self.tracker('reset_problem', event_info)
#server_track(request, 'reset_problem', event_info)
return json.dumps(self.get_problem_html(encapsulate=False)) return json.dumps(self.get_problem_html(encapsulate=False))
...@@ -25,8 +25,8 @@ class HtmlModule(XModule): ...@@ -25,8 +25,8 @@ class HtmlModule(XModule):
textlist=[i for i in textlist if type(i)==str] textlist=[i for i in textlist if type(i)==str]
return "".join(textlist) return "".join(textlist)
def __init__(self, xml, item_id, ajax_url=None, track_url=None, state=None): def __init__(self, xml, item_id, ajax_url=None, track_url=None, state=None, track_function=None):
XModule.__init__(self, xml, item_id, ajax_url, track_url, state) XModule.__init__(self, xml, item_id, ajax_url, track_url, state, track_function)
xmltree=etree.fromstring(xml) xmltree=etree.fromstring(xml)
self.filename = None self.filename = None
filename_l=xmltree.xpath("/html/@filename") filename_l=xmltree.xpath("/html/@filename")
......
...@@ -10,6 +10,7 @@ from auth.models import UserProfile ...@@ -10,6 +10,7 @@ from auth.models import UserProfile
from django.shortcuts import redirect from django.shortcuts import redirect
import StringIO import StringIO
import track.views
from django.http import Http404 from django.http import Http404
...@@ -35,6 +36,11 @@ modx_modules={'problem':capa_module.LoncapaModule, ...@@ -35,6 +36,11 @@ modx_modules={'problem':capa_module.LoncapaModule,
'html':html_module.HtmlModule, 'html':html_module.HtmlModule,
'schematic':schematic_module.SchematicModule} 'schematic':schematic_module.SchematicModule}
def make_track_function(request):
def f(event_type, event):
return track.views.server_track(request, event_type, event, page='x_module')
return f
def modx_dispatch(request, module=None, dispatch=None, id=None): def modx_dispatch(request, module=None, dispatch=None, id=None):
''' Generic view for extensions. ''' ''' Generic view for extensions. '''
# Grab the student information for the module from the database # Grab the student information for the module from the database
...@@ -60,7 +66,8 @@ def modx_dispatch(request, module=None, dispatch=None, id=None): ...@@ -60,7 +66,8 @@ def modx_dispatch(request, module=None, dispatch=None, id=None):
instance=modx_modules[module](xml, instance=modx_modules[module](xml,
s.module_id, s.module_id,
ajax_url=ajax_url, ajax_url=ajax_url,
state=s.state) state=s.state,
track_function = make_track_function(request))
# Let the module handle the AJAX # Let the module handle the AJAX
ajax_return=instance.handle_ajax(dispatch, request.POST) ajax_return=instance.handle_ajax(dispatch, request.POST)
# Save the state back to the database # Save the state back to the database
...@@ -153,7 +160,8 @@ def render_x_module(request, xml_module): ...@@ -153,7 +160,8 @@ def render_x_module(request, xml_module):
instance=module_class(xml_module.toxml(), instance=module_class(xml_module.toxml(),
module_id, module_id,
ajax_url=ajax_url, ajax_url=ajax_url,
state=state) state=state,
track_function = make_track_function(request))
# If instance wasn't already in the database, create it # If instance wasn't already in the database, create it
if len(s) == 0: if len(s) == 0:
......
...@@ -46,8 +46,8 @@ class VideoModule(XModule): ...@@ -46,8 +46,8 @@ class VideoModule(XModule):
def get_destroy_js(self): def get_destroy_js(self):
return "videoDestroy();" return "videoDestroy();"
def __init__(self, xml, item_id, ajax_url=None, track_url=None, state=None): def __init__(self, xml, item_id, ajax_url=None, track_url=None, state=None, track_function=None):
XModule.__init__(self, xml, item_id, ajax_url, track_url, state) XModule.__init__(self, xml, item_id, ajax_url, track_url, state, track_function)
print state print state
if state!=None and "time" not in json.loads(state): if state!=None and "time" not in json.loads(state):
self.video_time = 0 self.video_time = 0
def dummy_track(event_type, event):
pass
class XModule(object): class XModule(object):
''' Implements a generic learning module. ''' Implements a generic learning module.
Initialized on access with __init__, first time with state=None, and Initialized on access with __init__, first time with state=None, and
...@@ -36,10 +39,11 @@ class XModule(object): ...@@ -36,10 +39,11 @@ class XModule(object):
get is a dictionary-like object ''' get is a dictionary-like object '''
return "" return ""
def __init__(self, xml, item_id, ajax_url=None, track_url=None, state=None): def __init__(self, xml, item_id, ajax_url=None, track_url=None, state=None, track_function=None):
''' In most cases, you must pass state or xml''' ''' In most cases, you must pass state or xml'''
self.xml=xml self.xml=xml
self.item_id=item_id self.item_id=item_id
self.ajax_url=ajax_url self.ajax_url=ajax_url
self.track_url=track_url self.track_url=track_url
self.state=state self.state=state
self.tracker=track_function
...@@ -12,6 +12,7 @@ urlpatterns = ('', ...@@ -12,6 +12,7 @@ urlpatterns = ('',
url(r'^event$', 'track.views.user_track'), url(r'^event$', 'track.views.user_track'),
url(r'^t/(?P<template>[^/]*)$', 'static_template_view.views.index'), url(r'^t/(?P<template>[^/]*)$', 'static_template_view.views.index'),
url(r'^logout$', 'auth.views.logout_user'), url(r'^logout$', 'auth.views.logout_user'),
url(r'^info$', 'util.views.info'),
url(r'^login$', 'auth.views.login_user'), url(r'^login$', 'auth.views.login_user'),
url(r'^login/(?P<error>[^/]*)$', 'auth.views.login_user'), url(r'^login/(?P<error>[^/]*)$', 'auth.views.login_user'),
url(r'^create_account$', 'auth.views.create_account'), url(r'^create_account$', 'auth.views.create_account'),
......
...@@ -48,3 +48,6 @@ def send_feedback(request): ...@@ -48,3 +48,6 @@ def send_feedback(request):
fail_silently = False fail_silently = False
) )
return HttpResponse(json.dumps({'success':True})) return HttpResponse(json.dumps({'success':True}))
def info(request):
return render_to_response("info.html", {})
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