diff --git a/courseware/capa_module.py b/courseware/capa_module.py
index b829c9c305..7e5384feb3 100644
--- a/courseware/capa_module.py
+++ b/courseware/capa_module.py
@@ -4,26 +4,48 @@
import random, numpy, math, scipy, sys, StringIO, os, struct, json
from x_module import XModule
+from capa_problem import LoncapaProblem
+
from xml.dom.minidom import parse, parseString
-class LoncapaProblem(XModule):
+## TODO: Abstract out from Django
+from django.conf import settings
+from djangomako.shortcuts import render_to_response, render_to_string
+
+class LoncapaModule(XModule):
+ xml_tags=["problem"]
+ id_attribute="filename"
+
def get_state(self):
+ print "got"
+ return self.lcp.get_state()
def get_score(self):
+ return self.lcp.get_score()
def max_score(self):
+ return len(lcp.questions)
def get_html(self):
-
- def handle_ajax(self, json):
-
- def __init__(self, filename, id=None, state=None):
+ inner_html=self.lcp.get_html()
+ content={'name':self.name,
+ 'html':inner_html}
+ return render_to_string('problem.html',
+ {'problem':content, 'id':self.filename})
-if __name__=='__main__':
- p=LoncapaProblem('')
- print p.getHtml()
- print p.getContext()
- print p.getSeed()
- # Chef and puppot
+ def __init__(self, xml, item_id, ajax_url=None, track_url=None, state=None):
+ XModule.__init__(self, xml, item_id, ajax_url, track_url, state)
+ dom=parseString(xml)
+ node=dom.childNodes[0]
+ self.filename=node.getAttribute("filename")
+ filename=settings.DATA_DIR+self.filename+".xml"
+ self.name=node.getAttribute("name")
+ print state
+ self.lcp=LoncapaProblem(filename, item_id, state)
+
+ # Temporary
+
+ def check_problem(self, get):
+ pass
diff --git a/courseware/capa_problem.py b/courseware/capa_problem.py
index f17be7a62b..31162cc0da 100644
--- a/courseware/capa_problem.py
+++ b/courseware/capa_problem.py
@@ -26,16 +26,10 @@ class LoncapaProblem():
return {'score':correct,
'total':len(self.questions)}
- def max_score(self):
- pass
-
def get_html(self):
''' Return the HTML of the question '''
return self.text
- def handle_ajax(self, json):
- pass
-
def __init__(self, filename, id=None, state=None):
''' Create a new problem of the type defined in filename.
By default, this will generate a random problem. Passing
@@ -71,7 +65,7 @@ class LoncapaProblem():
ot=False ## Are we in an outtext context?
for e in dom.childNodes:
- if e.localName=='script' and context==None:
+ if e.localName=='script':
exec e.childNodes[0].data in g,self.context
if e.localName=='endouttext':
ot=False
@@ -85,7 +79,7 @@ class LoncapaProblem():
self.text=buf.getvalue()
self.text=self.contextualize_text(self.text)
-
+ self.filename=filename
text=""
context={} # Execution context from loncapa/python
diff --git a/courseware/content_parser.py b/courseware/content_parser.py
new file mode 100644
index 0000000000..83d597ab2c
--- /dev/null
+++ b/courseware/content_parser.py
@@ -0,0 +1,25 @@
+from django.conf import settings
+from xml.dom.minidom import parse, parseString
+
+
+def toc_from_xml(active_chapter,active_section):
+ dom=parse(settings.DATA_DIR+'course.xml')
+
+ course = dom.getElementsByTagName('course')[0]
+ name=course.getAttribute("name")
+ chapters = course.getElementsByTagName('chapter')
+ ch=list()
+ for c in chapters:
+ sections=list()
+ for s in c.getElementsByTagName('section'):
+ sections.append({'name':s.getAttribute("name"),
+ 'time':s.getAttribute("time"),
+ 'format':s.getAttribute("format"),
+ 'due':s.getAttribute("due"),
+ 'active':(c.getAttribute("name")==active_chapter and \
+ s.getAttribute("name")==active_section)})
+ ch.append({'name':c.getAttribute("name"),
+ 'sections':sections,
+ 'active':(c.getAttribute("name")==active_chapter)})
+ return ch
+
diff --git a/courseware/models.py b/courseware/models.py
index 3dbf7c46e3..867cfc06d1 100644
--- a/courseware/models.py
+++ b/courseware/models.py
@@ -44,10 +44,13 @@ class StudentModule(models.Model):
state = models.TextField(null=True, blank=True)
grade = models.FloatField(null=True, blank=True)
student = models.ForeignKey(User)
- MODULE_TYPES = (('hw','homework'),)
- module_type = models.CharField(max_length=32, choices=MODULE_TYPES, default='hw')
- module_id = models.CharField(max_length=255) # Filename
+ MODULE_TYPES = (('problem','problem'),)
+ module_type = models.CharField(max_length=32, choices=MODULE_TYPES, default='problem')
+ module_id = models.CharField(max_length=255) # Filename for homeworks, etc.
created = models.DateTimeField(auto_now_add=True)
modified = models.DateTimeField(auto_now=True)
class Meta:
- unique_together = (('student', 'module_id'),)
+ unique_together = (('student', 'module_id', 'module_type'),)
+
+ def __unicode__(self):
+ return self.module_type+'/'+self.student.username+"/"+self.module_id+'/'+str(self.state)[:20]
diff --git a/courseware/views.py b/courseware/views.py
index b5913b1982..416cf3f0ce 100644
--- a/courseware/views.py
+++ b/courseware/views.py
@@ -12,9 +12,11 @@ from django.shortcuts import redirect
import StringIO
+from django.http import Http404
+
import urllib
-import capa_problem
+import capa_module, capa_problem
from models import StudentModule
@@ -22,6 +24,8 @@ import urllib
from django.conf import settings
+from content_parser import *
+
template_imports={'urllib':urllib}
def profile(request):
@@ -49,9 +53,7 @@ def profile(request):
correct=response.grade
else:
correct=0
- # CRITICAL TODO: Benchmark, and probably cache. We shouldn't recalculate this
- # every time. By modularity, this also belongs inside LoncapaProblem.
- total=len(capa_problem.LoncapaProblem(settings.DATA_DIR+id+'.xml', id=id).questions)
+ total=capa_module.LoncapaModule(p, id=id).max_score()
scores.append((int(correct),total))
score={'course':course.getAttribute('name'),
'section':s.getAttribute("name"),
@@ -71,27 +73,6 @@ def profile(request):
}
return render_to_response('profile.html', context)
-def toc_from_xml(active_chapter,active_section):
- dom=parse(settings.DATA_DIR+'course.xml')
-
- course = dom.getElementsByTagName('course')[0]
- name=course.getAttribute("name")
- chapters = course.getElementsByTagName('chapter')
- ch=list()
- for c in chapters:
- sections=list()
- for s in c.getElementsByTagName('section'):
- sections.append({'name':s.getAttribute("name"),
- 'time':s.getAttribute("time"),
- 'format':s.getAttribute("format"),
- 'due':s.getAttribute("due"),
- 'active':(c.getAttribute("name")==active_chapter and \
- s.getAttribute("name")==active_section)})
- ch.append({'name':c.getAttribute("name"),
- 'sections':sections,
- 'active':(c.getAttribute("name")==active_chapter)})
- return ch
-
def render_accordion(request,course,chapter,section):
''' Draws accordion. Takes current position in accordion as
parameter. Returns (initialization_javascript, content)'''
@@ -138,28 +119,43 @@ def vertical_module(request, module):
return {'js':js,
'content':render_to_string('vert_module.html',{'items':contents})}
-def render_problem(request, filename):
+def render_x_module(request, xml_module):
# Check if problem has an instance in DB
- s = StudentModule.objects.filter(student=request.user, module_id=filename)
+ module_id=xml_module.getAttribute(capa_module.LoncapaModule.id_attribute)
+ s = StudentModule.objects.filter(student=request.user, module_id=module_id)
if len(s) == 0:
- # If not, create one, and return it
- problem=capa_problem.LoncapaProblem(settings.DATA_DIR+filename+'.xml', id=filename)
+ # If not, create one, and save it
+ problem=capa_module.LoncapaModule(xml_module.toxml(), module_id)
smod=StudentModule(student=request.user,
- module_id=filename,
+ module_id=module_id,
state=problem.get_state())
smod.save()
elif len(s) == 1:
# If so, render it
- problem=capa_problem.LoncapaProblem(settings.DATA_DIR+filename+'.xml',
- id=filename,
- state=s[0].state)
+ problem=capa_module.LoncapaModule(xml_module.toxml(),
+ module_id,
+ state=s[0].state)
else:
raise Exception("Database is inconsistent (1).")
-
- return problem.get_html()
-def reset_problem(request):
- s = StudentModule.objects.filter(student=request.user, module_id=request.GET['id'])
+ return {'content':problem.get_html()}
+
+def modx_dispatch(request, dispatch=None, id=None):
+ s = StudentModule.objects.filter(student=request.user, module_id=id)
+ if len(s) == 0:
+ raise Http404
+
+ if dispatch=='problem_check':
+ return check_problem(request)
+ elif dispatch=='problem_reset':
+ return reset_problem(request,id)
+ else:
+ print "AAA"
+ raise Http404
+
+
+def reset_problem(request,id):
+ s = StudentModule.objects.filter(student=request.user, module_id=id)
s[0].delete()
return HttpResponse(json.dumps({}), mimetype="application/json")
@@ -194,32 +190,11 @@ def check_problem(request):
return HttpResponse(js, mimetype="application/json")
-def problem_module(request, module):
- filename=module.getAttribute('filename')
- content={'name':module.getAttribute('name'),
- 'html':render_problem(request, filename)}
- return {'content':render_to_string('problem.html', {'problem':content, 'id':filename})}
-
-def homework_module(request, module):
- content={'name':module.getAttribute('name'),
- 'problems':[]}
- filename=module.getAttribute('filename')
- dom=parse(settings.DATA_DIR+filename)
- homework=dom.getElementsByTagName('homework')[0]
- for e in homework.childNodes:
- if e.nodeType==1:
- problem={'name':e.getAttribute('name'),
- 'html':render_problem(request, e.getAttribute('filename'))}
- content['problems'].append(problem)
-
- return {'content':render_to_string('homework.html', {'homework':content})}
-
module_types={'video':video_module,
'html':html_module,
'tab':tab_module,
'vertical':vertical_module,
- 'homework':homework_module,
- 'problem':problem_module}
+ 'problem':render_x_module}
#'lab':lab_module,
def render_module(request, module):
diff --git a/courseware/x_module.py b/courseware/x_module.py
index 7aedf0db1c..f9b1f5fac2 100644
--- a/courseware/x_module.py
+++ b/courseware/x_module.py
@@ -3,6 +3,14 @@ class XModule:
Initialized on access with __init__, first time with state=None, and
then with state
'''
+ def get_xml_tags():
+ ''' Tags in the courseware file guaranteed to correspond to the module '''
+ return []
+
+ def get_id_attribute():
+ ''' An attribute in the XML scheme that is guaranteed unique. '''
+ return "name"
+
def get_state(self):
return ""
diff --git a/urls.py b/urls.py
index 4748cb3bf1..808d383fd8 100644
--- a/urls.py
+++ b/urls.py
@@ -9,8 +9,8 @@ urlpatterns = patterns('',
url(r'^courseware/(?P[^/]*)/(?P[^/]*)/(?P[^/]*)/$', 'courseware.views.index'),
url(r'^courseware/(?P[^/]*)/(?P[^/]*)/$', 'courseware.views.index'),
url(r'^courseware/(?P[^/]*)/$', 'courseware.views.index'),
- url(r'^courseware/problem_check$', 'courseware.views.check_problem'),
- url(r'^courseware/problem_reset$', 'courseware.views.reset_problem'),
+# url(r'^courseware/modx/(?P[^/]*)/problem_check$', 'courseware.views.check_problem'),
+ url(r'^courseware/modx/(?P[^/]*)/(?P[^/]*)$', 'courseware.views.modx_dispatch'), #reset_problem'),
url(r'^courseware/$', 'courseware.views.index'),
url(r'^profile$', 'courseware.views.profile'),
# url(r'^admin/', include('django.contrib.admin.urls')),