cybertools.scorm package basically operating
git-svn-id: svn://svn.cy55.de/Zope3/src/cybertools/trunk@1713 fd906abe-77d9-0310-91a1-e0d9ade77398
This commit is contained in:
parent
76ae5d8bbf
commit
b65f9d1a6d
2 changed files with 59 additions and 4 deletions
|
@ -10,7 +10,7 @@ In order to work with the SCORM API we first need a tracking storage.
|
|||
>>> tracks = TrackingStorage()
|
||||
|
||||
We can now create a ScormAPI adapter. Note that this adapter is stateless
|
||||
as it is usually created anew upon each request.
|
||||
as usually a new instance is created upon each request.
|
||||
|
||||
>>> from cybertools.scorm.base import ScormAPI
|
||||
>>> api = ScormAPI(tracks, 'a001', 0, 'user1')
|
||||
|
@ -31,7 +31,7 @@ Then we can set some values.
|
|||
|
||||
Depending on the data elements the values entered are kept together in
|
||||
one track or stored in separate track objects. So there is a separate
|
||||
track for each interaction and one track for all the other elements.
|
||||
track for each interaction and one additional track for all the other elements.
|
||||
|
||||
>>> for t in sorted(tracks.values(), key=lambda x: x.timeStamp):
|
||||
... print t.data
|
||||
|
@ -48,3 +48,17 @@ to care about the storage in different track objects.
|
|||
('q007', '0')
|
||||
>>> api.getValue('cmi.interactions.1.result')
|
||||
('incorrect', '0')
|
||||
|
||||
We can also query special elements like _count and _children.
|
||||
|
||||
>>> api.getValue('cmi.objectives._count')
|
||||
(0, '0')
|
||||
>>> api.getValue('cmi.interactions._count')
|
||||
(2, '0')
|
||||
|
||||
>>> api.getValue('cmi.interactions._children')
|
||||
(('id', 'type', 'objectives', 'timestamp', 'correct_responses',
|
||||
'weighting', 'learner_response', 'result', 'latency', 'description'), '0')
|
||||
>>> api.getValue('cmi.objectives.5.score._children')
|
||||
(('scaled', 'raw', 'min', 'max'), '0')
|
||||
|
||||
|
|
|
@ -31,6 +31,19 @@ from cybertools.tracking.btree import TrackingStorage
|
|||
|
||||
OK = '0'
|
||||
|
||||
_children = {
|
||||
'cmi.comments_from_learner': ('comment', 'location', 'timestamp'),
|
||||
'cmi.comments_from_lms': ('comment', 'location', 'timestamp'),
|
||||
'cmi.interactions': ('id', 'type', 'objectives', 'timestamp',
|
||||
'correct_responses', 'weighting', 'learner_response',
|
||||
'result', 'latency', 'description'),
|
||||
'cmi.learner_preference': ('audio_level', 'language',
|
||||
'delivery_speed', 'audio_captioning'),
|
||||
'cmi.objectives': ('id', 'score', 'success_status', 'completion_status',
|
||||
'description'),
|
||||
'score': ('scaled', 'raw', 'min', 'max'),
|
||||
}
|
||||
|
||||
|
||||
class ScormAPI(object):
|
||||
""" ScormAPI objects are temporary adapters created by
|
||||
|
@ -81,8 +94,18 @@ class ScormAPI(object):
|
|||
|
||||
def getValue(self, element):
|
||||
tracks = self.storage.getUserTracks(self.taskId, self.runId, self.userId)
|
||||
if element.endswith('._count'):
|
||||
base = element[:-len('._count')]
|
||||
if element.startswith('cmi.interactions.'):
|
||||
return self._countSubtracks(tracks, base), OK
|
||||
else:
|
||||
data = self._getTrackData(tracks, '')
|
||||
return self._countSubelements(data, base), OK
|
||||
if element.endswith('_children'):
|
||||
base = element[:-len('._children')]
|
||||
return self._getChildren(base)
|
||||
prefix, key = self._splitKey(element)
|
||||
data = self._getTrackData(tracks, prefix) or {}
|
||||
data = self._getTrackData(tracks, prefix)
|
||||
if key in data:
|
||||
return data[key], OK
|
||||
else:
|
||||
|
@ -103,8 +126,26 @@ class ScormAPI(object):
|
|||
return '', element
|
||||
|
||||
def _getTrackData(self, tracks, prefix):
|
||||
track = None
|
||||
for tr in reversed(sorted(tracks, key=lambda x: x.timeStamp)):
|
||||
if tr and tr.data.get('key_prefix', None) == prefix:
|
||||
return tr.data
|
||||
return {}
|
||||
|
||||
def _countSubelements(self, data, element):
|
||||
result = set()
|
||||
for key in data:
|
||||
if key.startswith(element) and key not in result:
|
||||
result.add(key)
|
||||
return len(result)
|
||||
|
||||
def _countSubtracks(self, tracks, base):
|
||||
return len([tr for tr in tracks if tr.data.get('key_prefix').startswith(base)])
|
||||
|
||||
def _getChildren(self, base):
|
||||
if base.endswith('.score'):
|
||||
base = 'score'
|
||||
if base in _children:
|
||||
return _children[base], OK
|
||||
else:
|
||||
return '', '401'
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue