Commit 9ac4ac8a by Piotr Mitros

Minor layout fixes, basic schematic entry support, XPath for XML

parent 61880f5a
...@@ -76,15 +76,12 @@ class LoncapaProblem(): ...@@ -76,15 +76,12 @@ class LoncapaProblem():
# Loop through the nodes of the problem, and # Loop through the nodes of the problem, and
for e in dom.childNodes: for e in dom.childNodes:
# print e, ot
#
if e.localName=='script': if e.localName=='script':
#print e.childNodes[0].data #print e.childNodes[0].data
exec e.childNodes[0].data in g,self.context exec e.childNodes[0].data in g,self.context
elif e.localName=='endouttext': elif e.localName=='endouttext':
ot=False ot=False
elif ot: elif ot:
# print e, "::", e.toxml()
e.writexml(buf) e.writexml(buf)
elif e.localName=='startouttext': elif e.localName=='startouttext':
ot=True ot=True
...@@ -98,7 +95,6 @@ class LoncapaProblem(): ...@@ -98,7 +95,6 @@ class LoncapaProblem():
self.text=buf.getvalue() self.text=buf.getvalue()
self.text=self.contextualize_text(self.text) self.text=self.contextualize_text(self.text)
# print self.text
self.filename=filename self.filename=filename
done=False done=False
...@@ -134,8 +130,6 @@ class LoncapaProblem(): ...@@ -134,8 +130,6 @@ class LoncapaProblem():
if id not in answers: if id not in answers:
correct_map[id]='incorrect' # Should always be there correct_map[id]='incorrect' # Should always be there
else: else:
#correct_map[id]=self.grade_nr(self.questions[key],
# self.answers[id])
grader=self.graders[self.questions[key]['type']] grader=self.graders[self.questions[key]['type']]
print grader print grader
correct_map[id]=grader(self, self.questions[key], correct_map[id]=grader(self, self.questions[key],
...@@ -143,22 +137,20 @@ class LoncapaProblem(): ...@@ -143,22 +137,20 @@ class LoncapaProblem():
self.correct_map=correct_map self.correct_map=correct_map
return correct_map return correct_map
def handle_schem(self, element):
height = 480
width = 640
self.lid+=1
id=str(self.gid)+'_'+str(self.lid)
html='<input type="hidden" class="schematic" name="{id}" '+ \
'height="{height}" width="{width}" value="{value}">'
return html.format(height=height, width=width, id=id, value="")
def grade_schem(self, element):
return "correct"
## Internal methods
# def number(self,text):
# ''' Convert a number to a float, understanding suffixes '''
# try:
# text.strip()
# suffixes={'%':0.01,'k':1e3,'M':1e6,'G':1e9,'T':1e12,'P':1e15,
# 'E':1e18,'Z':1e21,'Y':1e24,'c':1e-2,'m':1e-3,'u':1e-6,
# 'n':1e-9,'p':1e-12,'f':1e-15,'a':1e-18,'z':1e-21,'y':1e-24}
# if text[-1] in suffixes:
# return float(text[:-1])*suffixes[text[-1]]
# else:
# return float(text)
# except:
# return 0 # TODO: Better error handling?
def grade_nr(self, question, answer): def grade_nr(self, question, answer):
error = abs(evaluator({},{},answer) - question['answer']) error = abs(evaluator({},{},answer) - question['answer'])
...@@ -255,9 +247,11 @@ class LoncapaProblem(): ...@@ -255,9 +247,11 @@ class LoncapaProblem():
return html return html
graders={'numericalresponse':grade_nr, graders={'numericalresponse':grade_nr,
'formularesponse':grade_fr} 'formularesponse':grade_fr,
'schematicresponse':grade_schem}
handlers={'numericalresponse':handle_nr, handlers={'numericalresponse':handle_nr,
'formularesponse':handle_fr} 'formularesponse':handle_fr,
'schematicresponse':handle_schem}
def contextualize_text(self, text): def contextualize_text(self, text):
''' Takes a string with variables. E.g. $a+$b. ''' Takes a string with variables. E.g. $a+$b.
......
from django.conf import settings from django.conf import settings
from xml.dom.minidom import parse, parseString from xml.dom.minidom import parse, parseString
import libxml2
''' This file will eventually form an abstraction layer between the ''' This file will eventually form an abstraction layer between the
course XML file and the rest of the system. course XML file and the rest of the system.
TODO: Shift everything from xml.dom.minidom to XPath (or XQuery)
''' '''
def module_xml(module, id_tag, module_id):
''' Get XML for a module based on module and module_id. Assumes
module occurs once in course.xml. '''
doc = libxml2.parseFile(settings.DATA_DIR+'course.xml')
# Sanitize input
if not module.isalnum():
raise Exception("Module is not alphanumeric")
if not module_id.isalnum():
raise Exception("Module ID is not alphanumeric")
xpath_search='//*/{module}[@{id_tag} = "{id}"]'.format(module=module,
id_tag=id_tag,
id=module_id)
result_set=doc.xpathEval(xpath_search)
if len(result_set)>1:
print "WARNING: Potentially malformed course file", module, module_id
if len(result_set)==0:
return None
return result_set[0].serialize()
def toc_from_xml(active_chapter,active_section): def toc_from_xml(active_chapter,active_section):
dom=parse(settings.DATA_DIR+'course.xml') dom=parse(settings.DATA_DIR+'course.xml')
......
...@@ -18,7 +18,6 @@ class HtmlModule(XModule): ...@@ -18,7 +18,6 @@ class HtmlModule(XModule):
return "html" return "html"
def get_html(self): def get_html(self):
print "XX",self.item_id
return render_to_string(self.item_id, {'id': self.item_id}) return render_to_string(self.item_id, {'id': self.item_id})
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):
......
...@@ -52,7 +52,6 @@ class StudentModule(models.Model): ...@@ -52,7 +52,6 @@ class StudentModule(models.Model):
module_id = models.CharField(max_length=255) # Filename for homeworks, etc. module_id = models.CharField(max_length=255) # Filename for homeworks, etc.
created = models.DateTimeField(auto_now_add=True) created = models.DateTimeField(auto_now_add=True)
modified = models.DateTimeField(auto_now=True) modified = models.DateTimeField(auto_now=True)
xml = models.TextField(blank=True)
class Meta: class Meta:
unique_together = (('student', 'module_id', 'module_type'),) unique_together = (('student', 'module_id', 'module_type'),)
......
...@@ -19,6 +19,7 @@ import urllib ...@@ -19,6 +19,7 @@ import urllib
import capa_module import capa_module
import video_module import video_module
import html_module import html_module
import schematic_module
from models import StudentModule from models import StudentModule
...@@ -30,12 +31,6 @@ import content_parser ...@@ -30,12 +31,6 @@ import content_parser
import uuid import uuid
#def html_module(request, module):
# ''' Show basic text
# '''
# template_source=module.getAttribute('filename')
# return {'content':render_to_string(template_source, {})}
def vertical_module(request, module): def vertical_module(request, module):
''' Layout module which lays out content vertically. ''' Layout module which lays out content vertically.
''' '''
...@@ -86,7 +81,8 @@ def seq_module(request, module): ...@@ -86,7 +81,8 @@ def seq_module(request, module):
modx_modules={'problem':capa_module.LoncapaModule, modx_modules={'problem':capa_module.LoncapaModule,
'video':video_module.VideoModule, 'video':video_module.VideoModule,
'html':html_module.HtmlModule} 'html':html_module.HtmlModule,
'schematic':schematic_module.SchematicModule}
def render_x_module(request, xml_module): def render_x_module(request, xml_module):
''' Generic module for extensions. This renders to HTML. ''' ''' Generic module for extensions. This renders to HTML. '''
...@@ -117,8 +113,7 @@ def render_x_module(request, xml_module): ...@@ -117,8 +113,7 @@ def render_x_module(request, xml_module):
smod=StudentModule(student=request.user, smod=StudentModule(student=request.user,
module_type = module_type, module_type = module_type,
module_id=module_id, module_id=module_id,
state=instance.get_state(), state=instance.get_state())
xml=instance.xml)
# Grab content # Grab content
content = {'content':instance.get_html(), content = {'content':instance.get_html(),
"destroy_js":instance.get_destroy_js(), "destroy_js":instance.get_destroy_js(),
...@@ -130,8 +125,11 @@ def render_x_module(request, xml_module): ...@@ -130,8 +125,11 @@ def render_x_module(request, xml_module):
def modx_dispatch(request, module=None, dispatch=None, id=None): def modx_dispatch(request, module=None, dispatch=None, id=None):
''' Generic module for extensions. ''' ''' Generic module for extensions. '''
s = StudentModule.objects.filter(module_type=module, student=request.user, module_id=id) s = StudentModule.objects.filter(module_type=module,
student=request.user,
module_id=id)
if len(s) == 0: if len(s) == 0:
print "ls404"
raise Http404 raise Http404
s=s[0] s=s[0]
...@@ -140,7 +138,16 @@ def modx_dispatch(request, module=None, dispatch=None, id=None): ...@@ -140,7 +138,16 @@ def modx_dispatch(request, module=None, dispatch=None, id=None):
ajax_url = '/modx/'+module+'/'+id+'/' ajax_url = '/modx/'+module+'/'+id+'/'
instance=modx_modules[module](s.xml, s.module_id, ajax_url=ajax_url, state=s.state) id_tag=modx_modules[module].id_attribute
#print "X",s.xml, "Y",content_parser.module_xml(module, id_tag, id)
print
xml = content_parser.module_xml(module, id_tag, id)
instance=modx_modules[module](xml,
s.module_id,
ajax_url=ajax_url,
state=s.state)
html=instance.handle_ajax(dispatch, request.GET) html=instance.handle_ajax(dispatch, request.GET)
s.state=instance.get_state() s.state=instance.get_state()
s.grade=instance.get_score()['score'] s.grade=instance.get_score()['score']
...@@ -153,8 +160,8 @@ module_types={'video':render_x_module, ...@@ -153,8 +160,8 @@ module_types={'video':render_x_module,
'vertical':vertical_module, 'vertical':vertical_module,
'sequential':seq_module, 'sequential':seq_module,
'problem':render_x_module, 'problem':render_x_module,
'schematic':render_x_module
} }
#'lab':lab_module,
def render_module(request, module): def render_module(request, module):
''' Generic dispatch for internal modules. ''' ''' Generic dispatch for internal modules. '''
...@@ -162,4 +169,5 @@ def render_module(request, module): ...@@ -162,4 +169,5 @@ def render_module(request, module):
return {"content":""} return {"content":""}
if str(module.localName) in module_types: if str(module.localName) in module_types:
return module_types[module.localName](request, module) return module_types[module.localName](request, module)
print "rm404"
raise Http404 raise Http404
from x_module import XModule
from xml.dom.minidom import parse, parseString
import json
## TODO: Abstract out from Django
from django.conf import settings
from djangomako.shortcuts import render_to_response, render_to_string
class SchematicModule(XModule):
id_attribute = 'id'
def get_state(self):
return json.dumps({ })
def get_xml_tags():
return "schematic"
def get_html(self):
return '<input type="hidden" class="schematic" name="{item_id}" height="480" width="640">'.format(item_id=self.item_id)
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)
...@@ -38,15 +38,22 @@ ...@@ -38,15 +38,22 @@
// add ourselves to the tasks that get performed when window is loaded // add ourselves to the tasks that get performed when window is loaded
window.onload = add_schematic_handler(window.onload); window.onload = add_schematic_handler(window.onload);
function update_schematics() {
// set up each schematic on the page
var schematics = document.getElementsByClassName('schematic');
for (var i = schematics.length - 1; i >= 0; i--)
if (schematics[i].getAttribute("loaded") != "true") {
new Schematic(schematics[i]);
schematics[i].setAttribute("loaded","true");
}
}
function add_schematic_handler(other_onload) { function add_schematic_handler(other_onload) {
return function() { return function() {
// execute othe onload functions first // execute othe onload functions first
if (other_onload) other_onload(); if (other_onload) other_onload();
// set up each schematic on the page update_schematics();
var schematics = document.getElementsByClassName('schematic');
for (var i = schematics.length - 1; i >= 0; i--)
new Schematic(schematics[i]);
} }
} }
......
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