diff options
author | Walter Bender <walter.bender@gmail.com> | 2012-10-02 13:30:05 (GMT) |
---|---|---|
committer | Walter Bender <walter.bender@gmail.com> | 2012-10-02 13:30:05 (GMT) |
commit | dfa1ba06e79e752d656b0cdb60d5092793dd1f90 (patch) | |
tree | 4f9fbdea6472b39153800ee818401a3b167f855b | |
parent | 516cf797d7b51f341f2cf9b9df6099cce3136d9b (diff) |
add journal stats samples
-rw-r--r-- | pysamples/journal-stats.py | 121 | ||||
-rwxr-xr-x | pysamples/ta-stats.py | 174 | ||||
-rw-r--r-- | samples/media-journal-stats.ta | 53 | ||||
-rw-r--r-- | samples/media-turtle-stats.ta | 86 |
4 files changed, 434 insertions, 0 deletions
diff --git a/pysamples/journal-stats.py b/pysamples/journal-stats.py new file mode 100644 index 0000000..2d8a5d3 --- /dev/null +++ b/pysamples/journal-stats.py @@ -0,0 +1,121 @@ +# Copyright (c) 2012, Walter Bender + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +def myblock(tw, x): # ignore second argument + ''' Load journal stats to heap (Sugar only) ''' + + import os + import glob + MAX = 19 + DIROFINTEREST = 'datastore' + + + class ParseJournal(): + ''' Simple parser of datastore ''' + + def __init__(self): + self._dsdict = {} + self._activity_name = [] + self._activity_count = [] + + homepath = os.environ['HOME'] + for path in glob.glob(os.path.join(homepath, '.sugar', '*')): + if isdsdir(path): + self._dsdict[os.path.basename(path)] = [] + dsobjdirs = glob.glob( + os.path.join(path, DIROFINTEREST, '??')) + for dsobjdir in dsobjdirs: + dsobjs = glob.glob(os.path.join(dsobjdir, '*')) + for dsobj in dsobjs: + self._dsdict[os.path.basename(path)].append({}) + activity = isactivity(dsobj) + if not activity: + self._dsdict[os.path.basename(path)][-1][ + 'activity'] = 'media object' + else: + self._dsdict[os.path.basename(path)][-1][ + 'activity'] = activity + + for k, v in self._dsdict.iteritems(): + for a in v: + if 'activity' in a: + if a['activity'] in self._activity_name: + i = self._activity_name.index(a['activity']) + self._activity_count[i] += 1 + else: + self._activity_name.append(a['activity']) + self._activity_count.append(1) + + def get_sorted(self): + activity_tuples = [] + for i in range(len(self._activity_name)): + activity_tuples.append((self._activity_name[i], + self._activity_count[i])) + sorted_tuples = sorted(activity_tuples, key=lambda x: x[1]) + activity_list = [] + count = 0 + length = len(sorted_tuples) + for i in range(length): + if i < MAX: + activity_list.append([sorted_tuples[length - i - 1][0], + sorted_tuples[length - i - 1][1]]) + else: + count += sorted_tuples[length - i - 1][1] + if count > 0: + activity_list.append([_('other'), count]) + return activity_list + + + def hascomponent(path, component): + ''' Return metadata attribute, if any ''' + if not os.path.exists(os.path.join(path, 'metadata')): + return False + if not os.path.exists(os.path.join(path, 'metadata', component)): + return False + fd = open(os.path.join(path, 'metadata', component)) + data = fd.readline() + fd.close() + if len(data) == 0: + return False + return data + + + def isactivity(path): + ''' Return activity name ''' + activity = hascomponent(path, 'activity') + if not activity: + return False + else: + return activity.split('.')[-1] + + + def isdsdir(path): + ''' Only interested if it is a datastore directory ''' + if not os.path.isdir(path): + return False + if not os.path.exists(os.path.join(path, DIROFINTEREST)): + return False + return True + + + data = ParseJournal() + activity_list = data.get_sorted() + for a in activity_list: + tw.lc.heap.append(a[0]) + tw.lc.heap.append(a[1]) + + tw.lc.heap.append(activity_list[0][1]) + return diff --git a/pysamples/ta-stats.py b/pysamples/ta-stats.py new file mode 100755 index 0000000..4d293e6 --- /dev/null +++ b/pysamples/ta-stats.py @@ -0,0 +1,174 @@ +# Copyright (c) 2012, Walter Bender + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +def myblock(tw, x): # ignore second argument + ''' Load journal stats to heap (Sugar only) ''' + + import os + import glob + MAX = 19 + DIROFINTEREST = 'datastore' + + + class ParseJournal(): + ''' Simple parser of datastore for turtle art entries ''' + + def __init__(self): + self._score = [] + + homepath = os.environ['HOME'] + for path in glob.glob(os.path.join(homepath, '.sugar', '*')): + if isdsdir(path): + dsobjdirs = glob.glob( + os.path.join(path, DIROFINTEREST, '??')) + for dsobjdir in dsobjdirs: + dsobjs = glob.glob(os.path.join(dsobjdir, '*')) + for dsobj in dsobjs: + if not isactivity(dsobj) == 'TurtleArtActivity': + continue + if hascomponent(dsobj, 'mime_type') != \ + 'application/x-turtle-art': + continue + score = hasturtleblocks(dsobj) + if score: + self._score.append(score) + + + def hascomponent(path, component): + ''' Return metadata attribute, if any ''' + if not os.path.exists(os.path.join(path, 'metadata')): + return False + if not os.path.exists(os.path.join(path, 'metadata', component)): + return False + fd = open(os.path.join(path, 'metadata', component)) + data = fd.readline() + fd.close() + if len(data) == 0: + return False + return data + + + def isactivity(path): + ''' Return activity name ''' + activity = hascomponent(path, 'activity') + if not activity: + return False + else: + return activity.split('.')[-1] + + + def isdsdir(path): + ''' Only interested if it is a datastore directory ''' + if not os.path.isdir(path): + return False + if not os.path.exists(os.path.join(path, DIROFINTEREST)): + return False + return True + + + TACAT = {'clean':'forward', 'forward':'forward', 'back':'forward', + 'left':'forward', 'right':'forward', 'arc': 'arc', + 'xcor': 'coord', 'ycor': 'coord', 'heading': 'coord', + 'setxy2': 'setxy', 'seth': 'setxy', 'penup': 'pen', 'pendown': 'pen', + 'setpensize': 'pen', 'setcolor': 'pen', 'pensize': 'pen', + 'color': 'pen', 'setshade': 'pen', 'setgray': 'pen', 'shade': 'pen', + 'gray': 'pen', 'fillscreen': 'pen', 'startfill': 'fill', + 'stopfill': 'fill', 'plus2': 'number', 'minus2': 'number', + 'product2': 'number', 'division2': 'number', 'remainder2': 'number', + 'sqrt': 'number', 'identity2': 'number', 'and2': 'boolean', + 'or2': 'boolean', 'not': 'boolean', 'greater2': 'boolean', + 'less2': 'boolean', 'equal2': 'boolean', 'random': 'random', + 'repeat': 'repeat', 'forever': 'repeat', 'if': 'ifthen', + 'ifelse': 'ifthen', 'while': 'ifthen', 'until': 'ifthen', + 'hat': 'action', 'stack': 'action', 'storein': 'box', 'box': 'box', + 'luminance': 'sensor', 'mousex': 'sensor', 'mousey': 'sensor', + 'mousebutton2': 'sensor', 'keyboard': 'sensor', 'kbinput': 'sensor', + 'readpixel': 'sensor', 'see': 'sensor', 'time': 'sensor', + 'sound': 'sensor', 'volume': 'sensor', 'pitch': 'sensor', + 'resistance': 'sensor', 'voltage': 'sensor', 'video': 'media', + 'wait': 'media', 'camera': 'media', 'journal': 'media', + 'audio': 'media', 'show': 'media', 'setscale': 'media', + 'savepix': 'media', 'savesvg': 'media', 'mediawait': 'media', + 'mediapause': 'media', 'mediastop': 'media', 'mediaplay': 'media', + 'speak': 'media', 'sinewave': 'media', 'description': 'media', + 'push':'extras', 'pop':'extras', 'printheap':'extras', + 'clearheap':'extras', 'isheapempty2':'extras', 'chr':'extras', + 'int':'extras', 'myfunction': 'python', 'userdefined': 'python', + 'loadblock': 'python', 'loadpalette': 'python'} + TAPAL = {'forward': 'turtlep', 'arc': 'turtlep', 'coord': 'turtlep', + 'setxy': 'turtlep', 'pen': 'penp', 'fill': 'penp', 'number': 'numberp', + 'random': 'numberp', 'boolean': 'numberp', 'repeat': 'flowp', + 'ifthen': 'flowp', 'action': 'boxp', 'box': 'boxp', + 'sensor': 'sensorp', 'media': 'mediap', 'extras': 'extrasp', + 'python': 'extrasp'} + TASCORE = {'forward': 3, 'arc': 3, 'setxy': 2.5, 'coord': 4, 'turtlep': 5, + 'pen': 2.5, 'fill': 2.5, 'penp': 5, + 'number': 2.5, 'boolean': 2.5, 'random': 2.5, 'numberp': 0, + 'repeat': 2.5, 'ifthen': 7.5, 'flowp': 10, + 'box': 7.5, 'action': 7.5, 'boxp': 0, + 'media': 5, 'mediap': 0, + 'python': 5, 'extras': 5, 'extrasp': 0, + 'sensor': 5, 'sensorp': 0} + PALS = ['turtlep', 'penp', 'numberp', 'flowp', 'boxp', 'sensorp', 'mediap', + 'extrasp'] + + def hasturtleblocks(path): + ''' Parse turtle block data and generate score based on rubric ''' + + if not os.path.exists(os.path.join(path, 'data')): + return None + fd = open(os.path.join(path, 'data')) + blocks = [] + # block name is second token in each line + for line in fd: + tokens = line.split(',') + if len(tokens) > 1: + token = tokens[1].strip('" [') + blocks.append(token) + + score = [] + for i in range(len(PALS)): + score.append(0) + cats = [] + pals = [] + + for b in blocks: + if b in TACAT: + if not TACAT[b] in cats: + cats.append(TACAT[b]) + for c in cats: + if c in TAPAL: + if not TAPAL[c] in pals: + pals.append(TAPAL[c]) + + for c in cats: + if c in TASCORE: + score[PALS.index(TAPAL[c])] += TASCORE[c] + + for p in pals: + if p in TASCORE: + score[PALS.index(p)] += TASCORE[p] + + return score + + data = ParseJournal() + n = min(40, len(data._score) / len(PALS)) + for i in range(n): + for j in range(len(PALS)): + tw.lc.heap.append(data._score[(n - i - 1)][len(PALS) - j - 1]) + + tw.lc.heap.append(n) + return diff --git a/samples/media-journal-stats.ta b/samples/media-journal-stats.ta new file mode 100644 index 0000000..37309c5 --- /dev/null +++ b/samples/media-journal-stats.ta @@ -0,0 +1,53 @@ +[[0, ["start", 2.0], 401, 0, [null, 1]], +[1, ["userdefined", "pysamples/journal-stats.py"], 401, 46, [0, 2, 6]], +[2, ["number", 100], 459, 46, [1, null]], +[3, "penup", 401, 296, [44, 5]], +[4, "pendown", 401, 422, [5, 11]], +[5, ["setxy2", 0], 401, 338, [3, 8, 29, 4]], +[6, ["storein", 0], 401, 88, [1, 7, 49, 51]], +[7, ["string", "scale"], 469, 88, [6, null]], +[8, "leftpos", 459, 338, [5, null]], +[9, "toppos", 513, 380, [29, null]], +[10, "forward", 67, 96, [25, 16, 17]], +[11, ["until", 0], 401, 464, [4, 12, 42, null]], +[12, "isheapempty2", 457, 480, [11, null]], +[13, "pop", 192, 96, [16, null]], +[14, "box", 192, 138, [16, 15, null]], +[15, ["string", "scale"], 247, 138, [14, null]], +[16, ["product2", 0], 138, 96, [10, 13, 14]], +[17, ["vspace", 0], 67, 138, [10, 27]], +[18, ["setxy2", 0], 67, 514, [23, 19, 20, 24]], +[19, "leftpos", 125, 514, [18, null]], +[20, "ycor", 125, 556, [18, null]], +[21, "show", 67, 430, [39, 22, 23]], +[22, "pop", 125, 430, [21, null]], +[23, "penup", 67, 472, [21, 18]], +[24, "pendown", 67, 598, [18, null]], +[25, "seth", 67, 54, [40, 26, 10]], +[26, ["number", 90], 166, 54, [25, null]], +[27, "seth", 67, 180, [17, 28, 38]], +[28, ["number", 0], 166, 180, [27, null]], +[29, ["minus2", 0], 459, 380, [5, 9, 30]], +[30, ["number", 30], 537, 422, [29, null]], +[31, ["setxy2", 20], 67, 264, [38, 35, 37, 39]], +[32, ["number", 20], 179, 306, [35, null]], +[33, ["number", -30], 179, 388, [37, null]], +[34, "xcor", 179, 264, [35, null]], +[35, ["plus2", 0], 125, 264, [31, 34, 32]], +[36, "ycor", 179, 346, [37, null]], +[37, ["plus2", 0], 125, 346, [31, 36, 33]], +[38, "penup", 67, 222, [27, 31]], +[39, "pendown", 67, 388, [31, 21]], +[40, "hat", 67, 0, [null, 41, 25]], +[41, ["string", "action"], 125, 12, [40, null]], +[42, "stack", 419, 530, [11, 43, null]], +[43, ["string", "action"], 477, 530, [42, null]], +[44, "setpensize", 401, 254, [51, 45, 3]], +[45, ["number", 20], 503, 254, [44, null]], +[46, ["division2", 0], 523, 130, [49, 47, 48]], +[47, "pop", 577, 130, [46, null]], +[48, "width", 601, 172, [46, null]], +[49, ["product2", 20], 469, 130, [6, 46, 50]], +[50, ["number", 0.15], 523, 212, [49, null]], +[51, ["vspace", 20], 401, 172, [6, 44]]] + diff --git a/samples/media-turtle-stats.ta b/samples/media-turtle-stats.ta new file mode 100644 index 0000000..269b818 --- /dev/null +++ b/samples/media-turtle-stats.ta @@ -0,0 +1,86 @@ +[[0, ["start", 2.0], 534, 124, [null, 84]], +[1, "pop", 602, 296, [2, null]], +[2, ["storein", 0], 534, 254, [28, 3, 1, 22]], +[3, ["string", "count"], 602, 254, [2, null]], +[4, "box", 72, 186, [12, 5, null]], +[5, ["string", "count"], 127, 186, [4, null]], +[6, "leftpos", 592, 422, [7, null]], +[7, ["setxy2", 0], 534, 422, [9, 6, 16, 10]], +[8, "forward", 934, 364, [75, 81, 71]], +[9, "penup", 534, 380, [22, 7]], +[10, "pendown", 534, 506, [7, 26]], +[11, ["setxy2", 20], 31, 312, [30, 14, 17, 31]], +[12, ["repeat", 104], 13, 186, [24, 4, 51, null]], +[13, "xcor", 143, 312, [14, null]], +[14, ["plus2", 0], 89, 312, [11, 13, 21]], +[15, "pop", 984, 214, [73, null]], +[16, ["number", 0], 592, 464, [7, null]], +[17, ["number", 0], 89, 394, [11, null]], +[18, "box", 714, 380, [23, 19, null]], +[19, ["string", "count"], 769, 380, [18, null]], +[20, "width", 690, 338, [23, null]], +[21, "pensize", 143, 354, [14, null]], +[22, "setpensize", 534, 338, [2, 23, 9]], +[23, ["division2", 0], 636, 338, [22, 20, 18]], +[24, "hat", 13, 132, [null, 25, 12]], +[25, ["string", "action"], 71, 144, [24, null]], +[26, "stack", 534, 548, [10, 27, null]], +[27, ["string", "action"], 592, 548, [26, null]], +[28, ["userdefined", "pysamples/ta-stats.py"], 534, 212, [84, 29, 2]], +[29, ["number", 100], 592, 212, [28, null]], +[30, "penup", 31, 270, [51, 11]], +[31, "pendown", 31, 436, [11, null]], +[32, "setcolor", 291, 180, [49, 33, 55]], +[33, "green", 368, 180, [32, null]], +[34, "setcolor", 291, 264, [55, 35, 57]], +[35, "cyan", 368, 264, [34, null]], +[36, "setcolor", 291, 348, [57, 43, 59]], +[37, "setcolor", 291, 432, [59, 44, 61]], +[38, "setcolor", 291, 516, [61, 45, 63]], +[39, "setcolor", 291, 600, [63, 46, 65]], +[40, "setcolor", 291, 684, [65, 47, 67]], +[41, "setcolor", 291, 768, [67, 48, 69]], +[42, "forward", 934, 448, [71, 83, 72]], +[43, "purple", 368, 348, [36, null]], +[44, "orange", 368, 432, [37, null]], +[45, "yellow", 368, 516, [38, null]], +[46, "red", 368, 600, [39, null]], +[47, "yellow", 368, 684, [40, null]], +[48, "red", 368, 768, [41, null]], +[49, "hat", 291, 126, [null, 50, 32]], +[50, ["string", "plot"], 349, 138, [49, null]], +[51, "stack", 31, 228, [12, 52, 30]], +[52, ["string", "plot"], 89, 228, [51, null]], +[53, "hat", 916, 118, [null, 54, 73]], +[54, ["string", "offset"], 974, 130, [53, null]], +[55, "stack", 291, 222, [32, 56, 34]], +[56, ["string", "offset"], 349, 222, [55, null]], +[57, "stack", 291, 306, [34, 58, 36]], +[58, ["string", "offset"], 349, 306, [57, null]], +[59, "stack", 291, 390, [36, 60, 37]], +[60, ["string", "offset"], 349, 390, [59, null]], +[61, "stack", 291, 474, [37, 62, 38]], +[62, ["string", "offset"], 349, 474, [61, null]], +[63, "stack", 291, 558, [38, 64, 39]], +[64, ["string", "offset"], 349, 558, [63, null]], +[65, "stack", 291, 642, [39, 66, 40]], +[66, ["string", "offset"], 349, 642, [65, null]], +[67, "stack", 291, 726, [40, 68, 41]], +[68, ["string", "offset"], 349, 726, [67, null]], +[69, "stack", 291, 810, [41, 70, null]], +[70, ["string", "offset"], 349, 810, [69, null]], +[71, "penup", 934, 406, [8, 42]], +[72, "pendown", 934, 490, [42, null]], +[73, ["storein", 0], 916, 172, [53, 74, 15, 80]], +[74, ["string", "value"], 984, 172, [73, null]], +[75, ["if", 63], 916, 298, [80, 76, 8, null]], +[76, ["greater2", 0], 972, 264, [75, 78, 77, null]], +[77, ["number", 0], 1042, 306, [76, null]], +[78, "box", 1018, 264, [76, 79, null]], +[79, ["string", "value"], 1073, 264, [78, null]], +[80, ["vspace", 0], 916, 256, [73, 75]], +[81, "box", 1005, 364, [8, 82, null]], +[82, ["string", "value"], 1060, 364, [81, null]], +[83, "pensize", 1005, 448, [42, null]], +[84, "setshade", 534, 170, [0, 85, 28]], +[85, ["number", 40.0], 619, 170, [84, null]]] |