From 0f77a95cb3397ae61e3549d0cdebdc420258e652 Mon Sep 17 00:00:00 2001 From: tom creighton Date: Mon, 16 Dec 2013 15:54:29 -0500 Subject: [PATCH 01/60] added performance framework --- main.py | 13 ++++--- util/__init__.py | 90 ++++++++++++++++++++++++++++++++++++++++++------ util/settings.py | 2 ++ 3 files changed, 87 insertions(+), 18 deletions(-) diff --git a/main.py b/main.py index 6e60c42..d3cf6fa 100644 --- a/main.py +++ b/main.py @@ -29,12 +29,9 @@ def send_js(filename): def index(): s = request.environ.get('beaker.session') form_fwkurl = request.forms.get('frameworkurl', None) - knownframeworkurls = set() - + if form_fwkurl: - knownframeworkurls.add(form_fwkurl) - for url in knownframeworkurls: - util.getComp(url) + util.getComp(form_fwkurl) username = s.get('username', None) num_user_comps = len(util.getMyComps(username)) @@ -195,5 +192,7 @@ def reset(): s.invalidate() mongo.drop_database(db) redirect('/') - -run(app, host='localhost', port=8888, reloader=True) \ No newline at end of file + +if __name__ == '__main__': + util.parsePerformanceFwk() + run(app, host='localhost', port=8888, reloader=True) \ No newline at end of file diff --git a/util/__init__.py b/util/__init__.py index abf8a16..40e49ba 100644 --- a/util/__init__.py +++ b/util/__init__.py @@ -4,9 +4,14 @@ import json import xml.etree.ElementTree as ET from pymongo import MongoClient +from util import settings namespaces = {'cf': 'http://ns.medbiq.org/competencyframework/v1/', - 'lom': 'http://ltsc.ieee.org/xsd/LOM'} + 'lom': 'http://ltsc.ieee.org/xsd/LOM', + 'pf': "http://ns.medbiq.org/performanceframework/v1/", + 'cobj': "http://ns.medbiq.org/competencyobject/v1/", + 'dcterms': "http://purl.org/dc/terms/", + 'rdf': "http://www.w3.org/1999/02/22-rdf-syntax-ns#"} mongo = MongoClient() db = mongo.compapp @@ -231,7 +236,7 @@ def parseCompetencies(uri): uri = addXMLSuffix(uri) competencies = [] try: - res = requests.get(uri).text + res = requests.get(uri).text.strip() except Exception, e: return None fmwkxml = ET.fromstring(res) @@ -251,8 +256,8 @@ def parse(xmlbit): for include in xmlbit.findall('cf:Includes', namespaces=namespaces): if not obj.get('competencies', False): obj['competencies'] = [] - url = addXMLSuffix(include.find('cf:Entry', namespaces=namespaces).text) - nxt = ET.fromstring(requests.get(url).text) + url = addXMLSuffix(include.find('cf:Entry', namespaces=namespaces).text.strip()) + nxt = ET.fromstring(requests.get(url).text.strip()) c = parse(nxt) obj['competencies'].append(c) return structure(xmlbit, obj) @@ -264,10 +269,10 @@ def structure(fmwk, root): # if no relations, return comps for relation in fmwk.findall('cf:Relation', namespaces=namespaces): #get Reference1 object from comps, set Relationship attr to Reference2 entry - ref1 = relation.find('cf:Reference1/cf:Entry', namespaces=namespaces).text - rel = relation.find('cf:Relationship', namespaces=namespaces).text + ref1 = relation.find('cf:Reference1/cf:Entry', namespaces=namespaces).text.strip() + rel = relation.find('cf:Relationship', namespaces=namespaces).text.strip() rel = rel[rel.rfind('#') + 1:] - ref2 = relation.find('cf:Reference2/cf:Entry', namespaces=namespaces).text + ref2 = relation.find('cf:Reference2/cf:Entry', namespaces=namespaces).text.strip() # if i'm referencing the framework as a relation... i can't do it here if ref1 == root['entry']: if not root.get(rel, False): @@ -281,19 +286,82 @@ def structure(fmwk, root): comp[rel].append(ref2) return root +def parsePerformanceFwk(): + for uri in settings.PERFORMANCE_FWKS: + if not db.perfwk.find_one({"entry":uri}): + try: + res = requests.get(addXMLSuffix(uri)).text.strip() + except Exception, e: + return None + fmwkxml = ET.fromstring(res) + + db.perfwk.insert(parseperf(fmwkxml)) + +def parseperf(xmlbit): + obj = {} + obj['type'] = "performanceframework" + obj['entry'] = getEntry(xmlbit) + obj['encodedentry'] = urllib.quote_plus(getEntry(xmlbit)) + obj['catalog'] = middleStuff(xmlbit) + obj['title'] = getTitle(xmlbit) + obj['description'] = getDescription(xmlbit) + obj['date'] = datetime.datetime.utcnow() + obj['references'] = getReferences(xmlbit) + obj['components'] = getComponents(xmlbit) + import pprint + pprint.pprint(obj) + return obj + def addXMLSuffix(url): if url.endswith('.xml'): return url return url + ".xml" +def getReferences(xmlbit): + refs = [] + for ref in xmlbit.findall('pf:SupportingInformation/pf:Reference', namespaces=namespaces): + r = {} + r['objecturi'] = ref.find('rdf:Description', namespaces=namespaces).attrib.values()[0].strip() + typexml = ref.find('rdf:Type', namespaces=namespaces) + if typexml is not None: + r['type'] = typexml.attrib.values()[0].strip() + r['contenttype'] = ref.find('dcterms:format', namespaces=namespaces).text.strip() + refs.append(r) + return refs + +def getComponents(xmlbit): + obj = [] + for compo in xmlbit.findall('pf:Component', namespaces=namespaces): + c = {} + c['id'] = compo.attrib.values()[0].strip() + c['title'] = compo.find('pf:Title', namespaces=namespaces).text.strip() + for comp in compo.findall('pf:Competency/pf:Reference', namespaces=namespaces): + if not c.get('competencies'): + c['competencies'] = [] + co = {} + co['entry'] = comp.find('rdf:Description', namespaces=namespaces).attrib.values()[0].strip() + co['type'] = comp.find('rdf:Type', namespaces=namespaces).attrib.values()[0].strip() + c['competencies'].append(co) + for pl in compo.findall('pf:PerformanceLevelSet/pf:PerformanceLevel', namespaces=namespaces): + if not c.get('performancelevels'): + c['performancelevels'] = [] + perlvl = {} + perlvl['displayorder'] = pl.find('pf:DisplayOrder', namespaces=namespaces).text.strip() + perlvl['score'] = {'singlevalue': pl.find('pf:Score/pf:SingleValue', namespaces=namespaces).text.strip()} + perlvl['id'] = pl.find('pf:Indicator', namespaces=namespaces).attrib.values()[0].strip() + perlvl['description'] = pl.find('pf:Indicator/pf:Description', namespaces=namespaces).text.strip() + c['performancelevels'].append(perlvl) + obj.append(c) + return obj + def middleStuff(xml): - return xml.find('lom:lom/lom:general/lom:identifier/lom:catalog', namespaces=namespaces).text + return xml.find('lom:lom/lom:general/lom:identifier/lom:catalog', namespaces=namespaces).text.strip() def getEntry(xml): - return xml.find('lom:lom/lom:general/lom:identifier/lom:entry', namespaces=namespaces).text + return xml.find('lom:lom/lom:general/lom:identifier/lom:entry', namespaces=namespaces).text.strip() def getTitle(xml): - return xml.find('lom:lom/lom:general/lom:title/lom:string[@language="en"]', namespaces=namespaces).text + return xml.find('lom:lom/lom:general/lom:title/lom:string[@language="en"]', namespaces=namespaces).text.strip() def getDescription(xml): - return xml.find('lom:lom/lom:general/lom:description/lom:string[@language="en"]', namespaces=namespaces).text \ No newline at end of file + return xml.find('lom:lom/lom:general/lom:description/lom:string[@language="en"]', namespaces=namespaces).text.strip() \ No newline at end of file diff --git a/util/settings.py b/util/settings.py index bf5b34d..a6a3254 100644 --- a/util/settings.py +++ b/util/settings.py @@ -20,3 +20,5 @@ "http://adlnet.gov/competency/scorm/choosing-an-lms/part4":"http://www.youtube.com/watch?v=fCaHP8LZAIo", "http://adlnet.gov/competency/scorm/choosing-an-lms/part5":"http://www.youtube.com/watch?v=tlBbt5niQto" } + +PERFORMANCE_FWKS = ["http://12.109.40.34/performance-framework/xapi/tetris"] From 244ba761f81095055c400261241d70031194e744 Mon Sep 17 00:00:00 2001 From: tom creighton Date: Mon, 16 Dec 2013 15:58:49 -0500 Subject: [PATCH 02/60] too much stripping --- util/__init__.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/util/__init__.py b/util/__init__.py index 40e49ba..aefb889 100644 --- a/util/__init__.py +++ b/util/__init__.py @@ -236,7 +236,7 @@ def parseCompetencies(uri): uri = addXMLSuffix(uri) competencies = [] try: - res = requests.get(uri).text.strip() + res = requests.get(uri).text except Exception, e: return None fmwkxml = ET.fromstring(res) @@ -257,7 +257,7 @@ def parse(xmlbit): if not obj.get('competencies', False): obj['competencies'] = [] url = addXMLSuffix(include.find('cf:Entry', namespaces=namespaces).text.strip()) - nxt = ET.fromstring(requests.get(url).text.strip()) + nxt = ET.fromstring(requests.get(url).text) c = parse(nxt) obj['competencies'].append(c) return structure(xmlbit, obj) @@ -290,7 +290,7 @@ def parsePerformanceFwk(): for uri in settings.PERFORMANCE_FWKS: if not db.perfwk.find_one({"entry":uri}): try: - res = requests.get(addXMLSuffix(uri)).text.strip() + res = requests.get(addXMLSuffix(uri)).text except Exception, e: return None fmwkxml = ET.fromstring(res) From c129e7bbc192fd75242015619cc34834c73d8f40 Mon Sep 17 00:00:00 2001 From: tom creighton Date: Mon, 16 Dec 2013 16:03:39 -0500 Subject: [PATCH 03/60] removed print --- util/__init__.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/util/__init__.py b/util/__init__.py index aefb889..42527a6 100644 --- a/util/__init__.py +++ b/util/__init__.py @@ -308,8 +308,6 @@ def parseperf(xmlbit): obj['date'] = datetime.datetime.utcnow() obj['references'] = getReferences(xmlbit) obj['components'] = getComponents(xmlbit) - import pprint - pprint.pprint(obj) return obj def addXMLSuffix(url): From c57cb50f5a26810bf7554a77486ec71f5df2808e Mon Sep 17 00:00:00 2001 From: tom creighton Date: Mon, 16 Dec 2013 16:23:42 -0500 Subject: [PATCH 04/60] added tetris comp fwk to startup --- main.py | 1 + 1 file changed, 1 insertion(+) diff --git a/main.py b/main.py index d3cf6fa..c285f25 100644 --- a/main.py +++ b/main.py @@ -195,4 +195,5 @@ def reset(): if __name__ == '__main__': util.parsePerformanceFwk() + util.getComp("http://12.109.40.34/competency-framework/xapi/tetris") run(app, host='localhost', port=8888, reloader=True) \ No newline at end of file From 5f9ef554e8a778f629eb88c3f1d1833ecaa434a3 Mon Sep 17 00:00:00 2001 From: Lou Wolford Date: Tue, 17 Dec 2013 09:06:05 -0500 Subject: [PATCH 05/60] started tetris badges --- main.py | 9 +++++++++ templates/index.tpl | 1 + 2 files changed, 10 insertions(+) diff --git a/main.py b/main.py index 6e60c42..ee6785a 100644 --- a/main.py +++ b/main.py @@ -24,6 +24,10 @@ def send_js(filename): return static_file(filename, root='./js', mimetype='text/javascript') +@bottle.route('/static/badges/') +def server_static(filename): + return static_file(filename, root='./static') + @bottle.route('/', method='GET') @bottle.route('/', method='POST') def index(): @@ -40,6 +44,11 @@ def index(): num_user_comps = len(util.getMyComps(username)) return template('./templates/index', fwks=util.getAllSystemComps(), username=username, comps=num_user_comps, error=None) +@bottle.get('/badges') +def badges(): + + return template('./templates/badges.tpl', points=pts, lines=lns, minutes=mins, levels=lvls) + @bottle.get('/login') def getlogin(): s = request.environ.get('beaker.session') diff --git a/templates/index.tpl b/templates/index.tpl index 879af8c..4f12675 100644 --- a/templates/index.tpl +++ b/templates/index.tpl @@ -52,6 +52,7 @@ %end + Badges Admin Reset