Minor layout fixes, basic schematic entry support, XPath for XML
This commit is contained in:
@@ -76,15 +76,12 @@ class LoncapaProblem():
|
||||
|
||||
# Loop through the nodes of the problem, and
|
||||
for e in dom.childNodes:
|
||||
# print e, ot
|
||||
#
|
||||
if e.localName=='script':
|
||||
#print e.childNodes[0].data
|
||||
exec e.childNodes[0].data in g,self.context
|
||||
elif e.localName=='endouttext':
|
||||
ot=False
|
||||
elif ot:
|
||||
# print e, "::", e.toxml()
|
||||
e.writexml(buf)
|
||||
elif e.localName=='startouttext':
|
||||
ot=True
|
||||
@@ -98,7 +95,6 @@ class LoncapaProblem():
|
||||
|
||||
self.text=buf.getvalue()
|
||||
self.text=self.contextualize_text(self.text)
|
||||
# print self.text
|
||||
self.filename=filename
|
||||
|
||||
done=False
|
||||
@@ -134,8 +130,6 @@ class LoncapaProblem():
|
||||
if id not in answers:
|
||||
correct_map[id]='incorrect' # Should always be there
|
||||
else:
|
||||
#correct_map[id]=self.grade_nr(self.questions[key],
|
||||
# self.answers[id])
|
||||
grader=self.graders[self.questions[key]['type']]
|
||||
print grader
|
||||
correct_map[id]=grader(self, self.questions[key],
|
||||
@@ -143,23 +137,21 @@ class LoncapaProblem():
|
||||
self.correct_map=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):
|
||||
error = abs(evaluator({},{},answer) - question['answer'])
|
||||
allowed_error = abs(question['answer']*question['tolerance'])
|
||||
@@ -255,9 +247,11 @@ class LoncapaProblem():
|
||||
return html
|
||||
|
||||
graders={'numericalresponse':grade_nr,
|
||||
'formularesponse':grade_fr}
|
||||
'formularesponse':grade_fr,
|
||||
'schematicresponse':grade_schem}
|
||||
handlers={'numericalresponse':handle_nr,
|
||||
'formularesponse':handle_fr}
|
||||
'formularesponse':handle_fr,
|
||||
'schematicresponse':handle_schem}
|
||||
|
||||
def contextualize_text(self, text):
|
||||
''' Takes a string with variables. E.g. $a+$b.
|
||||
|
||||
@@ -1,10 +1,33 @@
|
||||
from django.conf import settings
|
||||
from xml.dom.minidom import parse, parseString
|
||||
import libxml2
|
||||
|
||||
''' This file will eventually form an abstraction layer between the
|
||||
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):
|
||||
dom=parse(settings.DATA_DIR+'course.xml')
|
||||
|
||||
|
||||
@@ -18,7 +18,6 @@ class HtmlModule(XModule):
|
||||
return "html"
|
||||
|
||||
def get_html(self):
|
||||
print "XX",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):
|
||||
|
||||
@@ -52,7 +52,6 @@ class StudentModule(models.Model):
|
||||
module_id = models.CharField(max_length=255) # Filename for homeworks, etc.
|
||||
created = models.DateTimeField(auto_now_add=True)
|
||||
modified = models.DateTimeField(auto_now=True)
|
||||
xml = models.TextField(blank=True)
|
||||
class Meta:
|
||||
unique_together = (('student', 'module_id', 'module_type'),)
|
||||
|
||||
|
||||
@@ -19,6 +19,7 @@ import urllib
|
||||
import capa_module
|
||||
import video_module
|
||||
import html_module
|
||||
import schematic_module
|
||||
|
||||
from models import StudentModule
|
||||
|
||||
@@ -30,12 +31,6 @@ import content_parser
|
||||
|
||||
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):
|
||||
''' Layout module which lays out content vertically.
|
||||
'''
|
||||
@@ -86,7 +81,8 @@ def seq_module(request, module):
|
||||
|
||||
modx_modules={'problem':capa_module.LoncapaModule,
|
||||
'video':video_module.VideoModule,
|
||||
'html':html_module.HtmlModule}
|
||||
'html':html_module.HtmlModule,
|
||||
'schematic':schematic_module.SchematicModule}
|
||||
|
||||
def render_x_module(request, xml_module):
|
||||
''' Generic module for extensions. This renders to HTML. '''
|
||||
@@ -117,8 +113,7 @@ def render_x_module(request, xml_module):
|
||||
smod=StudentModule(student=request.user,
|
||||
module_type = module_type,
|
||||
module_id=module_id,
|
||||
state=instance.get_state(),
|
||||
xml=instance.xml)
|
||||
state=instance.get_state())
|
||||
# Grab content
|
||||
content = {'content':instance.get_html(),
|
||||
"destroy_js":instance.get_destroy_js(),
|
||||
@@ -130,8 +125,11 @@ def render_x_module(request, xml_module):
|
||||
|
||||
def modx_dispatch(request, module=None, dispatch=None, id=None):
|
||||
''' 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:
|
||||
print "ls404"
|
||||
raise Http404
|
||||
|
||||
s=s[0]
|
||||
@@ -140,7 +138,16 @@ def modx_dispatch(request, module=None, dispatch=None, id=None):
|
||||
|
||||
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)
|
||||
s.state=instance.get_state()
|
||||
s.grade=instance.get_score()['score']
|
||||
@@ -153,8 +160,8 @@ module_types={'video':render_x_module,
|
||||
'vertical':vertical_module,
|
||||
'sequential':seq_module,
|
||||
'problem':render_x_module,
|
||||
'schematic':render_x_module
|
||||
}
|
||||
#'lab':lab_module,
|
||||
|
||||
def render_module(request, module):
|
||||
''' Generic dispatch for internal modules. '''
|
||||
@@ -162,4 +169,5 @@ def render_module(request, module):
|
||||
return {"content":""}
|
||||
if str(module.localName) in module_types:
|
||||
return module_types[module.localName](request, module)
|
||||
print "rm404"
|
||||
raise Http404
|
||||
|
||||
25
courseware/schematic_module.py
Normal file
25
courseware/schematic_module.py
Normal file
@@ -0,0 +1,25 @@
|
||||
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 @@
|
||||
// add ourselves to the tasks that get performed when window is loaded
|
||||
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) {
|
||||
return function() {
|
||||
// execute othe onload functions first
|
||||
if (other_onload) other_onload();
|
||||
|
||||
// set up each schematic on the page
|
||||
var schematics = document.getElementsByClassName('schematic');
|
||||
for (var i = schematics.length - 1; i >= 0; i--)
|
||||
new Schematic(schematics[i]);
|
||||
|
||||
update_schematics();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
BIN
courseware/static/pixel.jpg
Normal file
BIN
courseware/static/pixel.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 306 B |
Reference in New Issue
Block a user