[Commits] typing-turtle branch master updated.

olpc olpc at xo-05-26-CC.localdomain
Tue Dec 9 22:18:05 EST 2008


This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "/home/olpc-code/git/activities/typing-turtle".

The branch, master has been updated
       via  716b1a7e21d5afcc06ade6e3f6d664aa3196ecd1 (commit)
      from  d06e90e126944d746448437d3e1d03d0266c55c1 (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

 keyboard.py      |   51 ++++-------
 lessonbuilder.py |  272 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 289 insertions(+), 34 deletions(-)
 create mode 100644 lessonbuilder.py

- Log -----------------------------------------------------------------
commit 716b1a7e21d5afcc06ade6e3f6d664aa3196ecd1
Author: olpc <olpc at xo-05-26-CC.localdomain>
Date:   Wed Dec 10 03:17:18 2008 +0000

    Added lesson builder script.  Generates Typing Turtle lesson content from a dictionary.

diff --git a/keyboard.py b/keyboard.py
index 2ace05d..1eb340f 100644
--- a/keyboard.py
+++ b/keyboard.py
@@ -272,8 +272,8 @@ class Keyboard(gtk.EventBox):
     def _realize_cb(self, widget):
         # Setup keyboard event snooping in the root window.
         self.root_window.add_events(gtk.gdk.KEY_PRESS_MASK | gtk.gdk.KEY_RELEASE_MASK)
-        self.key_press_cb_id = self.root_window.connect('key-press-event', self._key_press_cb)
-        self.key_release_cb_id = self.root_window.connect('key-release-event', self._key_release_cb)
+        self.key_press_cb_id = self.root_window.connect('key-press-event', self._key_press_release_cb)
+        self.key_release_cb_id = self.root_window.connect('key-release-event', self._key_press_release_cb)
 
     def _unrealize_cb(self, widget):
         self.root_window.disconnect(self.key_press_cb_id)
@@ -372,9 +372,8 @@ class Keyboard(gtk.EventBox):
         self._layout_keys()
 
     def _update_screen_layout(self):
-        """Applies the screen scaling factor for the layout given the current 
-           allocation.
-           TODO - Preserve the layout's aspect ratio in this calculation."""
+        """Applies the scaling factor to the layout given the current
+           allocation."""
         bounds = self.get_allocation()
  
         for k in self.keys:
@@ -384,12 +383,15 @@ class Keyboard(gtk.EventBox):
             # relative to layout-width and layout-height.
             ratio_x = 100 * bounds.width / k.props['layout-width']
             ratio_y = 100 * bounds.height / k.props['layout-height']
-
+            
+            # Pick the smaller ratio to fit while preserving aspect ratio.
+            ratio = min(ratio_x, ratio_y)
+            
             # Make sure the final coordinates are integers, for the drawing routines.
-            k.screen_x = int(k.x * ratio_x / 100)
-            k.screen_y = int(k.y * ratio_y / 100)
-            k.screen_width = int(k.width * ratio_x / 100)
-            k.screen_height = int(k.height * ratio_y / 100)
+            k.screen_x = int(k.x * ratio / 100)
+            k.screen_y = int(k.y * ratio / 100)
+            k.screen_width = int(k.width * ratio / 100)
+            k.screen_height = int(k.height * ratio / 100)
 
     def _expose_key(self, k, cr=None):
         # Create cairo context if need be.
@@ -453,7 +455,7 @@ class Keyboard(gtk.EventBox):
         cr.restore()
 
     def _expose_cb(self, area, event):
-        # Update layout given screen size.
+        # Update layout given widget size.
         self._update_screen_layout()
 
         # Draw the keys.
@@ -467,10 +469,10 @@ class Keyboard(gtk.EventBox):
 
         return True
 
-    def _key_press_cb(self, widget, event):
+    def _key_press_release_cb(self, widget, event):
         key = self.key_scan_map.get(event.hardware_keycode)
         if key:
-            key.pressed = True
+            key.pressed = event.type == gtk.gdk.KEY_PRESS
             self._expose_key(key)
 
         # Hack to get the current modifier state - which will not be represented by the event.
@@ -485,24 +487,6 @@ class Keyboard(gtk.EventBox):
         
         return False
 
-    def _key_release_cb(self, widget, event):
-        key = self.key_scan_map.get(event.hardware_keycode)
-        if key:
-            key.pressed = False 
-            self._expose_key(key)
-        
-        # Hack to get the current modifier state - which will not be represented by the event.
-        state = gtk.gdk.device_get_core_pointer().get_state(self.window)[1]
-
-        if self.active_group != event.group or self.active_state != state:
-            self.active_group = event.group
-            self.active_state = event.state
-            self.queue_draw()
-
-        #print "release %d state=%x group=%d" % (event.hardware_keycode, self.active_state, event.group)
-        
-        return False
-
     def clear_hilite(self):
         for k in self.keys:
             if k.hilite:
@@ -532,12 +516,11 @@ if __name__ == "__main__":
     window.set_title("keyboard widget")
     window.connect("destroy", lambda w: gtk.main_quit())
 
-    k = Keyboard()
+    k = Keyboard(window)
     k.set_layout(DEFAULT_LAYOUT)
-    k.show()
 
     window.add(k)
-    window.show()
+    window.show_all()
 
     gtk.main()
 
diff --git a/lessonbuilder.py b/lessonbuilder.py
new file mode 100644
index 0000000..8931535
--- /dev/null
+++ b/lessonbuilder.py
@@ -0,0 +1,272 @@
+# Copyright 2008 by Kate Scheppke and Wade Brainerd.  
+# This file is part of Typing Turtle.
+#
+# Typing Turtle 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.
+# 
+# Typing Turtle 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 Typing Turtle.  If not, see <http://www.gnu.org/licenses/>.
+#!/usr/bin/env python
+# vi:sw=4 et
+
+import os, sys, random, json
+from gettext import gettext as _
+
+def make_triple(keys):
+    text = ''
+    for k in new_keys:
+        text += k + k + ' ' + k + ' '
+    return text
+
+def make_double(keys):
+    text = ''
+    for k in new_keys:
+        text += k + k + ' '
+    return text
+
+def make_random_triple(keys, count):
+    text = ''
+    for y in xrange(0, count * len(keys)):
+        k = random.choice(keys)
+        text += k + k + ' ' + k + ' '
+    return text
+
+def make_random(keys, count, gap):
+    text = ''
+    for y in range(0, count * len(keys)):
+        text += random.choice(keys)
+        if y % gap == gap-1:
+            text += ' '
+    return text
+
+def make_all_pairs(keys):
+    text = ''
+    for k1 in keys:
+        for k2 in keys:
+            text += k1 + k2 + ' '
+        for k2 in keys:
+            text += k2 + k1 + ' '
+    return text
+
+def make_random_pair(keys, count):
+    text = ''
+    for y in xrange(0, count * len(keys)):
+        k1 = random.choice(keys)
+        k2 = random.choice(keys)
+        text += k1 + k2 + ' '
+    return text
+
+def make_all_joined_pairs(keys1, keys2):
+    text = ''
+    for k1 in keys1:
+        for k2 in keys2:
+            text += k1 + k2 + ' '
+        for k2 in keys2:
+            text += k2 + k1 + ' '
+    return text
+
+def make_words(wordlist, count):
+    text = ''
+    for x in range(0, count):
+        text += random.choice(wordlist) + ' '
+    return text
+
+def filter_wordlist(path, all_keys, req_keys, minlen, maxlen, badwordlist):
+    wordlist = open(path, 'r').readlines()
+    wordlist = [s.strip() for s in wordlist]
+
+    if badwordlist:
+        bad_words = open(badwordlist, 'r').readlines()
+        bad_words = [s.strip() for s in badwordlist]
+    else:
+        bad_words = []
+
+    good_words = []
+
+    for word in wordlist:
+        if len(word) < minlen or len(word) > maxlen:
+            continue
+
+        good = True
+
+        for c in word:
+            if all_keys.find(c) == -1:
+                good = False
+                break
+
+        any_req = False
+        for c in req_keys:
+            if word.find(c) >= 0:
+                any_req = True
+                break
+        if not any_req:
+            good = False
+
+        for bad in bad_words:
+            if word == bad:
+                good = False
+                break
+
+        if good:
+            good_words.append(word)
+
+    return good_words
+
+def add_step(lesson, instructions, text):
+    step = {}
+    step['instructions'] = instructions
+    step['text'] = text
+    lesson['steps'].append(step)
+
+def build_lesson(
+    name, description, 
+    level, required_level, 
+    new_keys, base_keys, 
+    wordlist=None, badwordlist=None):
+
+    all_keys = new_keys + base_keys
+
+    lesson = {}
+    lesson['name'] = name
+    lesson['description'] = description
+    lesson['level'] = level
+    lesson['requiredlevel'] = required_level
+    lesson['steps'] = []
+
+    for key in new_keys:
+        add_step(lesson,
+            _('Press the %(name)s key with your %(finger)s.') \
+                % { 'name': key, 'finger': 'finger' },
+            key)
+    
+    add_step(lesson,
+        _('Practice typing the keys you just learned.'),
+        make_triple(new_keys) * 4)
+    
+    add_step(lesson,
+        _('Practice typing the keys you just learned.'),
+        make_random_triple(new_keys, count=5))
+    
+    add_step(lesson,
+        _('Practice typing the keys you just learned.'),
+        make_all_pairs(new_keys))
+    
+    add_step(lesson,
+        _('Practice typing the keys you just learned.'),
+        make_random_pair(new_keys, count=10))
+    
+    add_step(lesson,
+        _('Practice typing the keys you just learned.'),
+        make_random(new_keys, count=40, gap=5))
+    
+    if base_keys != '':
+        add_step(lesson,
+            _('Practice typing the keys you just learned.'),
+            make_all_joined_pairs(new_keys, all_keys))
+    
+        add_step(lesson,
+            _('Practice typing the keys you just learned.'),
+            make_random_pair(all_keys, count=20))
+    
+        add_step(lesson,
+            _('Practice typing the keys you just learned.'),
+            make_random(all_keys, count=50, gap=5))
+
+    if wordlist:
+        good_words = filter_wordlist(path=wordlist, 
+            all_keys=all_keys, req_keys=new_keys, 
+            minlen=2, maxlen=10, 
+            badwordlist=badwordlist)
+
+        add_step(lesson,
+            _('Practice typing these words.'),
+            make_words(good_words, count=500))
+    
+    return lesson
+
+def usage():
+    print """
+lessonbuilder.py v1.0 by Wade Brainerd <wadetb at gmail.com>
+Generates automatic lesson content for Typing Turtle.
+
+--help              Display this message.
+--keys='...'        Keys to teach.  Required.
+--base-keys='...'   Keys already taught prior to this lesson.
+--name='...'        Lesson name.
+--desc='...'        Lesson description.
+--level=N           Level granted by the lesson.
+--required-level=N  Level requirement for the lesson.
+--wordlist=file     List of words to use, one per line.
+--badwordlist=file  List of words *not* to use, one per line.
+--output=file       Output file.
+"""
+
+if __name__ == "__main__":
+    import getopt
+    try:
+        opts, args = getopt.getopt(sys.argv[1:], 'x', 
+            ['help', 'name=', 'desc=', 'level=', 'required-level=', 
+             'keys=', 'base-keys=', 'wordlist=', 'badwordlist=',
+             'output='])
+    except:
+        usage()
+        sys.exit()
+
+    name = 'Generated lesson'
+    desc = 'Default description'
+    level = 0
+    required_level = 0
+    new_keys = None
+    base_keys = ''
+    wordlist = None
+    badwordlist = None
+    output = None
+
+    for opt, arg in opts:
+        if opt == '--help':
+            usage()
+            sys.exit()
+        elif opt == '--name':
+            name = arg
+        elif opt == '--desc':
+            desc = arg
+        elif opt == '--level':
+            level = int(arg)
+        elif opt == '--required-level':
+            required_level = int(arg)
+        elif opt == '--keys':
+            new_keys = arg
+        elif opt == '--base-keys':
+            base_keys = arg
+        elif opt == '--wordlist':
+            wordlist = arg
+        elif opt == '--badwordlist':
+            badwordlist = arg
+        elif opt == '--output':
+            output = arg
+
+    if not new_keys:
+        usage()
+        sys.exit()
+
+    lesson = build_lesson(
+        name='Created Lesson', description='Lesson Description', 
+        level=0, required_level=0,
+        new_keys=new_keys, base_keys=base_keys, 
+        wordlist=wordlist, badwordlist=badwordlist)
+
+    if output:
+        import json
+        text = json.write(lesson)
+        open(output, 'w').write(text)
+    else:
+        import pprint
+        pprint.pprint(lesson)
+
-----------------------------------------------------------------------


--
/home/olpc-code/git/activities/typing-turtle


More information about the Commits mailing list