From 37896ac5b04425bb787a7044de02d61122c58b71 Mon Sep 17 00:00:00 2001 From: Piotr Mitros Date: Mon, 26 Dec 2011 18:27:39 -0500 Subject: [PATCH] Gradual move to XPath/XQuery initiated --- courseware/capa_module.py | 55 ++++++++++++++++++---------- courseware/capa_problem.py | 2 +- courseware/content_parser.py | 9 +++++ courseware/static/js/video_player.js | 21 ++++++++--- 4 files changed, 61 insertions(+), 26 deletions(-) diff --git a/courseware/capa_module.py b/courseware/capa_module.py index 683e87f401..eeb2c52d7e 100644 --- a/courseware/capa_module.py +++ b/courseware/capa_module.py @@ -7,7 +7,10 @@ from django.http import Http404 import dateutil import datetime -from xml.dom.minidom import parse, parseString +#from xml.dom.minidom import parse, parseString +import content_parser + +import libxml2 ## TODO: Abstract out from Django from django.conf import settings @@ -65,7 +68,8 @@ class LoncapaModule(XModule): # User submitted a problem, and hasn't reset. We don't want # more submissions. - if self.lcp.done: + if self.lcp.done and not self.rerandomize: + #print "!" check_button = False save_button = False @@ -85,6 +89,7 @@ class LoncapaModule(XModule): 'save_button' : save_button, 'answer_available' : self.answer_available(), 'ajax_url' : self.ajax_url, + 'attempts': attempts_str }) if encapsulate: html = '
'.format(id=self.item_id)+html+"
" @@ -98,43 +103,53 @@ class LoncapaModule(XModule): self.max_attempts = None self.due_date = None - dom=parseString(xml) - node=dom.childNodes[0] + #dom=parseString(xml) + dom2 = libxml2.parseMemory(xml, len(xml)) - self.due_date=node.getAttribute("due") + #node=dom.childNodes[0] + + #self.due_date=node.getAttribute("due") + self.due_date=content_parser.item(dom2.xpathEval('/problem/@due')) if len(self.due_date)>0: self.due_date=dateutil.parser.parse(self.due_date) else: self.due_date=None - self.max_attempts=node.getAttribute("attempts") + #self.max_attempts=node.getAttribute("attempts") + self.max_attempts=content_parser.item(dom2.xpathEval('/problem/@attempts')) if len(self.max_attempts)>0: self.max_attempts=int(self.max_attempts) else: self.max_attempts=None - self.show_answer=node.getAttribute("showanswer") + #self.show_answer=node.getAttribute("showanswer") + self.show_answer=content_parser.item(dom2.xpathEval('/problem/@showanswer')) + if self.show_answer=="": self.show_answer="closed" - self.resettable=node.getAttribute("resettable") - if self.resettable=="": - self.resettable=True - elif self.resettable=="false": - self.resettable=False - elif self.resettable=="true": - self.resettable=True + self.rerandomize=content_parser.item(dom2.xpathEval('/problem/@rerandomize')) + #self.rerandomize=node.getAttribute("rerandomize") + if self.rerandomize=="": + self.rerandomize=True + elif self.rerandomize=="false": + self.rerandomize=False + elif self.rerandomize=="true": + self.rerandomize=True else: - raise Exception("Invalid resettable attribute "+self.resettable) + raise Exception("Invalid rerandomize attribute "+self.rerandomize) if state!=None: state=json.loads(state) if state!=None and 'attempts' in state: self.attempts=state['attempts'] - self.filename=node.getAttribute("filename") + self.filename=content_parser.item(dom2.xpathEval('/problem/@filename')) + #self.filename=node.getAttribute("filename") + #print self.filename filename=settings.DATA_DIR+"problems/"+self.filename+".xml" - self.name=node.getAttribute("name") + #self.name=node.getAttribute("name") + self.name=content_parser.item(dom2.xpathEval('/problem/@name')) self.lcp=LoncapaProblem(filename, self.item_id, state) def handle_ajax(self, dispatch, get): @@ -209,7 +224,7 @@ class LoncapaModule(XModule): # Problem submitted. Student should reset before checking # again. - if self.lcp.done and self.resettable: + if self.lcp.done and self.rerandomize: print "cpdr" raise Http404 @@ -232,7 +247,7 @@ class LoncapaModule(XModule): # Problem submitted. Student should reset before saving # again. - if self.lcp.done and self.resettable: + if self.lcp.done and self.rerandomize: print "spdr" return "Problem needs to be reset prior to save." @@ -257,7 +272,7 @@ class LoncapaModule(XModule): self.lcp.answers=dict() self.lcp.correct_map=dict() - if self.resettable: + if self.rerandomize: self.lcp.context=dict() self.lcp.questions=dict() # Detailed info about questions in problem instance. TODO: Should be by id and not lid. self.lcp.seed=None diff --git a/courseware/capa_problem.py b/courseware/capa_problem.py index f74f872f43..c837f120b4 100644 --- a/courseware/capa_problem.py +++ b/courseware/capa_problem.py @@ -90,7 +90,7 @@ class LoncapaProblem(): ot=False ## Are we in an outtext context? - print "Here", dom + #print "Here", dom # Loop through the nodes of the problem, and for e in dom.childNodes: diff --git a/courseware/content_parser.py b/courseware/content_parser.py index 284869bbaa..cccf0dfd41 100644 --- a/courseware/content_parser.py +++ b/courseware/content_parser.py @@ -9,6 +9,15 @@ course XML file and the rest of the system. TODO: Shift everything from xml.dom.minidom to XPath (or XQuery) ''' +def item(l, default="", process=lambda x:x): + if len(l)==0: + return default + elif len(l)==1: + return process(l[0].getContent()) + else: + raise Exception('Malformed XML') + + def course_file(user): # TODO: Cache. Also, return the libxml2 object. return settings.DATA_DIR+UserProfile.objects.get(user=user).courseware diff --git a/courseware/static/js/video_player.js b/courseware/static/js/video_player.js index 5ebc2c34c3..811f69eca4 100644 --- a/courseware/static/js/video_player.js +++ b/courseware/static/js/video_player.js @@ -125,15 +125,26 @@ function videoDestroy() { ytplayer = false; } -function log_event(e) { +function log_event(e, d) { // CRITICAL TODO: Change to AJAX //$("#eventlog").append("
"); //$("#eventlog").append(JSON.stringify(e)); - window['console'].log(JSON.stringify(e)); + + // TODO: Figure out + // XMLHttpRequest cannot load http://localhost:7000/userlog. Origin http://localhost:8000 is not allowed by Access-Control-Allow-Origin. + + /*window['console'].log(JSON.stringify(e)); + $.get("http://localhost:7000/userlog", + {'user':'pmitros', + 'key':'key', + 'event_type':'unknown', + 'data':'e'}, + function(data) { + });*/ } function seek_slide(type,oe,value) { - //log_event([type, value]); + //log_event('video', [type, value]); if(type=='slide') { // HACK/TODO: Youtube recommends this be false for slide and true for stop. // Works better on my system with true/true. @@ -145,7 +156,7 @@ function seek_slide(type,oe,value) { ytplayer.seekTo(value, true); } else if (type=='stop') { ytplayer.seekTo(value, true); - log_event([type, value]); + log_event('video', [type, value]); } update_captions(value); @@ -166,7 +177,7 @@ function get_state() { function onytplayerStateChange(newState) { setytplayerState(newState); - log_event(['State Change',newState, get_state()]); + log_event('video', ['State Change',newState, get_state()]); } function onPlayerError(errorCode) {