Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSimon Schampijer <simon@schampijer.de>2007-07-12 20:45:24 (GMT)
committer Simon Schampijer <simon@schampijer.de>2007-07-12 20:45:24 (GMT)
commit8a2defe196f4f1d1edd7845ca871d58a57c717e1 (patch)
tree9244672f0969a47ab7dc509bac0427c51df5dfe4
parent1c2728aad09cf28fd194f20c01138fc53e0f4b68 (diff)
Started to merge the memosono game and the meorize game into one activity.
-rw-r--r--AUTHORS2
-rw-r--r--NEWS2
-rwxr-xr-xactivity.py258
-rw-r--r--activity/activity.info9
-rw-r--r--buddiespanel.py197
-rwxr-xr-xcardtable.py192
-rw-r--r--controller.py250
-rwxr-xr-xgame.py304
-rwxr-xr-xgames/addition/addition.mem24
-rwxr-xr-xgames/drumgit/drumgit.mem30
-rwxr-xr-xgames/letters1/letters1.mem25
-rwxr-xr-xgames/letters2/letters2.mem25
-rwxr-xr-xgames/numbers/images/01x.jpgbin0 -> 7084 bytes
-rwxr-xr-xgames/numbers/images/02x.jpgbin0 -> 8317 bytes
-rwxr-xr-xgames/numbers/images/03x.jpgbin0 -> 5421 bytes
-rwxr-xr-xgames/numbers/images/04x.jpgbin0 -> 8574 bytes
-rwxr-xr-xgames/numbers/images/05x.jpgbin0 -> 6632 bytes
-rwxr-xr-xgames/numbers/images/06x.jpgbin0 -> 8132 bytes
-rwxr-xr-xgames/numbers/images/07x.jpgbin0 -> 10302 bytes
-rwxr-xr-xgames/numbers/images/08x.jpgbin0 -> 8105 bytes
-rwxr-xr-xgames/numbers/images/09x.jpgbin0 -> 8458 bytes
-rwxr-xr-xgames/numbers/images/10x.jpgbin0 -> 8471 bytes
-rwxr-xr-xgames/numbers/images/11x.jpgbin0 -> 8573 bytes
-rwxr-xr-xgames/numbers/images/12x.jpgbin0 -> 10726 bytes
-rwxr-xr-xgames/numbers/images/13x.jpgbin0 -> 7400 bytes
-rwxr-xr-xgames/numbers/images/14x.jpgbin0 -> 8037 bytes
-rwxr-xr-xgames/numbers/images/15x.jpgbin0 -> 10862 bytes
-rwxr-xr-xgames/numbers/numbers.mem22
-rwxr-xr-xgames/phonemes/images/agua1.jpgbin0 -> 4216 bytes
-rwxr-xr-xgames/phonemes/images/agua2.jpgbin0 -> 4682 bytes
-rwxr-xr-xgames/phonemes/images/bola1.jpgbin0 -> 6062 bytes
-rwxr-xr-xgames/phonemes/images/bola2.jpgbin0 -> 5634 bytes
-rwxr-xr-xgames/phonemes/images/casa1.jpgbin0 -> 5979 bytes
-rwxr-xr-xgames/phonemes/images/casa2.jpgbin0 -> 6094 bytes
-rwxr-xr-xgames/phonemes/images/ema1.jpgbin0 -> 4154 bytes
-rwxr-xr-xgames/phonemes/images/ema2.jpgbin0 -> 4704 bytes
-rwxr-xr-xgames/phonemes/images/frutas1.jpgbin0 -> 7482 bytes
-rwxr-xr-xgames/phonemes/images/frutas2.jpgbin0 -> 7658 bytes
-rwxr-xr-xgames/phonemes/images/homem1.jpgbin0 -> 5297 bytes
-rwxr-xr-xgames/phonemes/images/homem2.jpgbin0 -> 5574 bytes
-rwxr-xr-xgames/phonemes/images/ioio1.jpgbin0 -> 4866 bytes
-rwxr-xr-xgames/phonemes/images/ioio2.jpgbin0 -> 5026 bytes
-rwxr-xr-xgames/phonemes/images/kiwi1.jpgbin0 -> 6605 bytes
-rwxr-xr-xgames/phonemes/images/kiwi2.jpgbin0 -> 6969 bytes
-rwxr-xr-xgames/phonemes/images/ovo1.jpgbin0 -> 2923 bytes
-rwxr-xr-xgames/phonemes/images/ovo2.jpgbin0 -> 3428 bytes
-rwxr-xr-xgames/phonemes/images/peixe1.jpgbin0 -> 7289 bytes
-rwxr-xr-xgames/phonemes/images/peixe2.jpgbin0 -> 7369 bytes
-rwxr-xr-xgames/phonemes/images/queijo1.jpgbin0 -> 5989 bytes
-rwxr-xr-xgames/phonemes/images/queijo2.jpgbin0 -> 5402 bytes
-rwxr-xr-xgames/phonemes/images/roda1.jpgbin0 -> 5776 bytes
-rwxr-xr-xgames/phonemes/images/roda2.jpgbin0 -> 5683 bytes
-rwxr-xr-xgames/phonemes/images/sapo1.jpgbin0 -> 7399 bytes
-rwxr-xr-xgames/phonemes/images/sapo2.jpgbin0 -> 7191 bytes
-rwxr-xr-xgames/phonemes/images/uva1.jpgbin0 -> 4264 bytes
-rwxr-xr-xgames/phonemes/images/uva2.jpgbin0 -> 4932 bytes
-rwxr-xr-xgames/phonemes/images/zebra1.jpgbin0 -> 6607 bytes
-rwxr-xr-xgames/phonemes/images/zebra2.jpgbin0 -> 7280 bytes
-rwxr-xr-xgames/phonemes/phonemes.mem22
-rwxr-xr-ximages/card-text.svg126
-rwxr-xr-ximages/card.svg79
-rwxr-xr-ximages/score.svg81
-rwxr-xr-ximages/stock-buddy.svg18
-rw-r--r--infopanel.py20
-rw-r--r--memorize.dtd21
-rwxr-xr-xmemorizetoolbar.py99
-rw-r--r--memosono.dtd15
-rwxr-xr-xmemosonoactivity.py290
-rw-r--r--messenger.py116
-rw-r--r--misc/addition.mem23
-rw-r--r--misc/drumgit.mem24
-rw-r--r--model.py152
-rwxr-xr-xosc/__init__.py0
-rwxr-xr-xosc/oscapi.py163
-rwxr-xr-xosc/osccore.py405
-rwxr-xr-xplayerscoreboard.py131
-rw-r--r--playtile.py71
-rw-r--r--playview.py42
-rwxr-xr-xscore.py67
-rwxr-xr-xscoreboard.py83
-rwxr-xr-xsvgcard.py215
-rwxr-xr-xsvglabel.py103
82 files changed, 2217 insertions, 1489 deletions
diff --git a/AUTHORS b/AUTHORS
new file mode 100644
index 0000000..ac6f8ff
--- /dev/null
+++ b/AUTHORS
@@ -0,0 +1,2 @@
+Simon Schampijer - simon@schampijer.de
+Muriel de Souza Godoi - muriel@laptop.org
diff --git a/NEWS b/NEWS
index f9acee0..392dffb 100644
--- a/NEWS
+++ b/NEWS
@@ -1 +1,3 @@
+Starting to merge the memosono game and the memorize game into one activity. (erikos)
+
First version of the collaborated memosono. (erikos)
diff --git a/activity.py b/activity.py
new file mode 100755
index 0000000..0eb203c
--- /dev/null
+++ b/activity.py
@@ -0,0 +1,258 @@
+#! /usr/bin/env python
+#
+# Copyright (C) 2007, One Laptop Per Child
+#
+# Muriel de Souza Godoi - muriel@laptop.org
+#
+# 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 2 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+#
+
+import logging
+from gettext import gettext as _
+
+import dbus
+import gtk
+import pygtk
+import telepathy
+import telepathy.client
+
+from sugar.activity.activity import Activity, ActivityToolbox
+from sugar.presence import presenceservice
+import sugar.logger
+
+from sugar.graphics.xocolor import XoColor
+from sugar import profile
+import cardtable
+import scoreboard
+import game
+import messenger
+import memorizetoolbar
+
+# will eventually be imported from telepathy.tubes or something
+from tubeconn import TubeConnection
+
+SERVICE = "org.laptop.Memorize"
+IFACE = SERVICE
+PATH = "/org/laptop/Memorize"
+
+_logger = logging.getLogger('memorize-activity')
+
+class MemorizeActivity(Activity):
+ def __init__(self, handle):
+ Activity.__init__(self, handle)
+
+ self.set_title('Memorize Activity')
+
+ self.table = cardtable.CardTable()
+ self.scoreboard = scoreboard.Scoreboard()
+ self.game = game.MemorizeGame()
+
+ hbox = gtk.HBox(False)
+ hbox.pack_start(self.scoreboard, False, False)
+ hbox.pack_start(self.table)
+
+ toolbox = ActivityToolbox(self)
+ activity_toolbar = toolbox.get_activity_toolbar()
+
+ self._memorizeToolbar = memorizetoolbar.MemorizeToolbar(self)
+ toolbox.add_toolbar('Games', self._memorizeToolbar)
+ self._memorizeToolbar.show()
+
+ self.set_toolbox(toolbox)
+ toolbox.show()
+ self.set_canvas(hbox)
+
+ self.table.connect('key-press-event', self.table.key_press_event)
+ self.connect('shared', self._shared_cb)
+
+ self.table.connect('card-flipped', self.game.card_flipped)
+ self.table.connect('card-highlighted', self.game.card_highlighted)
+
+ self.game.connect('reset_scoreboard', self.scoreboard.reset)
+ self.game.connect('reset_table', self.table.reset)
+ self.game.connect('load_game', self.table.load_game)
+ self.game.connect('change_game', self.table.change_game)
+ self.game.connect('change_game', self._memorizeToolbar.update_toolbar)
+ self.game.connect('set-border', self.table.set_border)
+ self.game.connect('flop-card', self.table.flop_card)
+ self.game.connect('flip-card', self.table.flip_card)
+ self.game.connect('highlight-card', self.table.highlight_card)
+ self.game.connect('add_buddy', self.scoreboard.add_buddy)
+ self.game.connect('rem_buddy', self.scoreboard.rem_buddy)
+ self.game.connect('increase-score', self.scoreboard.increase_score)
+ self.game.connect('wait_mode_buddy', self.scoreboard.set_wait_mode)
+ self.game.connect('change-turn', self.scoreboard.set_selected)
+
+ self.show_all()
+
+ # Get the Presence Service
+ self.pservice = presenceservice.get_instance()
+ bus = dbus.Bus()
+ name, path = self.pservice.get_preferred_connection()
+ self.tp_conn_name = name
+ self.tp_conn_path = path
+ self.conn = telepathy.client.Connection(name, path)
+ self.initiating = None
+
+ # Buddy object for you
+ owner = self.pservice.get_owner()
+ self.owner = owner
+ self.current = 0
+ self.game.set_myself(self.owner)
+ # Owner.props.key
+ if self._shared_activity:
+ # We are joining the activity
+ self.connect('joined', self._joined_cb)
+ if self.get_shared():
+ # We've already joined
+ self._joined_cb()
+ else:
+ _logger.debug("buddy joined - __init__: %s", self.owner.props.nick)
+ self.game.load_game('numbers', 4)
+ self.game.add_buddy(self.owner)
+
+ def restart(self, widget):
+ self.game.reset()
+
+ def change_game(self, game_name, size):
+ self.game.change_game(game_name, size)
+
+ def _shared_cb(self, activity):
+ _logger.debug('My activity was shared')
+ self.initiating = True
+ self._setup()
+
+ for buddy in self._shared_activity.get_joined_buddies():
+ pass # Can do stuff with newly acquired buddies here
+
+ self._shared_activity.connect('buddy-joined', self._buddy_joined_cb)
+ self._shared_activity.connect('buddy-left', self._buddy_left_cb)
+
+ _logger.debug('This is my activity: making a tube...')
+ id = self.tubes_chan[telepathy.CHANNEL_TYPE_TUBES].OfferTube(
+ telepathy.TUBE_TYPE_DBUS, SERVICE, {})
+
+ def _setup(self):
+ if self._shared_activity is None:
+ _logger.error('Failed to share or join activity')
+ return
+
+ bus_name, conn_path, channel_paths =\
+ self._shared_activity.get_channels()
+
+ # Work out what our room is called and whether we have Tubes already
+ room = None
+ tubes_chan = None
+ text_chan = None
+ for channel_path in channel_paths:
+ channel = telepathy.client.Channel(bus_name, channel_path)
+ htype, handle = channel.GetHandle()
+ if htype == telepathy.HANDLE_TYPE_ROOM:
+ _logger.debug('Found our room: it has handle#%d "%s"',
+ handle, self.conn.InspectHandles(htype, [handle])[0])
+ room = handle
+ ctype = channel.GetChannelType()
+ if ctype == telepathy.CHANNEL_TYPE_TUBES:
+ _logger.debug('Found our Tubes channel at %s', channel_path)
+ tubes_chan = channel
+ elif ctype == telepathy.CHANNEL_TYPE_TEXT:
+ _logger.debug('Found our Text channel at %s', channel_path)
+ text_chan = channel
+
+ if room is None:
+ _logger.error("Presence service didn't create a room")
+ return
+ if text_chan is None:
+ _logger.error("Presence service didn't create a text channel")
+ return
+
+ # Make sure we have a Tubes channel - PS doesn't yet provide one
+ if tubes_chan is None:
+ _logger.debug("Didn't find our Tubes channel, requesting one...")
+ tubes_chan = self.conn.request_channel(telepathy.CHANNEL_TYPE_TUBES,
+ telepathy.HANDLE_TYPE_ROOM, room, True)
+
+ self.tubes_chan = tubes_chan
+ self.text_chan = text_chan
+
+ tubes_chan[telepathy.CHANNEL_TYPE_TUBES].connect_to_signal('NewTube',
+ self._new_tube_cb)
+
+ def _list_tubes_reply_cb(self, tubes):
+ for tube_info in tubes:
+ self._new_tube_cb(*tube_info)
+
+ def _list_tubes_error_cb(self, e):
+ _logger.error('ListTubes() failed: %s', e)
+
+ def _joined_cb(self, activity):
+ if not self._shared_activity:
+ return
+
+ for buddy in self._shared_activity.get_joined_buddies():
+ _logger.debug("buddy joined - _joined_cb: %s", buddy.props.nick)
+ self.game.add_buddy(buddy)
+
+ _logger.debug('Joined an existing shared activity')
+ self.initiating = False
+ self._setup()
+
+ self._shared_activity.connect('buddy-joined', self._buddy_joined_cb)
+ self._shared_activity.connect('buddy-left', self._buddy_left_cb)
+
+ _logger.debug('This is not my activity: waiting for a tube...')
+ self.tubes_chan[telepathy.CHANNEL_TYPE_TUBES].ListTubes(
+ reply_handler=self._list_tubes_reply_cb,
+ error_handler=self._list_tubes_error_cb)
+
+ def _new_tube_cb(self, id, initiator, type, service, params, state):
+ _logger.debug('New tube: ID=%d initator=%d type=%d service=%s '
+ 'params=%r state=%d', id, initiator, type, service,
+ params, state)
+
+ if (type == telepathy.TUBE_TYPE_DBUS and
+ service == SERVICE):
+ if state == telepathy.TUBE_STATE_LOCAL_PENDING:
+ self.tubes_chan[telepathy.CHANNEL_TYPE_TUBES].AcceptTube(id)
+
+ self.tube_conn = TubeConnection(self.conn,
+ self.tubes_chan[telepathy.CHANNEL_TYPE_TUBES],
+ id, group_iface=self.text_chan[telepathy.CHANNEL_INTERFACE_GROUP])
+
+ print 'Tube created'
+ self.messenger = messenger.Messenger(self.tube_conn, self.initiating, self._get_buddy, self.game)
+ self.game.connect('flip-card-signal', self.messenger.flip)
+ self.game.connect('change_game_signal', self.messenger.change_game)
+
+ def _get_buddy(self, cs_handle):
+ """Get a Buddy from a channel specific handle."""
+ group = self.text_chan[telepathy.CHANNEL_INTERFACE_GROUP]
+ my_csh = group.GetSelfHandle()
+ if my_csh == cs_handle:
+ handle = self.conn.GetSelfHandle()
+ else:
+ handle = group.GetHandleOwners([cs_handle])[0]
+ assert handle != 0
+ return self.pservice.get_buddy_by_telepathy_handle(self.tp_conn_name,
+ self.tp_conn_path, handle)
+
+ def _buddy_joined_cb (self, activity, buddy):
+ if buddy <> self.owner:
+ _logger.debug("buddy joined - _buddy_joined_cb: %s", buddy.props.nick)
+ self.game.add_buddy(buddy)
+
+ def _buddy_left_cb (self, activity, buddy):
+ _logger.debug("buddy left - _buddy_left_cb: %s", buddy.props.nick)
+ self.game.rem_buddy(buddy) \ No newline at end of file
diff --git a/activity/activity.info b/activity/activity.info
index 2949e26..10dab42 100644
--- a/activity/activity.info
+++ b/activity/activity.info
@@ -1,6 +1,7 @@
[Activity]
-name = Memosono
-service_name = org.laptop.Memosono
-class = memosonoactivity.MemosonoActivity
-icon = activity-memosono
+name = Memorize
+service_name = org.laptop.Memorize
+class = activity.MemorizeActivity
+icon = activity-memorize
activity_version = 11
+show_launcher = yes
diff --git a/buddiespanel.py b/buddiespanel.py
deleted file mode 100644
index e3361ad..0000000
--- a/buddiespanel.py
+++ /dev/null
@@ -1,197 +0,0 @@
-import gtk
-import hippo
-import math
-
-from sugar.graphics.canvasicon import CanvasIcon
-from sugar.graphics.xocolor import XoColor
-from sugar.graphics import color
-from sugar.graphics import style
-from sugar.graphics import units
-
-
-class BuddyPlayer(hippo.CanvasBox, hippo.CanvasItem):
- __gtype_name__ = 'BuddyPlayer'
- _BORDER_DEFAULT = units.points_to_pixels(1.0)
-
- def __init__(self, buddy, **kargs):
- hippo.CanvasBox.__init__(self, **kargs)
-
- self._radius = units.points_to_pixels(5)
- self.props.border_color = 0
- self.props.background_color = 0
- self.props.orientation = hippo.ORIENTATION_VERTICAL
- self.props.border = self._BORDER_DEFAULT
- self.props.border_left = self._radius
- self.props.border_right = self._radius
-
- buddy_color = buddy.props.color
- if not buddy_color:
- buddy_color = "#000000,#ffffff"
-
- self.icon = CanvasIcon(
- icon_name='theme:stock-buddy',
- xo_color=XoColor(buddy_color))
-
- nick = buddy.props.nick
- if not nick:
- nick = ""
- self.name = hippo.CanvasText(text=nick, size_mode=hippo.CANVAS_SIZE_WRAP_WORD, color=color.WHITE.get_int())
-
- self.append(self.icon)
- self.append(self.name)
-
-
- def do_paint_background(self, cr, damaged_box):
- [width, height] = self.get_allocation()
-
- x = self._BORDER_DEFAULT / 2
- y = self._BORDER_DEFAULT / 2
- width -= self._BORDER_DEFAULT
- height -= self._BORDER_DEFAULT
-
- cr.move_to(x + self._radius, y);
- cr.arc(x + width - self._radius, y + self._radius,
- self._radius, math.pi * 1.5, math.pi * 2);
- cr.arc(x + width - self._radius, x + height - self._radius,
- self._radius, 0, math.pi * 0.5);
- cr.arc(x + self._radius, y + height - self._radius,
- self._radius, math.pi * 0.5, math.pi);
- cr.arc(x + self._radius, y + self._radius, self._radius,
- math.pi, math.pi * 1.5);
-
- hippo.cairo_set_source_rgba32(cr, self.props.background_color)
- cr.fill()
-
-
-class BuddiesPanel(hippo.CanvasBox):
- _COLOR_ACTIVE = 50
- _COLOR_INACTIVE = 0
-
- def __init__(self):
- hippo.CanvasBox.__init__(self, spacing=4, padding=5,
- orientation=hippo.ORIENTATION_VERTICAL)
-
- self.players_box = hippo.CanvasBox(spacing=4, padding=5,
- orientation=hippo.ORIENTATION_VERTICAL)
-
- self.watchers_box = hippo.CanvasBox(spacing=4, padding=5,
- orientation=hippo.ORIENTATION_VERTICAL)
-
- self.append(self.players_box)
- self.append(hippo.CanvasWidget(widget=gtk.HSeparator()))
- self.append(self.watchers_box, hippo.PACK_EXPAND)
-
- self.players = {}
- self.watchers = {}
- self.last_active = None
-
- def _create_buddy_vbox (self, buddy):
- buddy_color = buddy.props.color
- if not buddy_color:
- buddy_color = "#000000,#ffffff"
-
- icon = CanvasIcon(
- icon_name='theme:stock-buddy',
- xo_color=XoColor(buddy_color))
-
- nick = buddy.props.nick
- if not nick:
- nick = ""
- name = hippo.CanvasText(text=nick, color=color.WHITE.get_int())
-
- vbox = hippo.CanvasBox(padding=5)
- vbox._radius = units.points_to_pixels(5)
- vbox.props.border_color = 100
- vbox.props.background_color = 200
- vbox.props.orientation = hippo.ORIENTATION_VERTICAL
- vbox.props.border = units.points_to_pixels(1.0)
- vbox.props.border_left = vbox._radius
- vbox.props.border_right = vbox._radius
-
- vbox.append(icon)
- vbox.append(name)
-
- return vbox
-
- def add_watcher(self, buddy):
- op = buddy.object_path()
- if self.watchers.get(op) is not None:
- return
- # if the watcher is also a player, don't add them
- if self.players.get(op) is not None:
- return
-
- vbox = self._create_buddy_vbox (buddy)
-
- self.watchers_box.append(vbox)
-
- self.watchers[op] = vbox
-
- def add_player(self, buddy):
- op = buddy.object_path()
- if self.players.get(op) is not None:
- return
- # if the player is also a watcher, drop them from the watchers
- widget = self.watchers.pop(op, None)
- if widget is not None:
- self.watchers_box.remove(widget)
-
- assert len(self.players) < 2
-
- hbox = hippo.CanvasBox(spacing=4, padding=5,
- orientation=hippo.ORIENTATION_HORIZONTAL)
- hbox.append(BuddyPlayer(buddy))
-
- count_font = style.FONT_BOLD.get_pango_desc()
- count_font.set_size(30000)
- count = hippo.CanvasText(text="0", color=color.WHITE.get_int(),
- font_desc=count_font)
- hbox.append(count)
-
- self.players_box.append(hbox)
-
- self.players[op] = hbox
-
- def set_is_playing(self, buddy):
- hbox = self.players.get(buddy.object_path())
- bp = hbox.get_children()[0]
- bp.props.background_color = self._COLOR_ACTIVE
- bp.emit_paint_needed(0, 0, -1, -1)
- if self.last_active is not None:
- hbox = self.players.get(self.last_active.object_path())
- lbp = hbox.get_children()[0]
- lbp.props.background_color = self._COLOR_INACTIVE
- lbp.emit_paint_needed(0, 0, -1, -1)
- self.last_active = buddy
-
- def set_count(self, buddy, val):
- hbox = self.players.get(buddy.object_path())
- if hbox is None:
- return
-
- count = hbox.get_children()[1]
- count.props.text = str(val)
-
- def remove_watcher(self, buddy):
- op = buddy.object_path()
- widget = self.watchers[op]
- if widget is None:
- return
-
- self.watchers_box.remove(widget)
- del self.watchers[op]
-
- # removing someone from the game entirely should also remove them
- # from the players
- self.remove_player(buddy)
-
- def remove_player(self, buddy):
- op = buddy.object_path()
- widget = self.players.get(op)
- if widget is None:
- return
-
- self.players_box.remove(widget)
- del self.players[op]
-
- self.add_watcher(buddy)
diff --git a/cardtable.py b/cardtable.py
new file mode 100755
index 0000000..b9f96b5
--- /dev/null
+++ b/cardtable.py
@@ -0,0 +1,192 @@
+#! /usr/bin/env python
+#
+# Copyright (C) 2007, One Laptop Per Child
+#
+# Muriel de Souza Godoi - muriel@laptop.org
+#
+# 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 2 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+#
+
+import gtk, pygtk
+import svgcard
+import os
+import time
+import gobject
+import math
+import gc
+
+class CardTable(gtk.EventBox):
+
+ __gsignals__ = {
+ 'card-flipped': (gobject.SIGNAL_RUN_FIRST, None, [int, gobject.TYPE_PYOBJECT]),
+ 'card-highlighted': (gobject.SIGNAL_RUN_FIRST, None, [int, gobject.TYPE_PYOBJECT]),
+ }
+
+ def __init__(self):
+ gtk.EventBox.__init__(self)
+
+ # Set table settings
+ self.modify_bg(gtk.STATE_NORMAL, gtk.gdk.color_parse('#000000'))
+ self.table = gtk.Table()
+ self.table.grab_focus()
+ self.table.set_flags(gtk.CAN_FOCUS)
+ self.table.set_flags(gtk.CAN_DEFAULT)
+ self.table.set_row_spacings(11)
+ self.table.set_col_spacings(11)
+ self.table.set_border_width(11)
+ self.table.set_resize_mode(gtk.RESIZE_IMMEDIATE)
+ self.set_property('child', self.table)
+ self.fist_load = True
+
+ def load_game(self, widget, data, grid):
+ self.data = data
+ self.cards_data = grid
+ self.size = int(math.ceil(math.sqrt(len(grid))))
+ self.table.resize(self.size, self.size)
+ self.card_size = self.get_card_size(self.size)
+ self.cards = {}
+ self.cd2id = {}
+ self.id2cd = {}
+ self.dict = {}
+ self.selected_card = [0, 0]
+ self.flipped_card = -1
+ self.table_positions = {}
+
+ # Build the table
+ if data['divided']=='True':
+ text1 = str(self.data['face1'])
+ text2 = str(self.data['face2'])
+ else:
+ text1 = str(self.data['face'])
+ text2 = str(self.data['face'])
+ buffer_card_1 = svgcard.SvgCard(-1, {'front_border':{'opacity':'0'}, 'front_h_border':{'opacity':'0.5'}, 'back_text':{'card_text':text1}}, {}, None, self.card_size)
+ buffer_card_2 = svgcard.SvgCard(-1, {'front_border':{'opacity':'0'}, 'front_h_border':{'opacity':'0.5'}, 'back_text':{'card_text':text2}}, {}, None, self.card_size)
+
+ self.game_dir = os.path.join(os.path.dirname(__file__), 'games')
+ x = 0
+ y = 0
+ id = 0
+ for card in self.cards_data:
+ if card[1] <> '':
+ jpg = os.path.join(self.game_dir, self.data['game_name']+'/images/'+str(card[1]))
+ else:
+ jpg = None
+ props = {}
+ props['front_border'] = {'opacity':'1'}
+ props['front_h_border'] ={'opacity':'1'}
+ props['front_text']= {'card_text':card[3], 'card_line1':card[4], 'card_line2':card[5], 'card_line3':card[6], 'card_line4':card[7]}
+
+ if card[0]== '1':
+ buffer_card = buffer_card_1
+ else:
+ buffer_card = buffer_card_2
+
+ card = svgcard.SvgCard(id, props, buffer_card.get_cache(), jpg, self.card_size)
+ card.connect('enter-notify-event', self.mouse_event, [x, y])
+ card.connect("button-press-event", self.flip_card_mouse, id)
+ self.table_positions[(x, y)]=1
+ self.cd2id[card] = id
+ self.id2cd[id] = card
+ self.cards[(x, y)] = card
+ self.dict[id] = (x, y)
+ self.table.attach(card, x, x+1, y, y+1, gtk.SHRINK, gtk.SHRINK)
+ #button = gtk.Button('button')
+ #button.show()
+ #self.table.attach(button, x, x+1, y, y+1, gtk.SHRINK, gtk.SHRINK)
+ x += 1
+ if x == self.size:
+ x = 0
+ y +=1
+ id += 1
+ self.fist_load = False
+ gc.collect()
+
+ def change_game(self, widget, data, grid):
+ if not self.fist_load:
+ for card in self.cards.values():
+ self.table.remove(card)
+ del card
+ self.load_game(None, data, grid)
+
+ def get_card_size(self, size_table):
+ x = (780 - (11*size_table))/size_table
+ return x
+
+ def mouse_event(self, widget, event, coord):
+ #self.table.grab_focus()
+ card = self.cards[coord[0], coord[1]]
+ id = self.cd2id.get(card)
+ self.emit('card-highlighted', id, True)
+ self.selected_card = (coord[0], coord[1])
+
+ def key_press_event(self, widget, event):
+ #self.table.grab_focus()
+ x= self.selected_card[0]
+ y= self.selected_card[1]
+
+ if event.keyval in (gtk.keysyms.Left, gtk.keysyms.KP_Left,gtk.keysyms.a):
+ if self.table_positions.has_key((x-1, y)):
+ card = self.cards[x-1, y]
+ id = self.cd2id.get(card)
+ self.emit('card-highlighted', id, False)
+
+ elif event.keyval in (gtk.keysyms.Right, gtk.keysyms.KP_Right,gtk.keysyms.d):
+ if self.table_positions.has_key((x+1, y)):
+ card = self.cards[x+1, y]
+ id = self.cd2id.get(card)
+ self.emit('card-highlighted', id, False)
+
+ elif event.keyval in (gtk.keysyms.Up, gtk.keysyms.KP_Up,gtk.keysyms.w):
+ if self.table_positions.has_key((x, y-1)):
+ card = self.cards[x, y-1]
+ id = self.cd2id.get(card)
+ self.emit('card-highlighted', id, False)
+
+ elif event.keyval in (gtk.keysyms.Down, gtk.keysyms.KP_Down,gtk.keysyms.s):
+ if self.table_positions.has_key((x, y+1)):
+ card = self.cards[x, y+1]
+ id = self.cd2id.get(card)
+ self.emit('card-highlighted', id, False)
+
+ elif event.keyval in (gtk.keysyms.space,gtk.keysyms.KP_Page_Down):
+ card = self.cards[x, y]
+ self.card_flipped(card)
+
+ def flip_card_mouse(self, widget, event, id):
+ position = self.dict[id]
+ card = self.cards[position]
+ self.card_flipped(card)
+
+ def card_flipped(self, card):
+ if not card.is_flipped():
+ id = self.cd2id[card]
+ self.emit('card-flipped', id, False)
+
+ def set_border(self, widget, id, stroke_color, fill_color):
+ self.id2cd[id].set_border(stroke_color, fill_color)
+
+ def flop_card(self, widget, id):
+ self.id2cd.get(id).flop()
+
+ def flip_card(self, widget, id):
+ self.id2cd.get(id).flip()
+
+ def highlight_card(self, widget, id, status):
+ self.selected_card = self.dict.get(id)
+ self.id2cd.get(id).set_highlight(status)
+
+ def reset(self, widget):
+ for id in self.id2cd.keys():
+ self.id2cd[id].reset()
diff --git a/controller.py b/controller.py
deleted file mode 100644
index 4970d87..0000000
--- a/controller.py
+++ /dev/null
@@ -1,250 +0,0 @@
-import logging
-
-import gobject
-import gtk
-import os
-
-from dbus import Interface
-from dbus.service import method, signal
-from dbus.gobject_service import ExportedGObject
-
-from model import Model
-from csound.csoundserver import CsoundServer
-
-SERVICE = "org.freedesktop.Telepathy.Tube.Memosono"
-IFACE = SERVICE
-PATH = "/org/freedesktop/Telepathy/Tube/Memosono"
-
-
-GAME_PATH = os.path.join(os.path.dirname(__file__),'games/drumgit')
-IMAGES_PATH = os.path.join(os.path.dirname(__file__),'games/drumgit/images')
-SOUNDS_PATH = os.path.join(os.path.dirname(__file__),'games/drumgit/sounds')
-MAX_NUM_PLAYERS = 2
-
-_logger = logging.getLogger('controller')
-
-
-class Controller(ExportedGObject):
- ''' Networked Controller which is the core component of the activity. It
- handles the communication with the components (model, view) and with the
- other players over the network.
- '''
- def __init__(self, tube, playview, is_initiator, buddies_panel, info_panel,
- owner, get_buddy, activity):
- super(Controller, self).__init__(tube, PATH)
- self.tube = tube
- self.pv = playview
- self.is_initiator = is_initiator
- self.entered = False
- self.buddies_panel = buddies_panel
- self.info_panel = info_panel
- self.owner = owner
- self._get_buddy = get_buddy
- self.activity = activity
- self.numplayers = 0
- self.turn = 0
-
- self.cs = CsoundServer()
- gtk.gdk.threads_init()
- self.cs.start()
-
- if self.is_initiator:
- self.init_game()
-
- for tile in self.pv.tiles:
- tile.connect('button-press-event', self._button_press_cb, self.pv.tiles.index(tile))
-
-
- self.tube.watch_participants(self.participant_change_cb)
-
-
- def participant_change_cb(self, added, removed):
-
- _logger.debug('adding participants: %r', added)
- _logger.debug('removing participants: %r', removed)
-
- for handle, bus_name in added:
- buddy = self._get_buddy(handle)
- if buddy is not None:
- _logger.debug('buddy %r was added', buddy)
- if self.numplayers < MAX_NUM_PLAYERS:
- self.buddies_panel.add_player(buddy)
- self.numplayers+=1
- if self.is_initiator:
- self.buddies_panel.set_is_playing(buddy)
- self.model.players[self.tube.participants[handle]] = [buddy.props.nick, 0]
- _logger.debug('list of players: %s', self.model.players)
- else:
- self.info_panel.show('we are already two players')
-
- for handle in removed:
- buddy = self._get_buddy(handle)
- if buddy is not None:
- _logger.debug('-----> buddy %r was removed', buddy)
- self.buddies_panel.remove_player(buddy)
- self.numplayers-=1
- if self.is_initiator:
- try:
- del self.model.players[self.tube.participants[handle]]
- except ValueError:
- # already absent
- pass
-
- if not self.entered:
- self.playerid = self.tube.get_unique_name()
- self.tube.add_signal_receiver(self.info_cb, 'Info', IFACE,
- path=PATH, sender_keyword='sender')
- self.tube.add_signal_receiver(self.turn_cb, 'Turn', IFACE,
- path=PATH, sender_keyword='sender')
- self.tube.add_signal_receiver(self.flip_cb, 'Flip', IFACE,
- path=PATH, sender_keyword='sender')
- self.tube.add_signal_receiver(self.play_cb, 'Play', IFACE,
- path=PATH, sender_keyword='sender')
- self.tube.add_signal_receiver(self.points_cb, 'Points', IFACE,
- path=PATH, sender_keyword='sender')
-
- self.entered = True
-
- if self.is_initiator:
- if len(self.model.players) == 2 and self.model.started == 0:
- _logger.debug('start the game')
- self.Info('start the game')
- self.model.started = 1
- self.change_turn()
-
- def init_game(self):
- _logger.debug('I am the initiator, so making myself the leader of the game.')
- self.model = Model(GAME_PATH, os.path.dirname(__file__))
- self.model.read('drumgit.mson')
- self.model.def_grid()
- self.tube.add_signal_receiver(self.selected_cb, 'Selected', IFACE,
- path=PATH, sender_keyword='sender')
-
-
- @signal(dbus_interface=IFACE, signature='n')
- def Selected(self, tilenum):
- """Signal that a tile has been selected"""
-
- def selected_cb(self, tilenum, sender=None):
- _logger.debug('MA: %s flipped tile %d', sender, tilenum)
- if self.model.grid[tilenum][2] == 1:
- self.Info('selected already')
- else:
- pairkey, moch, state = self.model.grid[tilenum]
- color = self.model.pairs[pairkey].props.color
-
- if moch == 0:
- if self.model.pairs[pairkey].props.aimg != None:
- img = os.path.join(IMAGES_PATH, self.model.pairs[pairkey].props.aimg)
- self.Flip(tilenum, img, color)
- if self.model.pairs[pairkey].props.asnd != None:
- snd = os.path.join(SOUNDS_PATH, self.model.pairs[pairkey].props.asnd)
- self.Play(tilenum, snd, color)
- elif moch == 1:
- if self.model.pairs[pairkey].props.bimg != None:
- img = os.path.join(IMAGES_PATH, self.model.pairs[pairkey].props.bimg)
- self.Flip(tilenum, img, color)
- if self.model.pairs[pairkey].props.bsnd != None:
- snd = os.path.join(SOUNDS_PATH, self.model.pairs[pairkey].props.bsnd)
- self.Play(tilenum, snd, color)
-
- self.model.count+=1
- if self.model.count == 1:
- self.model.selected = tilenum
- self.model.grid[tilenum][2] = 1
- return
- if self.model.count == 2:
- self.model.count = 0
- # evaluate
- if( self.model.same(tilenum, self.model.selected) == 1):
- _logger.debug('MA: Tile(%d) and (%d) are the same', tilenum, self.model.selected)
- self.model.grid[tilenum][2] = 1
- self.model.grid[self.model.selected][2] = 1
-
- self.model.players[sender][1]+=1
- self.Points(sender, self.model.players[sender][1])
- self.Info('found pair, one more try')
- else:
- self.model.grid[tilenum][2] = 0
- self.model.grid[self.model.selected][2] = 0
- self.change_turn()
- self.Info('pair does not match, next player')
- gobject.timeout_add(2000, self._turn_back, tilenum, self.model.selected)
- _logger.debug('Tile(%d) and (%d) are NOT the same', tilenum, self.model.selected)
-
- def _turn_back(self, tilenuma, tilenumb):
- self.Flip(tilenuma, 'images/black.png', 100)
- self.Flip(tilenumb, 'images/black.png', 100)
- return False
-
- def change_turn(self):
- if self.model.player_active < (len(self.model.players)-1):
- self.model.player_active+=1
- else:
- self.model.player_active = 0
-
- key = self.model.players.keys()[self.model.player_active]
- self.Turn(key, self.model.players[key][0])
-
-
- @signal(dbus_interface=IFACE, signature='nsn')
- def Flip(self, tilenum, obj, color):
- """Signal that a tile will be flipped"""
-
- def flip_cb(self, tilenum, obj, color, sender=None):
- handle = self.tube.bus_name_to_handle[sender]
- _logger.debug('Flipped tile(%d) from %s. Show image.', tilenum, sender)
- self.pv.flip(tilenum, os.path.join(os.path.dirname(__file__), obj), color)
-
-
- @signal(dbus_interface=IFACE, signature='nsn')
- def Play(self, tilenum, obj, color):
- """Signal that a sound will be played"""
-
- def play_cb(self, tilenum, obj, color, sender=None):
- handle = self.tube.bus_name_to_handle[sender]
- _logger.debug('Flipped tile(%d) from %s. Play sound.', tilenum, sender)
- _logger.debug(' Sound: %s', obj)
- self.cs.perform('i 108 0.0 3.0 "%s" 1 0.7 0.5 0'%(obj))
-
-
- @signal(dbus_interface=IFACE, signature='ss')
- def Turn(self, playerid, name):
- """Signal that it is the players turn"""
-
- def turn_cb(self, playerid, name, sender=None):
- if self.playerid == playerid:
- self.turn = 1
- else:
- self.turn = 0
-
- buddy = self._get_buddy(self.tube.bus_name_to_handle[playerid])
- self.buddies_panel.set_is_playing(buddy)
- self.info_panel.show('hey %s it is your turn'%name)
-
- @signal(dbus_interface=IFACE, signature='sn')
- def Points(self, player, points):
- """Signal to update the points"""
-
- def points_cb(self, player, points, sender=None):
- handle = self.tube.bus_name_to_handle[player]
- buddy = self._get_buddy(handle)
- self.buddies_panel.set_count(buddy, points)
-
-
- @signal(dbus_interface=IFACE, signature='s')
- def Info(self, msg):
- """Signal that there is some game information"""
-
- def info_cb(self, msg, sender=None):
- self.info_panel.show(msg)
-
-
- def _button_press_cb(self, tile, event, tilenum=None):
- if self.turn == 1:
- self.Selected(tilenum)
- else:
- _logger.debug('Not my turn')
- self.info_panel.show('Not my turn')
-
-
diff --git a/game.py b/game.py
new file mode 100755
index 0000000..493ce64
--- /dev/null
+++ b/game.py
@@ -0,0 +1,304 @@
+#! /usr/bin/env python
+#
+# Copyright (C) 2007, One Laptop Per Child
+#
+# Muriel de Souza Godoi - muriel@laptop.org
+#
+# 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 2 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+#
+
+import os
+import random
+import logging
+import gobject
+import time
+
+from sugar import profile
+from dbus.service import method, signal
+from dbus.gobject_service import ExportedGObject
+
+import gobject
+
+_logger = logging.getLogger('memorize-activity')
+
+SERVICE = "org.laptop.Memorize"
+IFACE = SERVICE
+PATH = "/org/laptop/Memorize"
+
+
+class MemorizeGame(gobject.GObject):
+
+ __gsignals__ = {
+ 'reset_scoreboard': (gobject.SIGNAL_RUN_FIRST, None, []),
+ 'reset_table': (gobject.SIGNAL_RUN_FIRST, None, []),
+ 'load_game': (gobject.SIGNAL_RUN_FIRST, None, [gobject.TYPE_PYOBJECT, gobject.TYPE_PYOBJECT]),
+ 'change_game': (gobject.SIGNAL_RUN_FIRST, None, [gobject.TYPE_PYOBJECT, gobject.TYPE_PYOBJECT]),
+ 'change_game_signal': (gobject.SIGNAL_RUN_FIRST, None, [gobject.TYPE_PYOBJECT, gobject.TYPE_PYOBJECT, gobject.TYPE_PYOBJECT]),
+ 'set-border': (gobject.SIGNAL_RUN_FIRST, None, [int, gobject.TYPE_PYOBJECT, gobject.TYPE_PYOBJECT]),
+ 'flip-card': (gobject.SIGNAL_RUN_FIRST, None, [int]),
+ 'flip-card-signal': (gobject.SIGNAL_RUN_FIRST, None, [int]),
+ 'flop-card': (gobject.SIGNAL_RUN_FIRST, None, [int]),
+ 'highlight-card': (gobject.SIGNAL_RUN_FIRST, None, [int, gobject.TYPE_PYOBJECT]),
+ 'add_buddy': (gobject.SIGNAL_RUN_FIRST, None, [gobject.TYPE_PYOBJECT, int]),
+ 'rem_buddy': (gobject.SIGNAL_RUN_FIRST, None, [gobject.TYPE_PYOBJECT]),
+ 'increase-score': (gobject.SIGNAL_RUN_FIRST, None, [gobject.TYPE_PYOBJECT]),
+ 'wait_mode_buddy': (gobject.SIGNAL_RUN_FIRST, None, [gobject.TYPE_PYOBJECT, gobject.TYPE_PYOBJECT]),
+ 'change-turn': (gobject.SIGNAL_RUN_FIRST, None, [gobject.TYPE_PYOBJECT]),
+ }
+
+ def __init__(self):
+ gobject.GObject.__init__(self)
+ self.myself = None
+ self.players_score = {}
+ self.players = []
+ self.waiting_players = []
+ self.current_player = None
+ self.last_flipped = -1
+ self.last_highlight = 1
+ self.game_dir = os.path.join(os.path.dirname(__file__), 'games')
+ self.messenger = None
+ self.sentitive = True
+
+ def load_game(self, game_name, size):
+ tuple = self.read_config(game_name, size)
+ self.data = tuple[0]
+ self.grid = tuple[1]
+ self.data['running'] = 'False'
+ self.emit('load_game', self.data, self.grid)
+
+ def add_buddy(self, buddy, score = 0):
+ _logger.debug('Buddy %r was added to game', buddy.props.nick)
+ self.players.append(buddy)
+ self.players_score[buddy] = score
+ self.emit('add_buddy', buddy, score)
+
+ if self.current_player == None:
+ self.current_player = buddy
+ self.change_turn()
+
+ def rem_buddy(self, buddy):
+ _logger.debug('Buddy %r was removed to game', buddy.props.nick)
+ index = self.players.index(buddy)
+ del self.players[index]
+ del (self.players_score[buddy])
+ if self.current_player == buddy and len(self.players) <> 0:
+ self.change_turn()
+ self.emit('rem_buddy', buddy)
+
+ def change_turn(self):
+ if self.current_player == None:
+ self.current_player = self.players[0]
+ elif self.current_player == self.players[-1]:
+ self.current_player = self.players[0]
+ else:
+ self.current_player = self.players[self.players.index(self.current_player)+1]
+ self.set_sensitive(self.current_player == self.myself)
+ self.emit('change-turn', self.current_player)
+
+ def card_flipped(self, widget, id, signal = False):
+ # Check if is my turn
+ if not self.sentitive and not signal:
+ return
+
+ # Handle groups if needed
+ if self.data['divided'] == 'True':
+ if self.last_flipped == -1 and id >= (len(self.grid)/2):
+ return
+ if self.last_flipped <> -1 and id < (len(self.grid)/2):
+ return
+ self.data['running'] = 'True'
+
+ # First card case
+ if self.last_flipped == -1:
+ self.last_flipped = id
+ self.grid[id][8] = 1
+ self.emit('flip-card', id)
+ if not signal:
+ self.emit('flip-card-signal', id)
+ if self.data['divided'] == 'True':
+ self.card_highlighted(widget, -1, False)
+
+ # Pair matched
+ elif self.grid[self.last_flipped][-1] == self.grid[id][-1]:
+ stroke_color, fill_color = self.current_player.props.color.split(',')
+ self.emit('set-border', id, stroke_color, fill_color)
+ self.emit('set-border', self.last_flipped, stroke_color, fill_color)
+ self.increase_point(self.current_player)
+ self.grid[id][8] = 1
+ self.emit('flip-card', id)
+ if self.data['divided'] == 'True':
+ self.card_highlighted(widget, -1, False)
+ if not signal:
+ self.emit('flip-card-signal', id)
+ self.last_flipped = -1
+ # Pair don't match
+ elif self.grid[self.last_flipped][-1] <> self.grid[id][-1]:
+ self.emit('flip-card', id)
+ if not signal:
+ self.emit('flip-card-signal', id)
+ self.grid[id][8] = 1
+ time.sleep(2)
+ self.emit('flop-card', id)
+ self.grid[id][8] = 0
+ self.emit('flop-card', self.last_flipped)
+ if self.data['divided'] == 'True':
+ self.card_highlighted(widget, -1, False)
+ # self.emit('highlight-card', id, True)
+ self.grid[self.last_flipped][8] = 0
+ self.last_flipped = -1
+ self.change_turn()
+
+ def card_highlighted(self, widget, id, mouse):
+ if id == -1:
+ self.last_highlight = 1
+ self.emit('highlight-card', self.last_highlight, False)
+ return
+
+ if not self.sentitive:
+ return
+ if self.data['divided'] == 'True':
+ if self.last_flipped == -1 and id >= (len(self.grid)/2):
+ return
+ if self.last_flipped <> -1 and id < (len(self.grid)/2):
+ return
+ self.emit('highlight-card', self.last_highlight, False)
+ if mouse and self.grid[id][8]==0:
+ self.emit('highlight-card', id, True)
+ if not mouse:
+ self.emit('highlight-card', id, True)
+
+ self.last_highlight = id
+
+ def increase_point(self, buddy):
+ self.players_score[buddy] += 1
+ self.emit('increase-score', buddy)
+
+ def read_config(self, game_name, size = 100):
+ filename = os.path.join(self.game_dir, game_name +'/'+game_name+'.mem')
+ # seed = random.randint(0, 14567)
+ temp1 = []
+ temp2 = []
+ grid = []
+ data = {}
+ # set random seed
+ random.seed()
+ filecheck = filename.split('.')
+ if filecheck[2] != 'mem':
+ logging.error('File format of %s'%filename)
+ else:
+ fd = open(filename, 'r')
+ if fd == None:
+ logging.error(' Reading setup file %s'%filename)
+ else:# set random seed
+ logging.info(' Read setup for memosono from file %s'%filename)
+ lines = fd.readlines()
+ index = 0
+
+ # Load variables
+ while lines[index][0] != '#':
+ zw = lines[index].split('=')
+ zw[1] = zw[1][:-1]
+ if len(zw) is not 0:
+ data[zw[0]]=zw[1]
+ index += 1
+ index += 1
+ data['size'] = str(size)
+
+ # Load cards data
+ tile_number = 0
+ card_num = len(lines)-index
+ while tile_number < card_num and tile_number <= int((size*size)/2)-1:
+ zw = lines[index].split(',')
+ if len(zw) is not 0:
+ temp1.append(zw[:8]+[ 0, 0, tile_number])
+ temp2.append(zw[8:]+[ 0, 0, tile_number])
+ tile_number += 1
+ index += 1
+ fd.close()
+
+ # Shuffle cards order
+ if data['divided']=='True':
+ random.shuffle(temp1)
+ random.shuffle(temp2)
+ temp1.extend(temp2)
+ else:
+ temp1.extend(temp2)
+ random.shuffle(temp1)
+
+ return data, temp1
+
+ def get_grid(self):
+ return self.grid
+
+ def get_data(self):
+ return self.data
+
+ def change_game(self, game_name, size):
+ tuple = self.read_config(game_name, size)
+ data = tuple[0]
+ grid = tuple[1]
+ self.load_remote(grid, data, False)
+
+
+ def load_remote(self, grid, data, signal = False):
+ self.grid = grid
+ self.data = data
+ self.emit('reset_scoreboard')
+ self.emit('change_game', self.get_data(), self.get_grid())
+ if not signal:
+ self.emit('change_game_signal', self.get_grid(), self.get_data(), self.waiting_players)
+ for buddy in self.players:
+ self.players_score[buddy] = 0
+ self.current_player = None
+ self.last_flipped = -1
+ self.last_highlight = 1
+ self.change_turn()
+ self.data['running'] = 'False'
+
+ def set_messenger(self, messenger):
+ self.messenger = messenger
+
+ def set_sensitive(self, status):
+ self.sentitive = status
+ if not status:
+ self.emit('highlight-card', self.last_highlight, False)
+ else:
+ self.emit('highlight-card', self.last_highlight, True)
+ def get_sensitive(self):
+ return self.sentitive
+
+ def get_current_player(self):
+ return self.current_player
+
+ def set_myself(self, buddy):
+ self.myself = buddy
+
+ def add_to_waiting_list(self,buddy):
+ self.players.remove(buddy)
+ self.waiting_players.append(buddy)
+ self.emit('wait_mode_buddy',buddy,True)
+
+ def rem_to_waiting_list(self,buddy):
+ self.waiting_players.remove(buddy)
+ self.players.append(buddy)
+ self.emit('wait_mode_buddy',buddy,False)
+
+ def load_waiting_list(self,list):
+ for buddy in list:
+ self.add_to_waiting_list(buddy)
+
+ def empty_waiting_list(self):
+ for buddy in self.waiting_players:
+ self.rem_to_waiting_list(buddy) \ No newline at end of file
diff --git a/games/addition/addition.mem b/games/addition/addition.mem
new file mode 100755
index 0000000..9e41bcc
--- /dev/null
+++ b/games/addition/addition.mem
@@ -0,0 +1,24 @@
+game_name=addition
+score_sound=score.wav
+win_sound=score.wav
+divided=false
+face=
+# Cards
+,,,,,,1+1,,,,,2,,,,
+,,,,,,1+2,,,,,3,,,,
+,,,,,,2+2,,,,,4,,,,
+,,,,,,2+3,,,,,5,,,,
+,,,,,,3+3,,,,,6,,,,
+,,,,,,3+4,,,,,7,,,,
+,,,,,,4+4,,,,,8,,,,
+,,,,,,4+5,,,,,9,,,,
+,,,,,,5+5,,,,,10,,,,
+,,,,,,5+6,,,,,11,,,,
+,,,,,,6+6,,,,,12,,,,
+,,,,,,6+7,,,,,13,,,,
+,,,,,,7+7,,,,,14,,,,
+,,,,,,7+8,,,,,15,,,,
+,,,,,,8+8,,,,,16,,,,
+,,,,,,8+9,,,,,17,,,,
+,,,,,,9+9,,,,,18,,,,
+,,,,,,10+9,,,,,19,,,, \ No newline at end of file
diff --git a/games/drumgit/drumgit.mem b/games/drumgit/drumgit.mem
new file mode 100755
index 0000000..482005a
--- /dev/null
+++ b/games/drumgit/drumgit.mem
@@ -0,0 +1,30 @@
+game_name=drumgit
+score_sound=score.wav
+win_sound=score.wav
+divided=False
+face=
+# Cards
+,drumkit1_b.jpg,beat1_a.wav,,,,,,,drumkit1_b.jpg,beat1_a.wav,,,,,
+,drumkit2_b.jpg,beat1_b.wav,,,,,,,drumkit2_b.jpg,beat1_b.wav,,,,,
+,drumkit3_b.jpg,beat1_c.wav,,,,,,,drumkit3_b.jpg,beat1_c.wav,,,,,
+,drumkit4_b.jpg,beat8.wav,,,,,,,drumkit4_b.jpg,beat8.wav,,,,,
+,drumkit5_b.jpg,beat2.wav,,,,,,,drumkit5_b.jpg,beat2.wav,,,,,
+,drumkit6_b.jpg,beat3.wav,,,,,,,drumkit6_b.jpg,beat3.wav,,,,,
+,drumkit7_b.jpg,beat4.wav,,,,,,,drumkit7_b.jpg,beat4.wav,,,,,
+,drumkit8_b.jpg,beat14.wav,,,,,,,drumkit8_b.jpg,beat14.wav,,,,,
+,drumkit9_b.jpg,beat6_2.wav,,,,,,,drumkit9_b.jpg,beat6_2.wav,,,,,
+,drumkit10_b.jpg,beat16.wav,,,,,,,drumkit10_b.jpg,beat16.wav,,,,,
+,drumkit11_b.jpg,beat17.wav,,,,,,,drumkit11_b.jpg,beat17.wav,,,,,
+,drumkit12_b.jpg,beat10.wav,,,,,,,drumkit12_b.jpg,beat10.wav,,,,,
+,guitar1_2.jpg,bending_a.wav,,,,,,,guitar1_2.jpg,bending_a.wav,,,,,
+,guitar2_2.jpg,bending_b.wav,,,,,,,guitar2_2.jpg,bending_b.wav,,,,,
+,guitar3_2.jpg,flashcomp2a.wav,,,,,,,guitar3_2.jpg,flashcomp2a.wav,,,,,
+,guitar4_2.jpg,flashcomp2b.wav,,,,,,,guitar4_2.jpg,flashcomp2b.wav,,,,,
+,guitar5_2.jpg,gedaempft.wav,,,,,,,guitar5_2.jpg,gedaempft.wav,,,,,
+,guitar6_2.jpg,ungedaempft.wav,,,,,,,guitar6_2.jpg,ungedaempft.wav,,,,,
+,guitar7_2.jpg,jimi4.wav,,,,,,,guitar7_2.jpg,jimi4.wav,,,,,
+,guitar8_2.jpg,git_hit1.wav,,,,,,,guitar8_2.jpg,git_hit1.wav,,,,,
+,guitar9_2.jpg,git_hit4.wav,,,,,,,guitar9_2.jpg,git_hit4.wav,,,,,
+,guitar10_2.jpg,guitcello.wav,,,,,,,guitar10_2.jpg,guitcello.wav,,,,,
+,guitar11_2.jpg,flasholet4.wav,,,,,,,guitar11_2.jpg,flasholet4.wav,,,,,
+,guitar12_2.jpg,jimi1.wav,,,,,,,guitar12_2.jpg,jimi1.wav,,,,, \ No newline at end of file
diff --git a/games/letters1/letters1.mem b/games/letters1/letters1.mem
new file mode 100755
index 0000000..cda6e27
--- /dev/null
+++ b/games/letters1/letters1.mem
@@ -0,0 +1,25 @@
+game_name=letters1
+score_sound=score.wav
+win_sound=score.wav
+divided=True
+face1=1
+face2=2
+# Cards
+1,,,A,,,,,2,,,a,,,,
+1,,,E,,,,,2,,,e,,,,
+1,,,I,,,,,2,,,i,,,,
+1,,,O,,,,,2,,,o,,,,
+1,,,U,,,,,2,,,u,,,,
+1,,,B,,,,,2,,,b,,,,
+1,,,C,,,,,2,,,c,,,,
+1,,,D,,,,,2,,,d,,,,
+1,,,F,,,,,2,,,f,,,,
+1,,,G,,,,,2,,,g,,,,
+1,,,H,,,,,2,,,h,,,,
+1,,,J,,,,,2,,,j,,,,
+1,,,K,,,,,2,,,k,,,,
+1,,,L,,,,,2,,,l,,,,
+1,,,M,,,,,2,,,m,,,,
+1,,,N,,,,,2,,,n,,,,
+1,,,P,,,,,2,,,p,,,,
+1,,,Q,,,,,2,,,q,,,, \ No newline at end of file
diff --git a/games/letters2/letters2.mem b/games/letters2/letters2.mem
new file mode 100755
index 0000000..ff806a9
--- /dev/null
+++ b/games/letters2/letters2.mem
@@ -0,0 +1,25 @@
+game_name=letters2
+score_sound=score.wav
+win_sound=score.wav
+divided=True
+face1=1
+face2=2
+# Cards
+1,,,A,,,,,2,,,a,,,,
+1,,,E,,,,,2,,,e,,,,
+1,,,I,,,,,2,,,i,,,,
+1,,,O,,,,,2,,,o,,,,
+1,,,U,,,,,2,,,u,,,,
+1,,,L,,,,,2,,,l,,,,
+1,,,M,,,,,2,,,m,,,,
+1,,,N,,,,,2,,,n,,,,
+1,,,P,,,,,2,,,p,,,,
+1,,,Q,,,,,2,,,q,,,,
+1,,,R,,,,,2,,,r,,,,
+1,,,S,,,,,2,,,s,,,,
+1,,,T,,,,,2,,,t,,,,
+1,,,V,,,,,2,,,v,,,,
+1,,,W,,,,,2,,,w,,,,
+1,,,X,,,,,2,,,x,,,,
+1,,,Y,,,,,2,,,y,,,,
+1,,,Z,,,,,2,,,z,,,, \ No newline at end of file
diff --git a/games/numbers/images/01x.jpg b/games/numbers/images/01x.jpg
new file mode 100755
index 0000000..4b8b35a
--- /dev/null
+++ b/games/numbers/images/01x.jpg
Binary files differ
diff --git a/games/numbers/images/02x.jpg b/games/numbers/images/02x.jpg
new file mode 100755
index 0000000..bfd6f1b
--- /dev/null
+++ b/games/numbers/images/02x.jpg
Binary files differ
diff --git a/games/numbers/images/03x.jpg b/games/numbers/images/03x.jpg
new file mode 100755
index 0000000..44329a2
--- /dev/null
+++ b/games/numbers/images/03x.jpg
Binary files differ
diff --git a/games/numbers/images/04x.jpg b/games/numbers/images/04x.jpg
new file mode 100755
index 0000000..63c1d8f
--- /dev/null
+++ b/games/numbers/images/04x.jpg
Binary files differ
diff --git a/games/numbers/images/05x.jpg b/games/numbers/images/05x.jpg
new file mode 100755
index 0000000..0e0df29
--- /dev/null
+++ b/games/numbers/images/05x.jpg
Binary files differ
diff --git a/games/numbers/images/06x.jpg b/games/numbers/images/06x.jpg
new file mode 100755
index 0000000..be5b5cf
--- /dev/null
+++ b/games/numbers/images/06x.jpg
Binary files differ
diff --git a/games/numbers/images/07x.jpg b/games/numbers/images/07x.jpg
new file mode 100755
index 0000000..17f09bb
--- /dev/null
+++ b/games/numbers/images/07x.jpg
Binary files differ
diff --git a/games/numbers/images/08x.jpg b/games/numbers/images/08x.jpg
new file mode 100755
index 0000000..8ce3123
--- /dev/null
+++ b/games/numbers/images/08x.jpg
Binary files differ
diff --git a/games/numbers/images/09x.jpg b/games/numbers/images/09x.jpg
new file mode 100755
index 0000000..5120b45
--- /dev/null
+++ b/games/numbers/images/09x.jpg
Binary files differ
diff --git a/games/numbers/images/10x.jpg b/games/numbers/images/10x.jpg
new file mode 100755
index 0000000..866446f
--- /dev/null
+++ b/games/numbers/images/10x.jpg
Binary files differ
diff --git a/games/numbers/images/11x.jpg b/games/numbers/images/11x.jpg
new file mode 100755
index 0000000..93a949c
--- /dev/null
+++ b/games/numbers/images/11x.jpg
Binary files differ
diff --git a/games/numbers/images/12x.jpg b/games/numbers/images/12x.jpg
new file mode 100755
index 0000000..1e4bf75
--- /dev/null
+++ b/games/numbers/images/12x.jpg
Binary files differ
diff --git a/games/numbers/images/13x.jpg b/games/numbers/images/13x.jpg
new file mode 100755
index 0000000..708f705
--- /dev/null
+++ b/games/numbers/images/13x.jpg
Binary files differ
diff --git a/games/numbers/images/14x.jpg b/games/numbers/images/14x.jpg
new file mode 100755
index 0000000..9ea6403
--- /dev/null
+++ b/games/numbers/images/14x.jpg
Binary files differ
diff --git a/games/numbers/images/15x.jpg b/games/numbers/images/15x.jpg
new file mode 100755
index 0000000..7a57cf8
--- /dev/null
+++ b/games/numbers/images/15x.jpg
Binary files differ
diff --git a/games/numbers/numbers.mem b/games/numbers/numbers.mem
new file mode 100755
index 0000000..b1a3839
--- /dev/null
+++ b/games/numbers/numbers.mem
@@ -0,0 +1,22 @@
+game_name=numbers
+score_sound=score.wav
+win_sound=score.wav
+divided=True
+face1=1
+face2=2
+# Cards
+1,,01.wav,1,,,,,2,01x.jpg,01.wav,,,,,
+1,,02.wav,2,,,,,2,02x.jpg,02.wav,,,,,
+1,,03.wav,3,,,,,2,03x.jpg,03.wav,,,,,
+1,,04.wav,4,,,,,2,04x.jpg,04.wav,,,,,
+1,,05.wav,5,,,,,2,05x.jpg,05.wav,,,,,
+1,,06.wav,6,,,,,2,06x.jpg,06.wav,,,,,
+1,,07.wav,7,,,,,2,07x.jpg,07.wav,,,,,
+1,,08.wav,8,,,,,2,08x.jpg,08.wav,,,,,
+1,,09.wav,9,,,,,2,09x.jpg,09.wav,,,,,
+1,,10.wav,10,,,,,2,10x.jpg,10.wav,,,,,
+1,,11.wav,11,,,,,2,11x.jpg,11.wav,,,,,
+1,,12.wav,12,,,,,2,12x.jpg,12.wav,,,,,
+1,,13.wav,13,,,,,2,13x.jpg,13.wav,,,,,
+1,,14.wav,14,,,,,2,14x.jpg,14.wav,,,,,
+1,,15.wav,15,,,,,2,15x.jpg,15.wav,,,,, \ No newline at end of file
diff --git a/games/phonemes/images/agua1.jpg b/games/phonemes/images/agua1.jpg
new file mode 100755
index 0000000..3175d47
--- /dev/null
+++ b/games/phonemes/images/agua1.jpg
Binary files differ
diff --git a/games/phonemes/images/agua2.jpg b/games/phonemes/images/agua2.jpg
new file mode 100755
index 0000000..e680fc1
--- /dev/null
+++ b/games/phonemes/images/agua2.jpg
Binary files differ
diff --git a/games/phonemes/images/bola1.jpg b/games/phonemes/images/bola1.jpg
new file mode 100755
index 0000000..8cb1e53
--- /dev/null
+++ b/games/phonemes/images/bola1.jpg
Binary files differ
diff --git a/games/phonemes/images/bola2.jpg b/games/phonemes/images/bola2.jpg
new file mode 100755
index 0000000..1531c51
--- /dev/null
+++ b/games/phonemes/images/bola2.jpg
Binary files differ
diff --git a/games/phonemes/images/casa1.jpg b/games/phonemes/images/casa1.jpg
new file mode 100755
index 0000000..628fab9
--- /dev/null
+++ b/games/phonemes/images/casa1.jpg
Binary files differ
diff --git a/games/phonemes/images/casa2.jpg b/games/phonemes/images/casa2.jpg
new file mode 100755
index 0000000..40892d9
--- /dev/null
+++ b/games/phonemes/images/casa2.jpg
Binary files differ
diff --git a/games/phonemes/images/ema1.jpg b/games/phonemes/images/ema1.jpg
new file mode 100755
index 0000000..64c6706
--- /dev/null
+++ b/games/phonemes/images/ema1.jpg
Binary files differ
diff --git a/games/phonemes/images/ema2.jpg b/games/phonemes/images/ema2.jpg
new file mode 100755
index 0000000..3e20812
--- /dev/null
+++ b/games/phonemes/images/ema2.jpg
Binary files differ
diff --git a/games/phonemes/images/frutas1.jpg b/games/phonemes/images/frutas1.jpg
new file mode 100755
index 0000000..925d8e8
--- /dev/null
+++ b/games/phonemes/images/frutas1.jpg
Binary files differ
diff --git a/games/phonemes/images/frutas2.jpg b/games/phonemes/images/frutas2.jpg
new file mode 100755
index 0000000..a7a178c
--- /dev/null
+++ b/games/phonemes/images/frutas2.jpg
Binary files differ
diff --git a/games/phonemes/images/homem1.jpg b/games/phonemes/images/homem1.jpg
new file mode 100755
index 0000000..b08e612
--- /dev/null
+++ b/games/phonemes/images/homem1.jpg
Binary files differ
diff --git a/games/phonemes/images/homem2.jpg b/games/phonemes/images/homem2.jpg
new file mode 100755
index 0000000..0d3d5e1
--- /dev/null
+++ b/games/phonemes/images/homem2.jpg
Binary files differ
diff --git a/games/phonemes/images/ioio1.jpg b/games/phonemes/images/ioio1.jpg
new file mode 100755
index 0000000..aa3ba6d
--- /dev/null
+++ b/games/phonemes/images/ioio1.jpg
Binary files differ
diff --git a/games/phonemes/images/ioio2.jpg b/games/phonemes/images/ioio2.jpg
new file mode 100755
index 0000000..d339f6a
--- /dev/null
+++ b/games/phonemes/images/ioio2.jpg
Binary files differ
diff --git a/games/phonemes/images/kiwi1.jpg b/games/phonemes/images/kiwi1.jpg
new file mode 100755
index 0000000..cd9e24d
--- /dev/null
+++ b/games/phonemes/images/kiwi1.jpg
Binary files differ
diff --git a/games/phonemes/images/kiwi2.jpg b/games/phonemes/images/kiwi2.jpg
new file mode 100755
index 0000000..7c7250b
--- /dev/null
+++ b/games/phonemes/images/kiwi2.jpg
Binary files differ
diff --git a/games/phonemes/images/ovo1.jpg b/games/phonemes/images/ovo1.jpg
new file mode 100755
index 0000000..fc83ec4
--- /dev/null
+++ b/games/phonemes/images/ovo1.jpg
Binary files differ
diff --git a/games/phonemes/images/ovo2.jpg b/games/phonemes/images/ovo2.jpg
new file mode 100755
index 0000000..8876749
--- /dev/null
+++ b/games/phonemes/images/ovo2.jpg
Binary files differ
diff --git a/games/phonemes/images/peixe1.jpg b/games/phonemes/images/peixe1.jpg
new file mode 100755
index 0000000..0e7c1d0
--- /dev/null
+++ b/games/phonemes/images/peixe1.jpg
Binary files differ
diff --git a/games/phonemes/images/peixe2.jpg b/games/phonemes/images/peixe2.jpg
new file mode 100755
index 0000000..daab513
--- /dev/null
+++ b/games/phonemes/images/peixe2.jpg
Binary files differ
diff --git a/games/phonemes/images/queijo1.jpg b/games/phonemes/images/queijo1.jpg
new file mode 100755
index 0000000..e23c8c2
--- /dev/null
+++ b/games/phonemes/images/queijo1.jpg
Binary files differ
diff --git a/games/phonemes/images/queijo2.jpg b/games/phonemes/images/queijo2.jpg
new file mode 100755
index 0000000..ed744b8
--- /dev/null
+++ b/games/phonemes/images/queijo2.jpg
Binary files differ
diff --git a/games/phonemes/images/roda1.jpg b/games/phonemes/images/roda1.jpg
new file mode 100755
index 0000000..8df6d11
--- /dev/null
+++ b/games/phonemes/images/roda1.jpg
Binary files differ
diff --git a/games/phonemes/images/roda2.jpg b/games/phonemes/images/roda2.jpg
new file mode 100755
index 0000000..d9a213e
--- /dev/null
+++ b/games/phonemes/images/roda2.jpg
Binary files differ
diff --git a/games/phonemes/images/sapo1.jpg b/games/phonemes/images/sapo1.jpg
new file mode 100755
index 0000000..4409d47
--- /dev/null
+++ b/games/phonemes/images/sapo1.jpg
Binary files differ
diff --git a/games/phonemes/images/sapo2.jpg b/games/phonemes/images/sapo2.jpg
new file mode 100755
index 0000000..632fb6a
--- /dev/null
+++ b/games/phonemes/images/sapo2.jpg
Binary files differ
diff --git a/games/phonemes/images/uva1.jpg b/games/phonemes/images/uva1.jpg
new file mode 100755
index 0000000..b4f702c
--- /dev/null
+++ b/games/phonemes/images/uva1.jpg
Binary files differ
diff --git a/games/phonemes/images/uva2.jpg b/games/phonemes/images/uva2.jpg
new file mode 100755
index 0000000..c0242f5
--- /dev/null
+++ b/games/phonemes/images/uva2.jpg
Binary files differ
diff --git a/games/phonemes/images/zebra1.jpg b/games/phonemes/images/zebra1.jpg
new file mode 100755
index 0000000..46d2516
--- /dev/null
+++ b/games/phonemes/images/zebra1.jpg
Binary files differ
diff --git a/games/phonemes/images/zebra2.jpg b/games/phonemes/images/zebra2.jpg
new file mode 100755
index 0000000..6002fd8
--- /dev/null
+++ b/games/phonemes/images/zebra2.jpg
Binary files differ
diff --git a/games/phonemes/phonemes.mem b/games/phonemes/phonemes.mem
new file mode 100755
index 0000000..a28d4ba
--- /dev/null
+++ b/games/phonemes/phonemes.mem
@@ -0,0 +1,22 @@
+game_name=phonemes
+score_sound=score.wav
+win_sound=score.wav
+divided=True
+face1=1
+face2=2
+# Cards
+1,agua1.jpg,agua1.wav,,,,,Á_ _ _,2,agua2.jpg,agua2.wav,,,,,_GUA
+1,bola1.jpg,bola1.wav,,,,,BO_ _,2,bola2.jpg,bola2.wav,,,,,_ _LA
+1,casa1.jpg,casa1.wav,,,,,CA_ _,2,casa2.jpg,casa2.wav,,,,,_ _SA
+1,ema1.jpg,ema1.wav,,,,,E_ _,2,ema2.jpg,ema2.wav,,,,,_MA
+1,frutas1.jpg,frutas1.wav,,,,,FRU_ _ _,2,frutas2.jpg,frutas2.wav,,,,,_ _ _TAS
+1,homem1.jpg,homem1.wav,,,,,HO_ _ _,2,homem2.jpg,homem2.wav,,,,,_ _MEM
+1,ioio1.jpg,ioio1.wav,,,,,IO_ _,2,ioio2.jpg,ioio2.wav,,,,,_ _IO
+1,kiwi1.jpg,kiwi1.wav,,,,,KI_ _,2,kiwi2.jpg,kiwi2.wav,,,,,_ _WI
+1,ovo1.jpg,ovo1.wav,,,,,O_ _,2,ovo2.jpg,ovo2.wav,,,,,_VO
+1,peixe1.jpg,peixe1.wav,,,,,PEI_ _,2,peixe2.jpg,peixe2.wav,,,,,_ _ _XE
+1,queijo1.jpg,queijo1.wav,,,,,QUEI_ _,2,queijo2.jpg,queijo2.wav,,,,,_ _ _ _JO
+1,roda1.jpg,roda1.wav,,,,,RO_ _,2,roda2.jpg,roda2.wav,,,,,_ _DA
+1,sapo1.jpg,sapo1.wav,,,,,SA_ _,2,sapo2.jpg,sapo2.wav,,,,,_ _PO
+1,uva1.jpg,uva1.wav,,,,,U_ _,2,uva2.jpg,uva2.wav,,,,,_VA
+1,zebra1.jpg,zebra1.wav,,,,,ZE_ _ _,2,zebra2.jpg,zebra2.wav,,,,,_ _BRA \ No newline at end of file
diff --git a/images/card-text.svg b/images/card-text.svg
new file mode 100755
index 0000000..f095605
--- /dev/null
+++ b/images/card-text.svg
@@ -0,0 +1,126 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" [
+ <!ENTITY ns_svg "http://www.w3.org/2000/svg">
+ <!ENTITY ns_xlink "http://www.w3.org/1999/xlink">
+ <!ENTITY stroke_color "#ffffff">
+ <!ENTITY text_color "#888888">
+]>
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://web.resource.org/cc/"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ width="260"
+ height="260"
+ id="svg2"
+ sodipodi:version="0.32"
+ inkscape:version="0.45"
+ version="1.0"
+ sodipodi:docname="card-text.svg"
+ sodipodi:docbase="/home/msgodoi/olpc/sugar-jhbuild/build/share/activities/Memonew.activity/images"
+ inkscape:output_extension="org.inkscape.output.svg.inkscape"
+ sodipodi:modified="true">
+ <defs
+ id="defs4" />
+ <sodipodi:namedview
+ id="base"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ gridtolerance="10000"
+ guidetolerance="10"
+ objecttolerance="10"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:zoom="2.4769231"
+ inkscape:cx="130"
+ inkscape:cy="130"
+ inkscape:document-units="px"
+ inkscape:current-layer="layer1"
+ width="260px"
+ height="260px"
+ inkscape:window-width="1434"
+ inkscape:window-height="848"
+ inkscape:window-x="0"
+ inkscape:window-y="0"
+ borderlayer="true" />
+ <metadata
+ id="metadata7">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <g
+ inkscape:label="Layer 1"
+ inkscape:groupmode="layer"
+ id="layer1"
+ transform="translate(126.73047,-9.5643997e-3)">
+ <text
+ xml:space="preserve"
+ style="font-size:55px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:condensed;text-align:center;line-height:80.00000119%;writing-mode:lr-tb;text-anchor:middle;fill:&text_color;;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:DejaVu Sans"
+ x="4.2810593"
+ y="45.200275"
+ id="text2212"
+ sodipodi:linespacing="80.000001%"
+ transform="scale(0.8898189,1.1238241)"><tspan
+ sodipodi:role="line"
+ id="tspan2214"
+ x="4.2810593"
+ y="45.200275">card_line1</tspan></text>
+ <text
+ xml:space="preserve"
+ style="font-size:55px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:condensed;text-align:center;line-height:80.00000119%;writing-mode:lr-tb;text-anchor:middle;fill:&text_color;;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:DejaVu Sans"
+ x="4.5251999"
+ y="158.3905"
+ id="text7222"
+ sodipodi:linespacing="80.000001%"
+ transform="scale(0.8898189,1.1238241)"><tspan
+ sodipodi:role="line"
+ id="tspan7224"
+ x="4.5251999"
+ y="158.3905">card_line3</tspan></text>
+ <text
+ xml:space="preserve"
+ style="font-size:55px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:condensed;text-align:center;line-height:80.00000119%;writing-mode:lr-tb;text-anchor:middle;fill:&text_color;;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:DejaVu Sans"
+ x="4.6960983"
+ y="101.79538"
+ id="text7226"
+ sodipodi:linespacing="80.000001%"
+ transform="scale(0.8898189,1.1238241)"><tspan
+ sodipodi:role="line"
+ id="tspan7228"
+ x="4.6960983"
+ y="101.79538">card_line2</tspan></text>
+ <text
+ xml:space="preserve"
+ style="font-size:55px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:condensed;text-align:center;line-height:80.00000119%;writing-mode:lr-tb;text-anchor:middle;fill:&text_color;;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:DejaVu Sans"
+ x="3.7683642"
+ y="214.98558"
+ id="text7230"
+ sodipodi:linespacing="80.000001%"
+ transform="scale(0.8898189,1.1238241)"><tspan
+ sodipodi:role="line"
+ id="tspan7232"
+ x="3.7683642"
+ y="214.98558">card_line4</tspan></text>
+ <text
+ xml:space="preserve"
+ style="font-size:240px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:condensed;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;fill:&text_color;;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:DejaVu Sans"
+ x="-80.34375"
+ y="217.49004"
+ id="text2210"
+ sodipodi:linespacing="125%"><tspan
+ sodipodi:role="line"
+ id="tspan2212"
+ x="-80.34375"
+ y="217.49004">card_text</tspan></text>
+ </g>
+</svg>
diff --git a/images/card.svg b/images/card.svg
new file mode 100755
index 0000000..5db83ce
--- /dev/null
+++ b/images/card.svg
@@ -0,0 +1,79 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" [
+ <!ENTITY ns_svg "http://www.w3.org/2000/svg">
+ <!ENTITY ns_xlink "http://www.w3.org/1999/xlink">
+ <!ENTITY stroke_color "#000000">
+ <!ENTITY fill_color "#888888">
+ <!ENTITY opacity "0">
+]>
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://web.resource.org/cc/"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ width="size_card1"
+ height="size_card1"
+ id="svg2"
+ sodipodi:version="0.32"
+ inkscape:version="0.45"
+ sodipodi:modified="true"
+ version="1.0">
+ <defs
+ id="defs4" />
+ <sodipodi:namedview
+ id="base"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ gridtolerance="10000"
+ guidetolerance="10"
+ objecttolerance="10"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:zoom="4"
+ inkscape:cx="71.742462"
+ inkscape:cy="67.822008"
+ inkscape:document-units="px"
+ inkscape:current-layer="layer1"
+ width="119px"
+ height="119px"
+ inkscape:window-width="1434"
+ inkscape:window-height="848"
+ inkscape:window-x="0"
+ inkscape:window-y="0" />
+ <metadata
+ id="metadata7">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <g
+ inkscape:label="Layer 1"
+ inkscape:groupmode="layer"
+ id="layer1">
+ <rect
+ style="fill:&stroke_color;;fill-opacity:0;stroke:&stroke_color;;stroke-width:6;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ id="rect2160"
+ width="size_card2"
+ height="size_card2"
+ x="3.0095644"
+ y="3.0095644"
+ ry="9.8352585" />
+ <rect
+ style="fill:&fill_color;;fill-opacity:&opacity;;stroke:&fill_color;;stroke-width:6;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ id="rect3133"
+ width="size_card3"
+ height="size_card3"
+ x="8.7060242"
+ y="8.7060242"
+ ry="4.1414652" />
+ </g>
+</svg>
diff --git a/images/score.svg b/images/score.svg
new file mode 100755
index 0000000..00a996a
--- /dev/null
+++ b/images/score.svg
@@ -0,0 +1,81 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" [
+ <!ENTITY ns_svg "http://www.w3.org/2000/svg">
+ <!ENTITY ns_xlink "http://www.w3.org/1999/xlink">
+ <!ENTITY stroke_color "#020202">
+ <!ENTITY fill_color "#B2B2B2">
+]>
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://web.resource.org/cc/"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ width="42"
+ height="42"
+ id="svg2"
+ sodipodi:version="0.32"
+ inkscape:version="0.45"
+ version="1.0"
+ sodipodi:docname="score.svg"
+ sodipodi:docbase="/home/msgodoi/olpc/sugar-jhbuild/build/share/activities/Memorize.activity"
+ inkscape:output_extension="org.inkscape.output.svg.inkscape"
+ sodipodi:modified="true">
+ <defs
+ id="defs4" />
+ <sodipodi:namedview
+ id="base"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ gridtolerance="10000"
+ guidetolerance="10"
+ objecttolerance="10"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:zoom="12.238095"
+ inkscape:cx="21"
+ inkscape:cy="21"
+ inkscape:document-units="px"
+ inkscape:current-layer="layer1"
+ width="42px"
+ height="42px"
+ inkscape:window-width="806"
+ inkscape:window-height="718"
+ inkscape:window-x="580"
+ inkscape:window-y="114" />
+ <metadata
+ id="metadata7">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <g
+ inkscape:label="Layer 1"
+ inkscape:groupmode="layer"
+ id="layer1">
+ <rect
+ style="fill:&fill_color;;fill-opacity:1;fill-rule:evenodd;stroke:&stroke_color;;stroke-width:3.5;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ id="rect7017"
+ width="30.046175"
+ height="30.046175"
+ x="1.9769126"
+ y="1.9769124"
+ ry="4.5299301" />
+ <rect
+ style="fill:&fill_color;;fill-opacity:1;fill-rule:evenodd;stroke:&stroke_color;;stroke-width:3.5;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ id="rect3133"
+ width="30.046175"
+ height="30.046175"
+ x="9.9769125"
+ y="9.9769125"
+ ry="4.5299301" />
+ </g>
+</svg>
diff --git a/images/stock-buddy.svg b/images/stock-buddy.svg
new file mode 100755
index 0000000..bad856f
--- /dev/null
+++ b/images/stock-buddy.svg
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 12.0.1, SVG Export Plug-In . SVG Version: 6.00 Build 51448) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" [
+ <!ENTITY ns_svg "http://www.w3.org/2000/svg">
+ <!ENTITY ns_xlink "http://www.w3.org/1999/xlink">
+ <!ENTITY stroke_color "#020202">
+ <!ENTITY fill_color "#B2B2B2">
+]>
+<svg version="1.1" id="Icon" xmlns="&ns_svg;" xmlns:xlink="&ns_xlink;" width="37.855" height="53.047"
+ viewBox="0 0 37.855 53.047" overflow="visible" enable-background="new 0 0 37.855 53.047" xml:space="preserve">
+<path fill="&fill_color;" stroke="&stroke_color;" stroke-width="3.5" d="M24.787,34.124l10.1,10.1c0.752,0.75,1.217,1.785,1.217,2.932
+ c0,2.287-1.855,4.143-4.146,4.143c-1.145,0-2.178-0.463-2.932-1.211l-10.1-10.102l-10.1,10.1c-0.75,0.75-1.787,1.211-2.933,1.211
+ c-2.285,0-4.142-1.854-4.142-4.141c0-1.146,0.465-2.184,1.212-2.934l10.103-10.1L2.963,24.02c-0.747-0.749-1.212-1.785-1.212-2.93
+ c0-2.289,1.853-4.145,4.145-4.145c1.143,0,2.18,0.465,2.93,1.214L18.925,28.26l10.1-10.102c0.754-0.749,1.787-1.214,2.934-1.214
+ c2.289,0,4.146,1.856,4.146,4.145c0,1.145-0.467,2.179-1.217,2.93L24.787,34.124z"/>
+<circle fill="&fill_color;" stroke="&stroke_color;" stroke-width="3.5" cx="18.925" cy="9.872" r="8.122"/>
+</svg>
+
diff --git a/infopanel.py b/infopanel.py
deleted file mode 100644
index 95defa6..0000000
--- a/infopanel.py
+++ /dev/null
@@ -1,20 +0,0 @@
-import hippo
-import pango
-from sugar.graphics import color
-
-class InfoPanel(hippo.CanvasBox):
- def __init__(self):
- hippo.CanvasBox.__init__(self, spacing=4, padding=5,
- orientation=hippo.ORIENTATION_VERTICAL)
- self.status_box = hippo.CanvasBox(spacing=4, padding=5,
- orientation=hippo.ORIENTATION_VERTICAL)
- self.append(self.status_box)
-
- def show(self, text):
- textwidget = hippo.CanvasText(text=text,
- font_desc=pango.FontDescription('Sans 16'),
- color=color.WHITE.get_int(),
- xalign=hippo.ALIGNMENT_CENTER)
- self.status_box.remove_all()
- self.status_box.append(textwidget)
-
diff --git a/memorize.dtd b/memorize.dtd
new file mode 100644
index 0000000..40542e8
--- /dev/null
+++ b/memorize.dtd
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+
+<!ELEMENT memorize (#PCDATA|pair)*>
+<!ATTLIST memorize
+ name CDATA #REQUIRED
+ scoresnd CDATA #IMPLIED
+ winsnd CDATA #IMPLIED
+ divided CDATA #IMPLIED
+ face CDATA #IMPLIED
+>
+
+<!ELEMENT pair (#PCDATA)* >
+<!ATTLIST pair
+ aimg CDATA #IMPLIED
+ asnd CDATA #IMPLIED
+ achar CDATA #IMPLIED
+ bimg CDATA #IMPLIED
+ bsnd CDATA #IMPLIED
+ bchar CDATA #IMPLIED
+ color CDATA #IMPLIED
+>
diff --git a/memorizetoolbar.py b/memorizetoolbar.py
new file mode 100755
index 0000000..9736e3d
--- /dev/null
+++ b/memorizetoolbar.py
@@ -0,0 +1,99 @@
+#! /usr/bin/env python
+#
+# Copyright (C) 2007, One Laptop Per Child
+#
+# Muriel de Souza Godoi - muriel@laptop.org
+#
+# 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 2 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+#
+
+import logging
+from gettext import gettext as _
+
+import gtk
+import os
+
+from sugar.graphics.toolbutton import ToolButton
+from sugar.graphics.combobox import ComboBox
+
+class MemorizeToolbar(gtk.Toolbar):
+ __gtype_name__ = 'MemoryToolbar'
+
+ def __init__(self, activity):
+ gtk.Toolbar.__init__(self)
+ self.activity = activity
+ self._lock = True
+
+
+ # Reset Button
+ self._reset_button = ToolButton('insert-image')
+ self._reset_button.connect('clicked', self._game_changed_cb)
+ self.insert(self._reset_button, -1)
+ self._reset_button.show()
+
+ # Separator
+ separator = gtk.SeparatorToolItem()
+ separator.set_draw(True)
+ self.insert(separator, -1)
+
+ # Change game combobox
+ self.games = os.listdir(os.path.join(os.path.dirname(__file__), 'games'))
+ self.games.sort()
+ self._game_combo = ComboBox()
+ for i, f in enumerate(self.games):
+ self._game_combo.append_item(i, f)
+ if f == 'numbers':
+ self._game_combo.set_active(i)
+ self._game_combo.connect('changed', self._game_changed_cb)
+ self._add_widget(self._game_combo)
+
+ separator = gtk.SeparatorToolItem()
+ separator.set_draw(True)
+ self.insert(separator, -1)
+ self._lock = False
+
+ # Change size combobox
+ self._size_combo = ComboBox()
+ self._sizes = ['4 X 4', '5 X 5', '6 X 6']
+ for i, f in enumerate(self._sizes):
+ self._size_combo.append_item(i, f)
+ if f == '4 X 4':
+ self._size_combo.set_active(i)
+ self._size_combo.connect('changed', self._game_changed_cb)
+ self._add_widget(self._size_combo)
+
+ def _add_widget(self, widget, expand=False):
+ tool_item = gtk.ToolItem()
+ tool_item.set_expand(expand)
+ tool_item.add(widget)
+ widget.show()
+ self.insert(tool_item, -1)
+ tool_item.show()
+
+ def _game_changed_cb(self, combobox):
+ if not self._lock:
+ game_name = self.games[self._game_combo.get_active()]
+ game_size = int(self._sizes[self._size_combo.get_active()][0])
+ self.activity.change_game(game_name, game_size)
+
+ def update_toolbar(self, widget, data, grid):
+ game = data.get('game_name')
+ size = data.get('size')
+ self._lock = True
+ game_index = self.games.index(game)
+ self._game_combo.set_active(game_index)
+ size_index = self._sizes.index(size+' X '+size)
+ self._size_combo.set_active(int(size_index))
+ self._lock = False
diff --git a/memosono.dtd b/memosono.dtd
deleted file mode 100644
index 713c779..0000000
--- a/memosono.dtd
+++ /dev/null
@@ -1,15 +0,0 @@
-<?xml version="1.0" encoding="ISO-8859-1"?>
-
-<!ELEMENT memosono (#PCDATA|pair)*>
-<!ATTLIST memosono
- name CDATA #REQUIRED
->
-
-<!ELEMENT pair (#PCDATA)* >
-<!ATTLIST pair
- aimg CDATA #IMPLIED
- asnd CDATA #IMPLIED
- bimg CDATA #IMPLIED
- bsnd CDATA #IMPLIED
- color CDATA #IMPLIED
->
diff --git a/memosonoactivity.py b/memosonoactivity.py
deleted file mode 100755
index 48783c9..0000000
--- a/memosonoactivity.py
+++ /dev/null
@@ -1,290 +0,0 @@
-#! /usr/bin/env python
-#
-# Copyright (C) 2006, 2007 Simon Schampijer
-#
-# 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 2 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., 675 Mass Ave, Cambridge, MA 02139, USA.
-#
-
-from gettext import gettext as _
-
-import gobject
-import gtk
-import os
-import logging
-import telepathy
-import telepathy.client
-import hippo
-
-from sugar.activity.activity import Activity
-from sugar.activity.activity import ActivityToolbox
-from sugar.presence import presenceservice
-
-from tubeconn import TubeConnection
-from playview import PlayView
-from buddiespanel import BuddiesPanel
-from infopanel import InfoPanel
-from controller import Controller
-
-
-_logger = logging.getLogger('activity')
-
-class MemosonoActivity(Activity):
- def __init__(self, handle):
- Activity.__init__(self, handle)
-
- _logger.debug('Starting Memosono activity...')
-
- self.set_title(_('Memsosono Activity'))
-
- w = self.get_screen().get_width()
- h = self.get_screen().get_height()
- ### FIXME: do better grid calculation
- if w <= 1024:
- self.pv = PlayView(600, 600, 32)
- else:
- self.pv = PlayView(800, 800, 32)
-
- self.buddies_panel = BuddiesPanel()
-
- self.info_panel = InfoPanel()
-
- vbox = hippo.CanvasBox(spacing=4,
- orientation=hippo.ORIENTATION_VERTICAL)
-
- hbox = hippo.CanvasBox(spacing=4,
- orientation=hippo.ORIENTATION_HORIZONTAL)
-
- hbox.append(self.buddies_panel)
- hbox.append(self.pv, hippo.PACK_EXPAND)
-
- vbox.append(hbox, hippo.PACK_EXPAND)
- vbox.append(self.info_panel, hippo.PACK_END)
-
- canvas = hippo.Canvas()
- canvas.set_root(vbox)
- self.set_canvas(canvas)
- self.show_all()
-
- toolbox = ActivityToolbox(self)
- self.set_toolbox(toolbox)
- toolbox.show()
-
- self.pservice = presenceservice.get_instance()
-
- name, path = self.pservice.get_preferred_connection()
- self.tp_conn_name = name
- self.tp_conn_path = path
- self.conn = telepathy.client.Connection(name, path)
- self.initiating = None
-
- self.ctrl = None
-
- toolbox = ActivityToolbox(self)
- self.set_toolbox(toolbox)
- toolbox.show()
-
- # connect to the in/out events of the memosono activity
- self.connect('focus_in_event', self._focus_in)
- self.connect('focus_out_event', self._focus_out)
- self.connect('destroy', self._cleanup_cb)
-
- self.info_panel.show('To play, share!')
-
- self.connect('shared', self._shared_cb)
-
- owner = self.pservice.get_owner()
- self.owner = owner
-
- if self._shared_activity:
- # we are joining the activity
- self.buddies_panel.add_watcher(owner)
- self.connect('joined', self._joined_cb)
- self._shared_activity.connect('buddy-joined', self._buddy_joined_cb)
- self._shared_activity.connect('buddy-left', self._buddy_left_cb)
- if self.get_shared():
- # oh, OK, we've already joined
- self._joined_cb()
- else:
- # we are creating the activity
- self.buddies_panel.add_player(owner)
-
- def _get_buddy(self, cs_handle):
- """Get a Buddy from a channel specific handle."""
- _logger.debug('Trying to find owner of handle %u...', cs_handle)
- group = self.text_chan[telepathy.CHANNEL_INTERFACE_GROUP]
- my_csh = group.GetSelfHandle()
- _logger.debug('My handle in that group is %u', my_csh)
- if my_csh == cs_handle:
- handle = self.conn.GetSelfHandle()
- _logger.debug('CS handle %u belongs to me, %u', cs_handle, handle)
- elif group.GetGroupFlags() & telepathy.CHANNEL_GROUP_FLAG_CHANNEL_SPECIFIC_HANDLES:
- handle = group.GetHandleOwners([cs_handle])[0]
- _logger.debug('CS handle %u belongs to %u', cs_handle, handle)
- else:
- handle = cs_handle
- _logger.debug('non-CS handle %u belongs to itself', handle)
-
- # XXX: deal with failure to get the handle owner
- assert handle != 0
-
- # XXX: we're assuming that we have Buddy objects for all contacts -
- # this might break when the server becomes scalable.
- return self.pservice.get_buddy_by_telepathy_handle(self.tp_conn_name,
- self.tp_conn_path, handle)
-
- def _shared_cb(self, activity):
- _logger.debug('My Memosono activity was shared')
- self.initiating = True
- self._setup()
-
- for buddy in self._shared_activity.get_joined_buddies():
- self.buddies_panel.add_watcher(buddy)
-
- self._shared_activity.connect('buddy-joined', self._buddy_joined_cb)
- self._shared_activity.connect('buddy-left', self._buddy_left_cb)
-
- _logger.debug('This is my activity: making a tube...')
- id = self.tubes_chan[telepathy.CHANNEL_TYPE_TUBES].OfferTube(
- telepathy.TUBE_TYPE_DBUS, 'org.fredektop.Telepathy.Tube.Memosono', {})
- _logger.debug('Tube address: %s', self.tubes_chan[telepathy.CHANNEL_TYPE_TUBES].GetDBusServerAddress(id))
- self.info_panel.show('Waiting for another player to join')
-
- # FIXME: presence service should be tubes-aware and give us more help
- # with this
- def _setup(self):
- if self._shared_activity is None:
- _logger.error('Failed to share or join activity')
- return
-
- bus_name, conn_path, channel_paths = self._shared_activity.get_channels()
-
- # Work out what our room is called and whether we have Tubes already
- room = None
- tubes_chan = None
- text_chan = None
- for channel_path in channel_paths:
- channel = telepathy.client.Channel(bus_name, channel_path)
- htype, handle = channel.GetHandle()
- if htype == telepathy.HANDLE_TYPE_ROOM:
- _logger.debug('Found our room: it has handle#%d "%s"',
- handle, self.conn.InspectHandles(htype, [handle])[0])
- room = handle
- ctype = channel.GetChannelType()
- if ctype == telepathy.CHANNEL_TYPE_TUBES:
- _logger.debug('Found our Tubes channel at %s', channel_path)
- tubes_chan = channel
- elif ctype == telepathy.CHANNEL_TYPE_TEXT:
- _logger.debug('Found our Text channel at %s', channel_path)
- text_chan = channel
-
- if room is None:
- _logger.error("Presence service didn't create a room")
- return
- if text_chan is None:
- _logger.error("Presence service didn't create a text channel")
- return
-
- # Make sure we have a Tubes channel - PS doesn't yet provide one
- if tubes_chan is None:
- _logger.debug("Didn't find our Tubes channel, requesting one...")
- tubes_chan = self.conn.request_channel(telepathy.CHANNEL_TYPE_TUBES,
- telepathy.HANDLE_TYPE_ROOM, room, True)
-
- self.tubes_chan = tubes_chan
- self.text_chan = text_chan
-
- tubes_chan[telepathy.CHANNEL_TYPE_TUBES].connect_to_signal('NewTube',
- self._new_tube_cb)
-
- def _list_tubes_reply_cb(self, tubes):
- for tube_info in tubes:
- self._new_tube_cb(*tube_info)
-
- def _list_tubes_error_cb(self, e):
- _logger.error('ListTubes() failed: %s', e)
-
- def _joined_cb(self, activity):
- if self.ctrl is not None:
- return
-
- if not self._shared_activity:
- return
-
- for buddy in self._shared_activity.get_joined_buddies():
- self.buddies_panel.add_watcher(buddy)
-
- _logger.debug('Joined an existing Memosono game')
- self.info_panel.show('Joined a game. Waiting for my turn...')
- self.initiating = False
- self._setup()
-
- _logger.debug('This is not my activity: waiting for a tube...')
- self.tubes_chan[telepathy.CHANNEL_TYPE_TUBES].ListTubes(
- reply_handler=self._list_tubes_reply_cb,
- error_handler=self._list_tubes_error_cb)
-
- def _new_tube_cb(self, id, initiator, type, service, params, state):
- _logger.debug('New tube: ID=%d initator=%d type=%d service=%s '
- 'params=%r state=%d', id, initiator, type, service,
- params, state)
-
- if (self.ctrl is None and type == telepathy.TUBE_TYPE_DBUS and
- service == 'org.fredektop.Telepathy.Tube.Memosono'):
- if state == telepathy.TUBE_STATE_LOCAL_PENDING:
- self.tubes_chan[telepathy.CHANNEL_TYPE_TUBES].AcceptTube(id)
-
- tube_conn = TubeConnection(self.conn,
- self.tubes_chan[telepathy.CHANNEL_TYPE_TUBES],
- id, group_iface=self.text_chan[telepathy.CHANNEL_INTERFACE_GROUP])
- self.ctrl = Controller(tube_conn, self.pv, self.initiating,
- self.buddies_panel, self.info_panel, self.owner,
- self._get_buddy, self)
-
- def _buddy_joined_cb(self, activity, buddy):
- _logger.debug('buddy joined')
- self.buddies_panel.add_watcher(buddy)
-
- def _buddy_left_cb(self, activity, buddy):
- _logger.debug('buddy left')
- self.buddies_panel.remove_watcher(buddy)
-
- def write_file(self, file_path):
- """Store game state in Journal.
-
- Handling the Journal is provided by Activity - we only need
- to define this method.
- """
- _logger.debug(" Write game state. ")
- f = open(file_path, 'w')
- try:
- f.write('erikos won the game')
- finally:
- f.close()
-
- def _focus_in(self, event, data=None):
- if self.ctrl != None:
- self.ctrl.cs.start()
- _logger.debug(" Memosono is visible: start csound server. ")
-
- def _focus_out(self, event, data=None):
- if self.ctrl != None:
- self.ctrl.cs.start()
- _logger.debug(" Memosono is invisible: pause csound server. ")
-
- def _cleanup_cb(self, data=None):
- if self.ctrl != None:
- self.ctrl.cs.quit()
- _logger.debug(" Memosono closes: close csound server. ")
-
diff --git a/messenger.py b/messenger.py
new file mode 100644
index 0000000..2bceab9
--- /dev/null
+++ b/messenger.py
@@ -0,0 +1,116 @@
+#! /usr/bin/env python
+#
+# Copyright (C) 2007, One Laptop Per Child
+#
+# Muriel de Souza Godoi - muriel@laptop.org
+#
+# 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 2 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+#
+
+import logging
+import dbus
+from dbus.gobject_service import ExportedGObject
+
+SERVICE = "org.laptop.Memorize"
+IFACE = SERVICE
+PATH = "/org/laptop/Memorize"
+
+_logger = logging.getLogger('memorize-activity')
+
+class Messenger(ExportedGObject):
+
+ def __init__(self, tube, is_initiator, get_buddy, game):
+ ExportedGObject.__init__(self, tube, PATH)
+ self._tube = tube
+ self.is_initiator = is_initiator
+ self._get_buddy = get_buddy
+ self.game = game
+ self.ordered_bus_names = []
+ self.entered = False
+ self._tube.watch_participants(self.participant_change_cb)
+
+ def participant_change_cb(self, added, removed):
+ if not self.entered:
+ self._tube.add_signal_receiver(self._flip_receiver, '_flip_signal', IFACE, path=PATH, sender_keyword='sender')
+ self._tube.add_signal_receiver(self._change_game_receiver, '_change_game_signal', IFACE, path=PATH, sender_keyword='sender')
+ if self.is_initiator:
+ _logger.debug('Initialising a new game, I am %s .', self._tube.get_unique_name())
+ self.player_id = self._tube.get_unique_name()
+ self.ordered_bus_names = [self.player_id]
+ self._tube.add_signal_receiver(self._hello_receiver, '_hello_signal', IFACE, path=PATH, sender_keyword='sender')
+ else:
+ self._hello_signal()
+ self.entered = True
+
+ @dbus.service.signal(IFACE, signature='')
+ def _hello_signal(self):
+ ''' Notify current players that you joined '''
+ _logger.debug('Sending hello to all')
+
+ def _hello_receiver(self, sender=None):
+ ''' Someone joined the game, so sync the new player '''
+ _logger.debug('The new player %s has joined', sender)
+ self.ordered_bus_names.append(sender)
+ self._tube.get_object(sender, PATH).load_game(self.ordered_bus_names, self.game.get_grid(), self.game.get_data(), self.game.waiting_players, dbus_interface=IFACE)
+
+ #@dbus.service.method(dbus_interface=IFACE, in_signature='asss', out_signature='')
+ @dbus.service.method(dbus_interface=IFACE, in_signature='asa(ssssssssiii)a{ss}av', out_signature='')
+ def load_game(self, bus_names, grid, data,list):
+ ''' Sync the game with with players '''
+ _logger.debug('Data received to sync game data')
+ self.ordered_bus_names = bus_names
+ self.player_id = bus_names.index(self._tube.get_unique_name())
+ self._change_game_receiver(grid,data,self.ordered_bus_names[0])
+ self.game.load_waiting_list(list)
+
+ def flip(self, widget, id):
+ ''' Notify other players that you flipped a card '''
+ _logger.debug('Sending flip message: '+str(id))
+ self._flip_signal(id)
+
+ @dbus.service.signal(IFACE, signature='n')
+ def _flip_signal(self, card_number):
+ _logger.debug('Notifing other players that you flipped: %s', str(card_number))
+ ''' Notify current players that you flipped a card '''
+
+ def _flip_receiver(self, card_number, sender=None):
+ ''' Someone flipped a card '''
+ handle = self._tube.bus_name_to_handle[sender]
+
+ if self._tube.self_handle <> handle:
+ _logger.debug('Other player flipped: %s ', str(card_number))
+ self.game.card_flipped(None, card_number, True)
+
+ def change_game(self, sender, grid, data, waiting_list):
+ ''' Notify other players that you changed the game '''
+ _logger.debug('Sending changed game message')
+ self._change_game_signal(grid, data)
+
+ @dbus.service.signal(IFACE, signature='a(ssssssssiii)a{ss}')
+ def _change_game_signal(self, grid, data):
+ _logger.debug('Notifing other players that you changed the game')
+ ''' Notify current players that you changed the game '''
+
+ def _change_game_receiver(self, grid, data, sender=None):
+ ''' Game changed by other player '''
+ handle = self._tube.bus_name_to_handle[sender]
+
+ if self._tube.self_handle <> handle:
+ _logger.debug('Game changed by other player')
+ new_grid = []
+ for card in grid:
+ new_grid.append(map(lambda x: str(x), card[:8])+[int(card[8]), int(card[9]), int(card[10])])
+ self.game.load_remote(new_grid, data, True)
+ \ No newline at end of file
diff --git a/misc/addition.mem b/misc/addition.mem
new file mode 100644
index 0000000..9521cb7
--- /dev/null
+++ b/misc/addition.mem
@@ -0,0 +1,23 @@
+<?xml version="1.0"?>
+<memorize name="addition" scoresnd="score.wav" winsnd="win.wav" divided="False" face="" >
+
+ <pair achar="1+1" bchar="2" />
+ <pair achar="1+2" bchar="3" />
+ <pair achar="2+2" bchar="4" />
+ <pair achar="2+3" bchar="5" />
+ <pair achar="3+3" bchar="6" />
+ <pair achar="3+4" bchar="7" />
+ <pair achar="4+4" bchar="8" />
+ <pair achar="4+5" bchar="9" />
+ <pair achar="5+5" bchar="10" />
+ <pair achar="5+6" bchar="11" />
+ <pair achar="6+6" bchar="12" />
+ <pair achar="6+7" bchar="13" />
+ <pair achar="7+7" bchar="14" />
+ <pair achar="7+8" bchar="15" />
+ <pair achar="8+8" bchar="16" />
+ <pair achar="8+9" bchar="17" />
+ <pair achar="9+9" bchar="18" />
+ <pair achar="10+9" bchar="19" />
+
+</memorize>
diff --git a/misc/drumgit.mem b/misc/drumgit.mem
new file mode 100644
index 0000000..67efec4
--- /dev/null
+++ b/misc/drumgit.mem
@@ -0,0 +1,24 @@
+<?xml version="1.0"?>
+<memorize name="drumgit" scoresnd="score.wav" winsnd="win.wav" divided="False" face="" >
+
+ <pair aimg="drumkit1_b.jpg" asnd="beat1_a.aiff" bimg="drumkit1_b.jpg" bsnd="beat1_a.aiff" color="100" />
+ <pair aimg="drumkit2_b.jpg" asnd="beat1_b.aiff" bimg="drumkit2_b.jpg" bsnd="beat1_b.aiff" color="100" />
+ <pair aimg="drumkit3_b.jpg" asnd="beat1_c.aiff" bimg="drumkit3_b.jpg" bsnd="beat1_c.aiff" color="100" />
+ <pair aimg="drumkit4_b.jpg" asnd="beat8.aiff" bimg="drumkit4_b.jpg" bsnd="beat8.aiff" color="100" />
+
+ <pair aimg="drumkit6_b.jpg" asnd="beat3.aiff" bimg="drumkit6_b.jpg" bsnd="beat3.aiff" color="100" />
+ <pair aimg="drumkit7_b.jpg" asnd="beat4.aiff" bimg="drumkit7_b.jpg" bsnd="beat4.aiff" color="100" />
+ <pair aimg="drumkit8_b.jpg" asnd="beat14.aiff" bimg="drumkit8_b.jpg" bsnd="beat14.aiff" color="100" />
+ <pair aimg="drumkit9_b.jpg" asnd="beat6_2.aiff" bimg="drumkit9_b.jpg" bsnd="beat6_2.aiff" color="100" />
+
+ <pair aimg="guitar1_2.jpg" asnd="bending_a.aiff" bimg="guitar1_2.jpg" bsnd="bending_a.aiff" color="100" />
+ <pair aimg="guitar2_2.jpg" asnd="bending_b.aiff" bimg="guitar2_2.jpg" bsnd="bending_b.aiff" color="100" />
+ <pair aimg="guitar3_2.jpg" asnd="flashcomp2a.aiff" bimg="guitar3_2.jpg" bsnd="flashcomp2a.aiff" color="100" />
+ <pair aimg="guitar4_2.jpg" asnd="flashcomp2b.aiff" bimg="guitar4_2.jpg" bsnd="flashcomp2b.aiff" color="100" />
+
+ <pair aimg="guitar5_2.jpg" asnd="gedaempft.aiff" bimg="guitar5_2.jpg" bsnd="gedaempft.aiff" color="100" />
+ <pair aimg="guitar6_2.jpg" asnd="gedaempft.aiff" bimg="guitar6_2.jpg" bsnd="gedaempft.aiff" color="100" />
+ <pair aimg="guitar7_2.jpg" asnd="ungedaempft.aiff" bimg="guitar7_2.jpg" bsnd="ungedaempft.aiff" color="100" />
+ <pair aimg="guitar8_2.jpg" asnd="jimi4.aiff" bimg="guitar8_2.jpg" bsnd="jimi4.aiff" color="100" />
+
+</memorize>
diff --git a/model.py b/model.py
index bb7870a..d85f603 100644
--- a/model.py
+++ b/model.py
@@ -5,7 +5,8 @@ import random
import gobject
IMAGES_PATH = 'games/drumgit/images'
-GAME_PATH = 'games/drumgit'
+SOUNDS_PATH = 'games/drumgit/sounds'
+GAME_PATH = ''
_logger = logging.getLogger('model')
@@ -14,8 +15,10 @@ class Pair(gobject.GObject):
__gproperties__ = {
'aimg' : (str, None, None, None, gobject.PARAM_READWRITE),
'asnd' : (str, None, None, None, gobject.PARAM_READWRITE),
+ 'achar' : (str, None, None, None, gobject.PARAM_READWRITE),
'bimg' : (str, None, None, None, gobject.PARAM_READWRITE),
'bsnd' : (str, None, None, None, gobject.PARAM_READWRITE),
+ 'bchar' : (str, None, None, None, gobject.PARAM_READWRITE),
'color': (gobject.TYPE_INT, 'Base', 'Base', 0, 10, 0, gobject.PARAM_READWRITE)
}
@@ -30,10 +33,14 @@ class Pair(gobject.GObject):
return self._properties["aimg"]
elif pspec.name == "asnd":
return self._properties["asnd"]
+ elif pspec.name == "achar":
+ return self._properties["achar"]
elif pspec.name == "bimg":
return self._properties["bimg"]
elif pspec.name == "bsnd":
return self._properties["bsnd"]
+ elif pspec.name == "bchar":
+ return self._properties["bchar"]
elif pspec.name == "color":
return self._properties["color"]
@@ -42,10 +49,14 @@ class Pair(gobject.GObject):
self._properties['aimg'] = value
elif name == "asnd":
self._properties["asnd"] = value
+ elif name == "achar":
+ self._properties["achar"] = value
elif name == "bimg":
self._properties["bimg"] = value
elif name == "bsnd":
self._properties["bsnd"] = value
+ elif name == "bchar":
+ self._properties["bchar"] = value
elif name == "color":
self._properties["color"] = int(value)
'''
@@ -60,19 +71,20 @@ class Model(object):
information.
'''
def __init__(self, gamepath, dtdpath, name='noname'):
- self.name = name
+ self.data = {}
self.gamepath = gamepath
self.dtdpath = dtdpath
+
try:
- self.dtd = libxml2.parseDTD(None, os.path.join(self.dtdpath, 'memosono.dtd'))
+ self.dtd = libxml2.parseDTD(None, os.path.join(self.dtdpath, 'memorize.dtd'))
except libxml2.parserError, e:
- _logger.error('No memosono.dtd found ' +str(e))
+ _logger.error('No memorize.dtd found ' +str(e))
self.dtd = None
self.ctxt = libxml2.newValidCtxt()
self.pairs = {}
self.grid = []
-
+
# used by the leader of the game to keep track of the game state
self.players = {}
self.player_active = 0
@@ -81,7 +93,6 @@ class Model(object):
self.started = 0
self.count = 0
-
def read(self, filename):
''' reades the configuration from an xml file '''
try:
@@ -97,18 +108,34 @@ class Model(object):
for elem in res:
attributes = elem.get_properties()
pair = Pair()
- for attribute in attributes:
- if(attribute.name == 'text'):
- pass
- else:
- pass
- pair.set_property(attribute.name, attribute.content)
if( elem.name == 'pair' ):
+ for attribute in attributes:
+ if(attribute.name == 'text'):
+ pass
+ else:
+ pair.set_property(attribute.name, attribute.content)
self.pairs[self.idpair] = pair
- self.idpair+=1
- elif( elem.name == 'memosono' ):
- self.name = attribute.content
-
+ self.idpair+=1
+ elif( elem.name == 'memorize' ):
+ for attribute in attributes:
+ if(attribute.name == 'text'):
+ pass
+ elif(attribute.name == 'name'):
+ self.data['game_name'] = attribute.content
+ elif(attribute.name == 'scoresnd'):
+ self.data['scoresnd'] = attribute.content
+ elif(attribute.name == 'winsnd'):
+ self.data['winsnd'] = attribute.content
+ elif(attribute.name == 'divided'):
+ self.data['divided'] = attribute.content
+ elif(attribute.name == 'divided'):
+ self.data['divided'] = attribute.content
+ elif(attribute.name == 'face'):
+ self.data['face'] = attribute.content
+ elif(attribute.name == 'face1'):
+ self.data['face1'] = attribute.content
+ elif(attribute.name == 'face2'):
+ self.data['face2'] = attribute.content
xpa.xpathFreeContext()
else:
_logger.error('Error in validation of the file')
@@ -120,8 +147,9 @@ class Model(object):
def save(self, filename):
''' saves the configuration to an xml file '''
doc = libxml2.newDoc("1.0")
- root = doc.newChild(None, "memosono", None)
- root.setProp("name", self.name)
+ root = doc.newChild(None, "memorize", None)
+ root.setProp("name", self.data['game_name'])
+ ### Fixme: add other attributes here
for key in self.pairs:
elem = root.newChild(None, "pair", None)
@@ -129,10 +157,14 @@ class Model(object):
elem.setProp("aimg", self.pairs[key].props.aimg)
if self.pairs[key].props.asnd != None:
elem.setProp("asnd", self.pairs[key].props.asnd)
+ if self.pairs[key].props.achar != None:
+ elem.setProp("achar", self.pairs[key].props.achar)
if self.pairs[key].props.bimg != None:
elem.setProp("bimg", self.pairs[key].props.bimg)
if self.pairs[key].props.bsnd != None:
elem.setProp("bsnd", self.pairs[key].props.bsnd)
+ if self.pairs[key].props.bchar != None:
+ elem.setProp("bchar", self.pairs[key].props.bchar)
elem.setProp("color", str(self.pairs[key].props.color))
if doc.validateDtd(self.ctxt, self.dtd):
@@ -140,15 +172,27 @@ class Model(object):
doc.freeDoc()
- def def_grid(self):
+ def def_grid(self, size):
''' create the grid for the play from the pairs information
and shuffles the grid so they always appear in a different
- place
+ place
+ grid [pair_key, a_or_b, flipstatus]
'''
_logger.debug(' pairs: %s', self.pairs)
+ i=0
for key in self.pairs.iterkeys():
- self.grid.append([key, 0, 0])
- self.grid.append([key, 1, 0])
+ if i < size:
+ self.grid.append([key, 0, 0])
+ self.grid.append([key, 1, 0])
+ i+=1
+ else:
+ break
+
+ numpairs = len(self.pairs)
+ if numpairs < size:
+ _logger.debug('We did not have enough pairs. requested=%s had=%s' %(numpairs, size))
+
+ self.data['size'] = numpairs
random.shuffle(self.grid)
_logger.debug(' grid: %s', self.grid)
@@ -156,10 +200,24 @@ class Model(object):
def gettile(self, tilenum):
''' gets the information of an object associated with a tile number '''
- pairkey, moch, state = self.grid[tilenum]
- obj = os.path.join(IMAGES_PATH, self.pairs[pairkey][moch])
- color = self.pairs[pairkey][2]
- return (obj, color)
+ img = None
+ snd = None
+ char = None
+ pairkey, moch, state = self.grid[tilenum]
+ if moch == 0:
+ if self.pairs[pairkey].props.aimg != None:
+ img = os.path.join(IMAGES_PATH, self.pairs[pairkey].props.aimg)
+ if self.pairs[pairkey].props.asnd != None:
+ snd = os.path.join(SOUNDS_PATH, self.pairs[pairkey].props.asnd)
+ char = self.pairs[pairkey].props.achar
+ if moch == 1:
+ if self.pairs[pairkey].props.bimg != None:
+ img = os.path.join(IMAGES_PATH, self.pairs[pairkey].props.bimg)
+ if self.pairs[pairkey].props.bsnd != None:
+ snd = os.path.join(SOUNDS_PATH, self.pairs[pairkey].props.bsnd)
+ char = self.pairs[pairkey].props.bchar
+ color = self.pairs[pairkey].props.color
+ return (img, snd, char, color)
def same(self, a, b):
@@ -173,11 +231,41 @@ class Model(object):
if __name__ == '__main__':
model = Model(GAME_PATH, os.path.dirname(__file__))
- model.read('drumgit.mson')
- print '%s' %model.pairs[0].props.color
- print '%s' %model.pairs[1]._properties
- print '%s' %model.pairs[2]._properties
+ model.read('drumgit.mem')
+ print '%s' %model.pairs[0]._properties
+ print 'name=%s' %model.data['game_name']
+ print 'scoresnd=%s' %model.data['scoresnd']
+ print 'winsnd=%s' %model.data['winsnd']
+ print 'div=%s' %model.data['divided']
+ model.def_grid(8)
+ print 'grid size=%d'%model.data['size']
+ print model.grid
+
+ i=0
+ while i < model.data['size']:
+ pairkey, moch, state = model.grid[i]
+ if moch == 0:
+ if model.pairs[pairkey].props.aimg != None:
+ print model.pairs[pairkey].props.aimg
+ if moch == 1:
+ if model.pairs[pairkey].props.bimg != None:
+ print model.pairs[pairkey].props.bimg
+ i+=1
- model.def_grid()
+
+ '''
+ print '\n_______________________________\n'
+
+ model.read('addition.mem')
+ print '%s' %model.pairs[0]._properties
+ print 'name=%s' %model.data['game_name']
+ print 'scoresnd=%s' %model.data['scoresnd']
+ print 'winsnd=%s' %model.data['winsnd']
+ print 'div=%s' %model.data['divided']
+
+ model.def_grid(12)
print model.grid
- #model.save('/tmp/mod.txt')
+ print model.gettile(0)
+ print model.gettile(1)
+ model.save('/tmp/mod.txt')
+ '''
diff --git a/osc/__init__.py b/osc/__init__.py
deleted file mode 100755
index e69de29..0000000
--- a/osc/__init__.py
+++ /dev/null
diff --git a/osc/oscapi.py b/osc/oscapi.py
deleted file mode 100755
index bc26ddb..0000000
--- a/osc/oscapi.py
+++ /dev/null
@@ -1,163 +0,0 @@
-""" This file is based on simpleOSC 0.2 by Daniel Holth.
-This file has been modified by Simon Schampijer.
-
-This library is free software; you can redistribute it and/or
-modify it under the terms of the GNU Lesser General Public
-License as published by the Free Software Foundation; either
-version 2.1 of the License, or (at your option) any later version.
-
-This library 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
-Lesser General Public License for more details.
-
-You should have received a copy of the GNU Lesser General Public
-License along with this library; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-"""
-
-
-import socket
-import errno
-import logging
-import sys
-
-import osccore
-
-
-class OscApi(object):
- def __init__(self, port=None, host=None):
- """create the send/receive socket and the callback manager
- bind the socket to a name (host and port)
-
- Keyword arguments:
- port -- the port
- if no port is specified the socket will not be bound to an address and
- will only be used for sending
- host -- the host address, can be a dotted decimal address (e.g. '192.168.0.100')
- or a hostname (e.g. 'machine', 'localhost')
- if you do not specify a hostname the socket will listen on all the
- devices for incoming messages
- """
-
- self.manager = 0
- self.iosock = 0
- self.iosock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
- self.manager = osccore.CallbackManager()
-
- self.isserver = 0
-
- if port is not None:
- if host is None:
- host = ""
- try:
- self.iosock.bind((host, port))
- self.isserver = 1
- except socket.error:
- if errno.EADDRINUSE:
- logging.error("Port " +str(port)+ " in use." +
- " Maybe another oscapi is still or already running?" +
- " oscapi can only be used for sending.")
- self.iosock.close()
- self.iosock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
- self.iosock.setblocking(0)
-
-
- def addmethod(self, path, types, func):
- '''adds an osc method to the listener
-
- Keyword arguments:
- func -- the callback function which gets called when the appropriate osc message is received
- path -- the path (identifier) of the osc message
-
- '''
- self.manager.add(func, path, types)
-
-
- def handlemsg(self, data, addr):
- '''give the information read from the socket to the osc message dispatcher
-
- Keyword arguments:
- data -- the data read from the socket
- addr -- address the message is received from
- '''
- self.manager.handle(data, addr)
-
-
- def _create_binarymsg(self, path, data):
- """create an OSC message in binary format
-
- Keyword arguments:
- path -- the path (identifier) of the osc message
- data -- the data of the message
-
- return: the osc message in binary format
- """
- m = osccore.OSCMessage()
- m.setAddress(path)
-
- if len(data) != 0:
- for x in data:
- m.append(x)
-
- return m.getBinary()
-
-
- def send(self, to, path, data):
- """send an osc message to the address specified
-
- Keyword arguments:
- to -- address of receiver in the form (ipaddr, bundle)
- path -- the path of the osc message
- data -- the data of the message
- """
- ### resolve host? [a,b,host] = socket.gethostbyaddr(to[0])
- msg = self._create_binarymsg(path, data)
- try:
- self.iosock.sendto(msg, (to[0],to[1]))
- except socket.error:
- cla, exc, trbk = sys.exc_info()
- try:
- excArgs = exc.__dict__["args"]
- except KeyError:
- excArgs = "<no args>"
- logging.error('error '+str(excArgs))
-
- def createbundle(self):
- """create the header of a bundle of OSC messages"""
- b = osccore.OSCMessage()
- b.setAddress("")
- b.append("#bundle")
- b.append(0)
- b.append(0)
- return b
-
- def appendbundle(self, bundle, path, data):
- """append osc message to the bundle
-
- Keyword arguments:
- bundle -- the bundle to which you want to append a message
- path -- the path of the OSC message
- data -- the data of the message
- """
- msg = self._create_binarymsg(path, data)
- bundle.append(msg, 'b')
-
-
- def sendbundle(self, to, bundle):
- """send bundle to the address specified
-
- Keyword arguments:
- to -- address of receiver in the form (ipaddr, bundle)
- bundle -- the bundle to send
- """
- try:
- self.iosock.sendto(bundle.message, to)
- except socket.error:
- cla, exc, trbk = sys.exc_info()
- try:
- excArgs = exc.__dict__["args"]
- except KeyError:
- excArgs = "<no args>"
- logging.error('error '+str(excArgs))
-
diff --git a/osc/osccore.py b/osc/osccore.py
deleted file mode 100755
index 4cab0b5..0000000
--- a/osc/osccore.py
+++ /dev/null
@@ -1,405 +0,0 @@
-#!/usr/bin/python
-#
-# Open SoundControl for Python
-# Copyright (C) 2002 Daniel Holth, Clinton McChesney
-#
-# This library is free software; you can redistribute it and/or
-# modify it under the terms of the GNU Lesser General Public
-# License as published by the Free Software Foundation; either
-# version 2.1 of the License, or (at your option) any later version.
-#
-# This library 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
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public
-# License along with this library; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-#
-# For questions regarding this module contact
-# Daniel Holth <dholth@stetson.edu> or visit
-# http://www.stetson.edu/~ProctoLogic/
-#
-# Changelog:
-# 15 Nov. 2001:
-# Removed dependency on Python 2.0 features.
-# - dwh
-# 13 Feb. 2002:
-# Added a generic callback handler.
-# - dwh
-# 29 Mai 2007:
-# Added type checking of messanges.
-# - erikos
-
-import socket
-import struct
-import math
-import sys
-import string
-import pprint
-
-
-def hexDump(bytes):
- """Useful utility; prints the string in hexadecimal"""
- for i in range(len(bytes)):
- sys.stdout.write("%2x " % (ord(bytes[i])))
- if (i+1) % 8 == 0:
- print repr(bytes[i-7:i+1])
-
- if(len(bytes) % 8 != 0):
- print string.rjust("", 11), repr(bytes[i-len(bytes)%8:i+1])
-
-
-class OSCMessage:
- """Builds typetagged OSC messages."""
- def __init__(self):
- self.address = ""
- self.typetags = ","
- self.message = ""
-
- def setAddress(self, address):
- self.address = address
-
- def setMessage(self, message):
- self.message = message
-
- def setTypetags(self, typetags):
- self.typetags = typetags
-
- def clear(self):
- self.address = ""
- self.clearData()
-
- def clearData(self):
- self.typetags = ","
- self.message = ""
-
- def append(self, argument, typehint = None):
- """Appends data to the message,
- updating the typetags based on
- the argument's type.
- If the argument is a blob (counted string)
- pass in 'b' as typehint."""
-
- if typehint == 'b':
- binary = OSCBlob(argument)
- else:
- binary = OSCArgument(argument)
-
- self.typetags = self.typetags + binary[0]
- self.rawAppend(binary[1])
-
- def rawAppend(self, data):
- """Appends raw data to the message. Use append()."""
- self.message = self.message + data
-
- def getBinary(self):
- """Returns the binary message (so far) with typetags."""
- address = OSCArgument(self.address)[1]
- typetags = OSCArgument(self.typetags)[1]
- return address + typetags + self.message
-
- def __repr__(self):
- return self.getBinary()
-
-def readString(data):
- length = string.find(data,"\0")
- nextData = int(math.ceil((length+1) / 4.0) * 4)
- return (data[0:length], data[nextData:])
-
-
-def readBlob(data):
- length = struct.unpack(">i", data[0:4])[0]
- nextData = int(math.ceil((length) / 4.0) * 4) + 4
- return (data[4:length+4], data[nextData:])
-
-
-def readInt(data):
- if(len(data)<4):
- print "Error: too few bytes for int", data, len(data)
- rest = data
- integer = 0
- else:
- integer = struct.unpack(">i", data[0:4])[0]
- rest = data[4:]
-
- return (integer, rest)
-
-
-
-def readLong(data):
- """Tries to interpret the next 8 bytes of the data
- as a 64-bit signed integer."""
- high, low = struct.unpack(">ll", data[0:8])
- big = (long(high) << 32) + low
- rest = data[8:]
- return (big, rest)
-
-
-
-def readFloat(data):
- if(len(data)<4):
- print "Error: too few bytes for float", data, len(data)
- rest = data
- float = 0
- else:
- float = struct.unpack(">f", data[0:4])[0]
- rest = data[4:]
-
- return (float, rest)
-
-
-def OSCBlob(next):
- """Convert a string into an OSC Blob,
- returning a (typetag, data) tuple."""
-
- if type(next) == type(""):
- length = len(next)
- padded = math.ceil((len(next)) / 4.0) * 4
- binary = struct.pack(">i%ds" % (padded), length, next)
- tag = 'b'
- else:
- tag = ''
- binary = ''
-
- return (tag, binary)
-
-
-def OSCArgument(next):
- """Convert some Python types to their
- OSC binary representations, returning a
- (typetag, data) tuple."""
-
- if type(next) == type(""):
- OSCstringLength = math.ceil((len(next)+1) / 4.0) * 4
- binary = struct.pack(">%ds" % (OSCstringLength), next)
- tag = "s"
- elif type(next) == type(42.5):
- binary = struct.pack(">f", next)
- tag = "f"
- elif type(next) == type(13):
- binary = struct.pack(">i", next)
- tag = "i"
- else:
- binary = ""
- tag = ""
-
- return (tag, binary)
-
-
-def parseArgs(args):
- """Given a list of strings, produces a list
- where those strings have been parsed (where
- possible) as floats or integers."""
- parsed = []
- for arg in args:
- print arg
- arg = arg.strip()
- interpretation = None
- try:
- interpretation = float(arg)
- if string.find(arg, ".") == -1:
- interpretation = int(interpretation)
- except:
- # Oh - it was a string.
- interpretation = arg
- pass
- parsed.append(interpretation)
- return parsed
-
-
-
-def decodeOSC(data):
- """Converts a typetagged OSC message to a Python list."""
- table = {"i":readInt, "f":readFloat, "s":readString, "b":readBlob}
- decoded = []
- address, rest = readString(data)
- typetags = ""
-
- if address == "#bundle":
- time, rest = readLong(rest)
-# decoded.append(address)
-# decoded.append(time)
- while len(rest)>0:
- length, rest = readInt(rest)
- decoded.append(decodeOSC(rest[:length]))
- rest = rest[length:]
-
- elif len(rest) > 0:
- typetags, rest = readString(rest)
- decoded.append(address)
- decoded.append(typetags)
- if typetags[0] == ",":
- for tag in typetags[1:]:
- value, rest = table[tag](rest)
- decoded.append(value)
- else:
- print "Oops, typetag lacks the magic ,"
-
- return decoded
-
-
-class CallbackManager:
- """This utility class maps OSC addresses to callables.
-
- The CallbackManager calls its callbacks with a list
- of decoded OSC arguments, including the address and
- the typetags as the first two arguments."""
-
- def __init__(self):
- self.callbacks = {}
- self.add(self.unbundler, "#bundle", '')
-
- def handle(self, data, source = None):
- """Given OSC data, tries to call the callback with the
- right address."""
- decoded = decodeOSC(data)
- self.dispatch(decoded, source)
-
- def dispatch(self, message, source = None):
- """Sends decoded OSC data to an appropriate callback"""
- try:
- if type(message[0]) == str :
- # got a single message
- address = message[0]
-
- if address in self.callbacks:
- types = message[1].split(',')[1]
- if(types == self.callbacks[address][1]):
- self.callbacks[address][0](message, source)
- else:
- print '[error] path %s exist on osc server but...'%address
- print ' the types received [%s] do not match with [%s].'%(types,self.callbacks[address][1])
- print ' received message: %s'%(message)
- else:
- print '[error] path %s does not exist on osc server.'%address
-
- elif type(message[0]) == list :
- # smells like nested messages
- for msg in message :
- self.dispatch(msg, source)
-
- except KeyError, e:
- # address not found
- print 'address %s not found ' % address
- pprint.pprint(message)
- except IndexError, e:
- print 'got malformed OSC message'
- pass
- except None, e:
- print "Exception in", address, "callback :", e
-
- return
-
- def add(self, callback, name, types):
- """Adds a callback to our set of callbacks,
- or removes the callback with name if callback
- is None."""
- if callback == None:
- del self.callbacks[name]
- else:
- self.callbacks[name] = [callback, types]
-
- def unbundler(self, messages):
- """Dispatch the messages in a decoded bundle."""
- # first two elements are #bundle and the time tag, rest are messages.
- for message in messages[2:]:
- self.dispatch(message)
-
-
-if __name__ == "__main__":
- hexDump("Welcome to the OSC testing program.")
- print
- message = OSCMessage()
- message.setAddress("/foo/play")
- message.append(44)
- message.append(11)
- message.append(4.5)
- message.append("the white cliffs of dover")
- hexDump(message.getBinary())
-
- print "Making and unmaking a message.."
-
- strings = OSCMessage()
- strings.append("Mary had a little lamb")
- strings.append("its fleece was white as snow")
- strings.append("and everywhere that Mary went,")
- strings.append("the lamb was sure to go.")
- strings.append(14.5)
- strings.append(14.5)
- strings.append(-400)
-
- raw = strings.getBinary()
-
- hexDump(raw)
-
- print "Retrieving arguments..."
- data = raw
- for i in range(6):
- text, data = readString(data)
- print text
-
- number, data = readFloat(data)
- print number
-
- number, data = readFloat(data)
- print number
-
- number, data = readInt(data)
- print number
-
- hexDump(raw)
- print decodeOSC(raw)
- print decodeOSC(message.getBinary())
-
- print "Testing Blob types."
-
- blob = OSCMessage()
- blob.append("","b")
- blob.append("b","b")
- blob.append("bl","b")
- blob.append("blo","b")
- blob.append("blob","b")
- blob.append("blobs","b")
- blob.append(42)
-
- hexDump(blob.getBinary())
-
- print decodeOSC(blob.getBinary())
-
- def printingCallback(*stuff):
- sys.stdout.write("Got: ")
- for i in stuff:
- sys.stdout.write(str(i) + " ")
- sys.stdout.write("\n")
-
- print "Testing the callback manager."
-
- c = CallbackManager()
- c.add(printingCallback, "/print")
-
- c.handle(message.getBinary())
- message.setAddress("/print")
- c.handle(message.getBinary())
-
- print1 = OSCMessage()
- print1.setAddress("/print")
- print1.append("Hey man, that's cool.")
- print1.append(42)
- print1.append(3.1415926)
-
- c.handle(print1.getBinary())
-
- bundle = OSCMessage()
- bundle.setAddress("")
- bundle.append("#bundle")
- bundle.append(0)
- bundle.append(0)
- bundle.append(print1.getBinary(), 'b')
- bundle.append(print1.getBinary(), 'b')
-
- bundlebinary = bundle.message
-
- print "sending a bundle to the callback manager"
- c.handle(bundlebinary)
diff --git a/playerscoreboard.py b/playerscoreboard.py
new file mode 100755
index 0000000..c6a180a
--- /dev/null
+++ b/playerscoreboard.py
@@ -0,0 +1,131 @@
+#! /usr/bin/env python
+#
+# Copyright (C) 2007, One Laptop Per Child
+#
+# Muriel de Souza Godoi - muriel@laptop.org
+#
+# 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 2 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+#
+
+import gtk, pygtk
+
+import pango
+import svglabel
+import os
+from score import Score
+
+class PlayerScoreboard(gtk.EventBox):
+
+ def __init__(self, nick, fill_color, stroke_color,score = 0):
+ gtk.EventBox.__init__(self)
+
+ self.default_color = '#4c4d4f'
+ self.selected_color = '#818286'
+ self.current_color = '#4c4d4f'
+ self.status = False
+
+ self.fill_color = fill_color
+ self.stroke_color = stroke_color
+
+ # Set table
+ self.table = gtk.Table(2, 3, True)
+ self.modify_bg(gtk.STATE_NORMAL, gtk.gdk.color_parse(self.current_color))
+ self.table.set_row_spacings(0)
+ self.table.set_col_spacings(5)
+ self.table.set_border_width(10)
+
+ self.scores = []
+ self.current_x = 1
+ self.current_y = 1
+ status = False
+
+ # Set buddy icon
+ self.xo_buddy = os.path.join(os.path.dirname(__file__), "images/stock-buddy.svg")
+ self.icon = svglabel.SvgLabel(self.xo_buddy, fill_color, stroke_color, False, self.current_color, 45, 55)
+
+ # Set waiting buddy icon
+ self.waiting_icon = svglabel.SvgLabel(self.xo_buddy, self.default_color, '#ffffff', False, self.current_color, 45, 55)
+
+ # Cache the score icon
+ score_label = Score(fill_color, stroke_color)
+ self.score_pixbuf_unsel = score_label.get_pixbuf()
+ self.score_pixbuf_sel = score_label.get_pixbuf_sel()
+
+ # Set nick label
+ self.nick = gtk.Label(nick)
+ self.nick.modify_font(pango.FontDescription("12"))
+ self.nick.modify_fg(gtk.STATE_NORMAL, gtk.gdk.color_parse('#ffffff'))
+ self.nick.set_alignment(0, 0.5)
+
+ # Set message label
+ self.msg = gtk.Label('Waiting for next game...')
+ self.msg.modify_font(pango.FontDescription("12"))
+ self.msg.modify_fg(gtk.STATE_NORMAL, gtk.gdk.color_parse('#ffffff'))
+ self.msg.set_alignment(0, 0.5)
+
+ self.add(self.table)
+ self.table.attach(self.icon, 0, 1, 0, 1)
+ self.table.attach(self.nick, 1, 7, 0, 1)
+
+ if score <> 0:
+ for i in range(score):
+ self.increase_score()
+
+ def increase_score(self):
+ new_score = Score(self.fill_color, self.stroke_color, self.score_pixbuf_sel, self.score_pixbuf_unsel,self.status)
+ self.scores.append(new_score)
+ new_score.show()
+ self.table.attach(new_score, self.current_x , self.current_x+1, self.current_y, self.current_y+1)
+ self.current_x += 1
+ if self.current_x == 7:
+ self.current_x = 1
+ self.current_y += 1
+ self.queue_draw()
+
+ def set_selected(self, sel):
+ self.status = sel
+ if sel:
+ self.current_color = self.selected_color
+ else:
+ self.current_color = self.default_color
+ self.modify_bg(gtk.STATE_NORMAL, gtk.gdk.color_parse(self.current_color))
+ self.icon.set_background(self.current_color)
+ for score in self.scores:
+ score.set_selected(sel)
+ self.queue_draw()
+
+ def reset(self):
+ for score in self.scores:
+ self.table.remove(score)
+ self.current_x = 1
+ self.current_y = 1
+ del self.scores
+ self.scores = []
+ self.queue_draw()
+
+ def set_wait_mode(self,status):
+ if status:
+ self.table.remove(self.icon)
+ self.table.attach(self.waiting_icon, 0, 1, 0, 1)
+ if len(self.scores) == 0:
+ self.table.attach(self.msg, 1, 7, 1, 2)
+ else:
+ self.table.remove(self.waiting_icon)
+ self.table.attach(self.icon, 0, 1, 0, 1)
+ self.table.remove(self.msg)
+ if len(self.scores) == 0:
+ self.table.remove(self.msg)
+ self.queue_draw()
+ \ No newline at end of file
diff --git a/playtile.py b/playtile.py
deleted file mode 100644
index e3c2494..0000000
--- a/playtile.py
+++ /dev/null
@@ -1,71 +0,0 @@
-import gtk
-import hippo
-import math
-import os
-
-from sugar.graphics import units
-
-class PlayTile(hippo.CanvasBox, hippo.CanvasItem):
- __gtype_name__ = 'PlayTile'
- _BORDER_DEFAULT = units.points_to_pixels(1.0)
-
- def __init__(self, num, x, y, **kargs):
- hippo.CanvasBox.__init__(self, **kargs)
-
- self.num = num
- self.image = os.path.join(os.path.dirname(__file__), 'images/black.png')
- self.scale_x = x
- self.scale_y = y
-
- self._radius = units.points_to_pixels(5)
- self.props.border_color = 100
- self.props.background_color = 100
- self.props.orientation = hippo.ORIENTATION_VERTICAL
- self.props.border = self._BORDER_DEFAULT
- self.props.border_left = self._radius
- self.props.border_right = self._radius
-
- self.append(self._build_title_box())
-
-
- def do_paint_background(self, cr, damaged_box):
- [width, height] = self.get_allocation()
-
- x = self._BORDER_DEFAULT / 2
- y = self._BORDER_DEFAULT / 2
- width -= self._BORDER_DEFAULT
- height -= self._BORDER_DEFAULT
-
- cr.move_to(x + self._radius, y);
- cr.arc(x + width - self._radius, y + self._radius,
- self._radius, math.pi * 1.5, math.pi * 2);
- cr.arc(x + width - self._radius, x + height - self._radius,
- self._radius, 0, math.pi * 0.5);
- cr.arc(x + self._radius, y + height - self._radius,
- self._radius, math.pi * 0.5, math.pi);
- cr.arc(x + self._radius, y + self._radius, self._radius,
- math.pi, math.pi * 1.5);
-
- hippo.cairo_set_source_rgba32(cr, self.props.background_color)
- cr.fill()
-
- def _build_title_box(self):
- hbox = hippo.CanvasBox(orientation=hippo.ORIENTATION_HORIZONTAL)
- hbox.props.spacing = units.points_to_pixels(5)
- hbox.props.padding_top = units.points_to_pixels(5)
- hbox.props.padding_bottom = units.points_to_pixels(5)
-
- self.img_widget = gtk.Image()
- pixbuf_i = gtk.gdk.pixbuf_new_from_file(self.image)
- self.scaledbuf_i = pixbuf_i.scale_simple(self.scale_x, self.scale_y, gtk.gdk.INTERP_BILINEAR)
- self.img_widget.set_from_pixbuf(self.scaledbuf_i)
-
- canvas_widget = hippo.CanvasWidget()
- canvas_widget.props.widget = self.img_widget
- self.img_widget.show()
- hbox.append(canvas_widget)
-
- return hbox
-
-
-
diff --git a/playview.py b/playview.py
deleted file mode 100644
index 1a9a15d..0000000
--- a/playview.py
+++ /dev/null
@@ -1,42 +0,0 @@
-import hippo
-import os
-import cairo
-import gtk
-import math
-
-from sugar.graphics import color
-
-from playtile import PlayTile
-
-class PlayView(hippo.CanvasBox, hippo.CanvasItem):
- def __init__(self, wx, wy, numtiles, **kargs):
- hippo.CanvasBox.__init__(self, **kargs)
-
- self.props.orientation = hippo.ORIENTATION_VERTICAL
- self.tiles = []
- tile_num = 0
-
- numx = math.pow(float(numtiles), 0.5)
- if numx%1 != 0:
- numx = int(numx)+1
- self.y = self.x = (int(wx/numx)-10)
-
- while tile_num < numtiles:
- if tile_num == 0 or ((tile_num)%numx) == 0:
- box = hippo.CanvasBox()
- box.props.orientation = hippo.ORIENTATION_HORIZONTAL
- self.append(box)
-
- tile = PlayTile(tile_num, self.x, self.y)
- self.tiles.append(tile)
- box.append(tile)
-
- tile_num+=1
-
- def flip(self, tile_num, obj, color):
- tile = self.tiles[tile_num]
- tile.img_pixbuf = gtk.gdk.pixbuf_new_from_file(obj)
- tile.img_widget.set_from_pixbuf(tile.img_pixbuf.scale_simple(self.x, self.y, gtk.gdk.INTERP_BILINEAR))
- tile.props.background_color = color
- tile.emit_paint_needed(0, 0, -1, -1)
-
diff --git a/score.py b/score.py
new file mode 100755
index 0000000..7b6e11e
--- /dev/null
+++ b/score.py
@@ -0,0 +1,67 @@
+#! /usr/bin/env python
+#
+# Copyright (C) 2007, One Laptop Per Child
+#
+# Muriel de Souza Godoi - muriel@laptop.org
+#
+# 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 2 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+#
+
+import rsvg
+import re
+import svglabel
+import gtk
+import gobject
+import os
+
+class Score(svglabel.SvgLabel):
+
+ selected_color = "#818286"
+ default_color = "#4c4d4f"
+ status = False
+
+ def __init__(self, fill_color, stroke_color, pixbuf= None, pixbuf_sel = None,status= False):
+ filename = os.path.join(os.path.dirname(__file__), "images/score.svg")
+ self.pixbuf_un = pixbuf
+ self.pixbuf_sel = pixbuf_sel
+ self.status = status
+ if self.pixbuf_un == None:
+ self.pixbuf_un = svglabel.SvgLabel(filename, fill_color, stroke_color, False, self.default_color).get_pixbuf()
+ if self.pixbuf_sel == None:
+ self.pixbuf_sel = svglabel.SvgLabel(filename, fill_color, stroke_color, False, self.selected_color).get_pixbuf()
+ if status:
+ self.pixbuf = self.pixbuf_sel
+ else:
+ self.pixbuf = self.pixbuf_un
+
+ svglabel.SvgLabel.__init__(self, filename, fill_color, stroke_color, self.pixbuf, self.default_color, 35, 35)
+ self.set_selected(status)
+
+ def set_selected(self, status):
+ self.status = status
+ if status:
+ self.pixbuf = self.pixbuf_sel
+ self.modify_bg(gtk.STATE_NORMAL,gtk.gdk.color_parse(self.selected_color))
+ else:
+ self.pixbuf = self.pixbuf_un
+ self.modify_bg(gtk.STATE_NORMAL,gtk.gdk.color_parse(self.default_color))
+ self.queue_draw()
+
+ def get_pixbuf_un(self):
+ return self.pixbuf_un
+
+ def get_pixbuf_sel(self):
+ return self.pixbuf_sel
+ \ No newline at end of file
diff --git a/scoreboard.py b/scoreboard.py
new file mode 100755
index 0000000..8c00214
--- /dev/null
+++ b/scoreboard.py
@@ -0,0 +1,83 @@
+#! /usr/bin/env python
+#
+# Copyright (C) 2007, One Laptop Per Child
+#
+# Muriel de Souza Godoi - muriel@laptop.org
+#
+# 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 2 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+#
+
+import gtk
+from playerscoreboard import PlayerScoreboard
+
+class Scoreboard(gtk.EventBox):
+ def __init__(self):
+ gtk.EventBox.__init__(self)
+
+ self.players = {}
+ self.current_buddy = None
+
+ self.set_size_request(400, 150)
+ self.vbox = gtk.VBox(False)
+
+ fill_box = gtk.EventBox()
+ fill_box.modify_bg(gtk.STATE_NORMAL, gtk.gdk.color_parse('#4c4d4f'))
+ fill_box.show()
+ self.vbox.pack_end(fill_box, True, True)
+
+ scroll = gtk.ScrolledWindow()
+ scroll.props.shadow_type = gtk.SHADOW_NONE
+ scroll.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
+ scroll.add_with_viewport(self.vbox)
+ scroll.set_border_width(0)
+ scroll.get_child().set_property('shadow-type', gtk.SHADOW_NONE)
+ self.add(scroll)
+ self.show()
+
+ def add_buddy(self, widget, buddy, score):
+ nick = buddy.props.nick
+ stroke_color, fill_color = buddy.props.color.split(',')
+ player = PlayerScoreboard(nick, fill_color, stroke_color, score)
+ player.show()
+ self.players[buddy]=player
+ self.vbox.pack_start(player, False, True)
+ if score == -1:
+ player.set_wait_mode(True)
+ self.show_all()
+
+
+
+ def rem_buddy(self, widget, buddy):
+ self.vbox.remove(self.players[buddy])
+ del self.players[id]
+
+ def set_selected(self, widget, buddy):
+ if self.current_buddy <> None:
+ old = self.players[self.current_buddy]
+ old.set_selected(False)
+ self.current_buddy = buddy
+ player = self.players[buddy]
+ player.set_selected(True)
+
+ def increase_score(self, widget, buddy):
+ self.players[buddy].increase_score()
+
+ def reset(self, widget):
+ for buddy in self.players.keys():
+ self.players[buddy].reset()
+
+ def set_wait_mode(self, widget, buddy, status):
+ self.players[buddy].set_wait_mode(status)
+ \ No newline at end of file
diff --git a/svgcard.py b/svgcard.py
new file mode 100755
index 0000000..9062d18
--- /dev/null
+++ b/svgcard.py
@@ -0,0 +1,215 @@
+#! /usr/bin/env python
+#
+# Copyright (C) 2007, One Laptop Per Child
+#
+# Muriel de Souza Godoi - muriel@laptop.org
+#
+# 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 2 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+#
+
+import os
+import gc
+import rsvg
+import re
+import svglabel
+import gtk
+import gobject
+
+class SvgCard(gtk.DrawingArea):
+
+ border_svg = os.path.join(os.path.dirname(__file__), "images/card.svg")
+ text_svg = os.path.join(os.path.dirname(__file__), "images/card-text.svg")
+
+ # Default properties
+ default_props = {}
+ default_props['back_border'] = {'filename':border_svg, 'fill_color':'#b2b3b7', 'stroke_color':'#b2b3b7', 'opacity':'1'}
+ default_props['back_h_border'] = {'filename':border_svg, 'fill_color':'#b2b3b7', 'stroke_color':'#ffffff', 'opacity':'1'}
+ default_props['back_text'] = {'filename':text_svg, 'text_color':'#c7c8cc'}
+ default_props['front_border'] = {'filename':border_svg, 'fill_color':'#4c4d4f', 'stroke_color':'#ffffff', 'opacity':'0'}
+ default_props['front_h_border'] = {'filename':border_svg, 'fill_color':'#555555', 'stroke_color':'#888888', 'opacity':'0.5'}
+ default_props['front_text'] = {'filename':text_svg, 'text_color':'#ffffff'}
+
+
+ def __init__(self, id, pprops, pcache, jpeg, size):
+ gtk.DrawingArea.__init__(self)
+ self.set_size_request(size, size)
+ self.bg_color = '#000000'
+ self.modify_bg(gtk.STATE_NORMAL, gtk.gdk.color_parse(self.bg_color))
+ self.connect('expose-event', self._expose_cb)
+ self.flipped = False
+ self.id = id
+ self.jpeg = jpeg
+ self.size = size
+ self.set_flags(gtk.CAN_FOCUS)
+
+ # Views properties
+ views = ['back_border','back_h_border','back_text','front_border','front_h_border','front_text']
+ self.pprops = pprops
+ self.props = {}
+ for view in views:
+ self.props[view] = {}
+ self.props[view].update(self.default_props[view])
+ self.props[view].update(pprops.get(view, {}))
+
+ # Cache
+ self.cache = {}
+ self.cache.update(pcache)
+
+ if len(self.cache) == 0:
+ build_all = True
+ else:
+ build_all = False
+
+ self.build_all = build_all
+
+ if build_all or pprops.has_key('back_border'):
+ self.cache['back_border']= self._read_icon_data(self.props['back_border'])
+ if build_all or pprops.has_key('back_h_border'):
+ self.cache['back_h_border']= self._read_icon_data(self.props['back_h_border'])
+ if build_all or pprops.has_key('back_text'):
+ text = self._read_icon_data(self.props['back_text'])
+ self.cache['back_text'] = text.scale_simple(self.size-14, self.size-14, gtk.gdk.INTERP_BILINEAR)
+ del text
+ if build_all or self.pprops.has_key('back_border') or self.pprops.has_key('back_text'):
+ self.cache['back'] = self.build_face('back')
+ if build_all or self.pprops.has_key('back_h_border') or self.pprops.has_key('back_text'):
+ self.cache['back_h'] = self.build_face('back_h')
+
+ self.current_pixbuf = self.cache['back']
+ # Set events and listeners
+ self.set_events(gtk.gdk.ALL_EVENTS_MASK)
+ gc.collect()
+ self.show()
+
+ def _expose_cb(self, widget, event):
+ self.window.draw_pixbuf(None, self.current_pixbuf, 0, 0, 0, 0)
+ return False
+
+ def _read_icon_data(self, dict):
+ icon_file = open(dict.get('filename', 'card.svg'), 'r')
+ data = icon_file.read()
+ icon_file.close()
+
+ # Replace borders parameters
+ entity = '<!ENTITY fill_color "%s">' % dict.get('fill_color', '')
+ data = re.sub('<!ENTITY fill_color .*>', entity, data)
+
+ entity = '<!ENTITY stroke_color "%s">' % dict.get('stroke_color', '')
+ data = re.sub('<!ENTITY stroke_color .*>', entity, data)
+
+ entity = '<!ENTITY opacity "%s">' % dict.get('opacity', '')
+ data = re.sub('<!ENTITY opacity .*>', entity, data)
+
+ data = re.sub('size_card1', str(self.size), data)
+ data = re.sub('size_card2', str(self.size-6), data)
+ data = re.sub('size_card3', str(self.size-17), data)
+
+ # Replace text parameters
+ entity = '<!ENTITY text_color "%s">' % dict.get('text_color', '#ffffff')
+ data = re.sub('<!ENTITY text_color .*>', entity, data)
+
+ data = re.sub('card_text', dict.get('card_text', ''), data)
+ data = re.sub('card_line1', dict.get('card_line1', ''), data)
+ data = re.sub('card_line2', dict.get('card_line2', ''), data)
+ data = re.sub('card_line3', dict.get('card_line3', ''), data)
+ data = re.sub('card_line4', dict.get('card_line4', ''), data)
+
+ self.data_size = len(data)
+ return rsvg.Handle(data=data).get_pixbuf()
+
+ def build_face(self, face):
+ if face.endswith('_h'):
+ text = face[:-2]
+ else:
+ text = face
+ pixbuf = gtk.gdk.Pixbuf(gtk.gdk.COLORSPACE_RGB, True, 8, self.size, self.size)
+ pixbuf.fill(0x00000000)
+ self.cache[face + '_border'].composite(pixbuf, 0, 0, self.size, self.size, 0, 0, 1, 1, gtk.gdk.INTERP_NEAREST, 255)
+ if face.startswith('front') and self.jpeg <> None:
+ self.cache['jpeg'].composite(pixbuf, 11, 11, self.size-22, self.size-22, 11, 11, 1, 1, gtk.gdk.INTERP_NEAREST, 255)
+ #self.cache[face + '_border'].composite(pixbuf, 0, 0, self.size, self.size, 0, 0, 1, 1, gtk.gdk.INTERP_BILINEAR, 255)
+ self.cache[text + '_text'].composite(pixbuf, 11, 11, self.size-22, self.size-22, 11, 11, 1, 1, gtk.gdk.INTERP_NEAREST, 255)
+ return pixbuf
+
+ def set_border(self, stroke_color, fill_color):
+ self.props['front_border'].update({'fill_color':fill_color, 'stroke_color':stroke_color})
+ self.cache['front_border'] = self._read_icon_data(self.props['front_border'])
+ self.cache['front'] = self.build_face('front')
+ self.current_pixbuf = self.cache['front']
+ self.queue_draw()
+
+ def set_highlight(self, status, mouse = False):
+ if self.flipped:
+ if mouse:
+ return
+ if status:
+ self.current_pixbuf = self.cache['front_h']
+ else:
+ self.current_pixbuf = self.cache['front']
+ else:
+ if status:
+ self.current_pixbuf = self.cache['back_h']
+ else:
+ self.current_pixbuf = self.cache['back']
+ self.queue_draw()
+
+ def flip(self):
+ if self.build_all or self.pprops.has_key('front_border'):
+ self.cache['front_border']= self._read_icon_data(self.props['front_border'])
+ if self.build_all or self.pprops.has_key('front_h_border'):
+ self.cache['front_h_border']= self._read_icon_data(self.props['front_h_border'])
+ if self.build_all or self.pprops.has_key('front_text'):
+ text = self._read_icon_data(self.props['front_text'])
+ self.cache['front_text'] = text.scale_simple(self.size-22, self.size-22, gtk.gdk.INTERP_BILINEAR)
+ del text
+
+ if self.jpeg <> None:
+ pixbuf_t = gtk.gdk.pixbuf_new_from_file(self.jpeg)
+ # pixbuf_t = pixbuf_t.add_alpha(True,chr(255),chr(255),chr(255))
+ self.cache['jpeg']= pixbuf_t.scale_simple(self.size-22, self.size-22, gtk.gdk.INTERP_BILINEAR)
+ del pixbuf_t
+
+ if self.cache.has_key('front_border') or self.cache.has_key('front_text'):
+ self.cache['front'] = self.build_face('front')
+ if self.cache.has_key('front_h_border') or self.cache.has_key('front_text'):
+ self.cache['front_h'] = self.build_face('front_h')
+
+ if not self.flipped:
+ self.current_pixbuf = self.build_face('front')
+ self.flipped = True
+ self.queue_draw()
+ while gtk.events_pending():
+ gtk.main_iteration()
+
+ def flop(self):
+ self.current_pixbuf = self.build_face('back')
+ self.flipped = False
+ self.queue_draw()
+
+ def is_flipped(self):
+ return self.flipped
+
+ def get_id(self):
+ return self.id
+
+ def get_cache(self):
+ return self.cache
+
+ def reset(self):
+ if self.flipped:
+ fill_color = self.default_props.get('front_border').get('fill_color')
+ stroke_color = self.default_props.get('front_border').get('stroke_color')
+ self.set_border(fill_color, stroke_color)
+ self.flop() \ No newline at end of file
diff --git a/svglabel.py b/svglabel.py
new file mode 100755
index 0000000..64c7f44
--- /dev/null
+++ b/svglabel.py
@@ -0,0 +1,103 @@
+#! /usr/bin/env python
+#
+# Copyright (C) 2007, One Laptop Per Child
+#
+# Muriel de Souza Godoi - muriel@laptop.org
+#
+# 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 2 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+#
+
+import gtk, pygtk
+import rsvg
+import cairo
+import re
+
+class SvgLabel(gtk.DrawingArea):
+
+ filename = ''
+ fill_color = ''
+ stroke_color = ''
+ background_color = ''
+
+
+ def __init__(self, filename, fill_color, stroke_color, pixbuf = False, background_color = '', request_x = 45, request_y = 45):
+ gtk.DrawingArea.__init__(self)
+ self.set_size_request(request_x, request_y)
+ self.filename = filename
+ self.background_color = background_color
+ self.fill_color = fill_color
+ self.stroke_color = stroke_color
+ self.modify_bg(gtk.STATE_NORMAL,gtk.gdk.color_parse(background_color))
+ if pixbuf:
+ self.pixbuf = pixbuf
+ else:
+ self.pixbuf = self._read_icon_data(self.filename, self.fill_color, self.stroke_color)
+
+ self.connect('expose-event', self._expose_cb)
+
+ def _expose_cb(self, widget, event):
+ widget.window.draw_pixbuf(None,self.pixbuf, 0, 0, 0, 0)
+ return False
+
+ def _read_icon_data(self, filename, fill_color, stroke_color):
+ icon_file = open(filename, 'r')
+ data = icon_file.read()
+ icon_file.close()
+
+ if fill_color:
+ entity = '<!ENTITY fill_color "%s">' % fill_color
+ data = re.sub('<!ENTITY fill_color .*>', entity, data)
+
+ if stroke_color:
+ entity = '<!ENTITY stroke_color "%s">' % stroke_color
+ data = re.sub('<!ENTITY stroke_color .*>', entity, data)
+
+ self.data_size = len(data)
+ return rsvg.Handle(data=data).get_pixbuf()
+
+ def set_color(self, fill_color, stroke_color):
+ self.fill_color = fill_color
+ self.stroke_color = stroke_color
+ self.pixmap = self._read_icon_data(self.filename, self.fill_color, self.stroke_color)
+ self.queue_draw()
+
+ def set_fill_color(self, fill_color):
+ self.fill_color = fill_color
+ self.pixmap = self._read_icon_data(self.filename, self.fill_color, self.stroke_color)
+ self.queue_draw()
+
+ def get_fill_color(self):
+ return self.fill_color
+
+ def set_stroke_color(self, stroke_color):
+ self.stroke_color = stroke_color
+ self.pixmap = self._read_icon_data(self.filename, self.fill_color, self.stroke_color)
+ self.queue_draw()
+
+ def get_stroke_color(self):
+ return self.stroke_color
+
+ def get_pixbuf(self):
+ return self.pixbuf
+
+ def set_pixbuf(self, pixbuf):
+ self.pixbuf = pixbuf
+ self.queue_draw()
+
+ def set_background(self, background_color):
+ self.background_color = background_color
+ self.modify_bg(gtk.STATE_NORMAL,gtk.gdk.color_parse(self.background_color))
+ self.queue_draw()
+ \ No newline at end of file