diff options
author | olpc <olpc@xo-05-26-CC.localdomain> | 2008-12-10 03:17:18 (GMT) |
---|---|---|
committer | olpc <olpc@xo-05-26-CC.localdomain> | 2008-12-10 03:17:18 (GMT) |
commit | 716b1a7e21d5afcc06ade6e3f6d664aa3196ecd1 (patch) | |
tree | 7fcfae8cbfe6b70dfab2ccae99ae4cb2ebe683ae | |
parent | d06e90e126944d746448437d3e1d03d0266c55c1 (diff) |
Added lesson builder script. Generates Typing Turtle lesson content from a dictionary.
-rw-r--r-- | keyboard.py | 51 | ||||
-rw-r--r-- | lessonbuilder.py | 272 |
2 files changed, 289 insertions, 34 deletions
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@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) + |