Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorWalter Bender <walter@walter-laptop.(none)>2009-10-03 00:24:36 (GMT)
committer Walter Bender <walter@walter-laptop.(none)>2009-10-03 00:24:36 (GMT)
commitb0e22b3b1ab7a16471f6ddd1e91e1f0c6a8b529d (patch)
tree7b6b9076bc91feb36468e74f1df6465f071e4741
new project
-rw-r--r--COPYING20
-rw-r--r--CardSortActivity.py318
-rw-r--r--CardSortActivity.pycbin0 -> 10328 bytes
-rw-r--r--CardSortActivity.py~318
-rw-r--r--MANIFEST31
-rw-r--r--MANIFEST~24
-rw-r--r--NEWS3
-rw-r--r--NEWS~350
-rw-r--r--activity-cardsort.pngbin0 -> 1690 bytes
-rw-r--r--activity/activity-cardsort.svg16
-rw-r--r--activity/activity.info9
-rw-r--r--dist/CardSort-1.tar.bz2bin0 -> 20417 bytes
-rw-r--r--dist/CardSort-1.xobin0 -> 32559 bytes
-rw-r--r--icons/solve-off.svg141
-rw-r--r--icons/solve-on.svg141
-rw-r--r--images/card0.svg21
-rw-r--r--images/card0x.svg57
-rw-r--r--images/card1.svg21
-rw-r--r--images/card1x.svg57
-rw-r--r--images/card2.svg16
-rw-r--r--images/card2x.svg57
-rw-r--r--images/card3.svg21
-rw-r--r--images/card3x.svg57
-rw-r--r--images/card4.svg21
-rw-r--r--images/card4x.svg57
-rw-r--r--images/card5.svg21
-rw-r--r--images/card5x.svg57
-rw-r--r--images/card6.svg21
-rw-r--r--images/card6x.svg57
-rw-r--r--images/card7.svg21
-rw-r--r--images/card7x.svg57
-rw-r--r--images/card8.svg21
-rw-r--r--images/card8x.svg57
-rw-r--r--po/CardSort.pot44
-rwxr-xr-xsetup.py5
-rw-r--r--sprites.py161
-rw-r--r--sprites.pycbin0 -> 6338 bytes
-rw-r--r--sprites.py~174
38 files changed, 2452 insertions, 0 deletions
diff --git a/COPYING b/COPYING
new file mode 100644
index 0000000..a817f22
--- /dev/null
+++ b/COPYING
@@ -0,0 +1,20 @@
+Copyright (c) 2007-9, Playful Invention Company, Sugar Labs
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+
diff --git a/CardSortActivity.py b/CardSortActivity.py
new file mode 100644
index 0000000..0522e82
--- /dev/null
+++ b/CardSortActivity.py
@@ -0,0 +1,318 @@
+#Copyright (c) 2009, Walter Bender
+
+#Permission is hereby granted, free of charge, to any person obtaining a copy
+#of this software and associated documentation files (the "Software"), to deal
+#in the Software without restriction, including without limitation the rights
+#to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+#copies of the Software, and to permit persons to whom the Software is
+#furnished to do so, subject to the following conditions:
+
+#The above copyright notice and this permission notice shall be included in
+#all copies or substantial portions of the Software.
+
+#THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+#IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+#FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+#AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+#LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+#OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+#THE SOFTWARE.
+
+import pygtk
+pygtk.require('2.0')
+import gtk
+import gobject
+
+import sugar
+from sugar.activity import activity
+from sugar.bundle.activitybundle import ActivityBundle
+from sugar.activity.widgets import ActivityToolbarButton
+from sugar.activity.widgets import StopButton
+from sugar.graphics.toolbarbox import ToolbarBox
+from sugar.graphics.toolbarbox import ToolbarButton
+from sugar.graphics.toolbutton import ToolButton
+from sugar.graphics.menuitem import MenuItem
+from sugar.graphics.icon import Icon
+from sugar.graphics import style
+from sugar.datastore import datastore
+
+from sugar import profile
+from gettext import gettext as _
+import locale
+import os.path
+from sprites import *
+from math import sqrt
+
+class taWindow: pass
+
+SERVICE = 'org.sugarlabs.CardSortActivity'
+IFACE = SERVICE
+PATH = '/org/augarlabs/CardSortActivity'
+
+CARD_DIM = 135
+CARD_DEFS = ((1,3,-2,-3),(2,3,-3,-2),(2,3,-4,-4),\
+ (2,1,-1,-4),(3,4,-4,-3),(4,2,-1,-2),\
+ (1,1,-2,-4),(4,2,-3,-4),(1,3,-1,-2))
+
+
+#
+# class for defining 3x3 matrix of cards
+#
+class Grid:
+ # 123
+ # 456
+ # 789
+ def __init__(self,tw):
+ self.grid = [1,2,3,4,5,6,7,8,9]
+ self.card_table = {}
+ # Initialize the cards
+ i = 0
+ x = (tw.width-(CARD_DIM*3))/2
+ y = (tw.height-(CARD_DIM*3))/2
+ for c in CARD_DEFS:
+ self.card_table[i] = Card(tw,c,i,x,y)
+ self.card_table[i].draw_card()
+ x += CARD_DIM
+ if x > (tw.width+(CARD_DIM*2))/2:
+ x = (tw.width-(CARD_DIM*3))/2
+ y += CARD_DIM
+ i += 1
+
+ def swap(self,a,b):
+ # swap grid elements and x,y positions of sprites
+ print "swapping cards " + str(a) + " and " + str(b)
+ tmp = self.grid[a]
+ x = self.card_table[a].spr.x
+ y = self.card_table[a].spr.y
+ self.grid[a] = self.grid[b]
+ self.card_table[a].spr.x = self.card_table[b].spr.x
+ self.card_table[a].spr.y = self.card_table[b].spr.y
+ self.grid[b] = tmp
+ self.card_table[b].spr.x = x
+ self.card_table[b].spr.y = y
+
+ def print_grid(self):
+ print self.grid
+ return
+
+ def test(self):
+ for i in (0,1,3,4,6,7):
+ if self.card_table[self.grid[i]].east + \
+ self.card_table[self.grid[i+1]].west != 0:
+ return False
+ for i in (0,1,2,3,4,5):
+ if self.card_table[self.grid[i]].south + \
+ self.card_table[self.grid[i+3]].north != 0:
+ return False
+ return True
+
+
+#
+# class for defining individual cards
+#
+class Card:
+ # Spade = 1,-1
+ # Heart = 2,-2
+ # Club = 3,-3
+ # Diamond = 4,-4
+ def __init__(self,tw,c,i,x,y):
+ self.north = c[0]
+ self.east = c[1]
+ self.south = c[2]
+ self.west = c[3]
+ self.rotate = 0
+ # create sprite from svg file
+ self.spr = sprNew(tw,x,y,self.load_image(tw.path,i))
+ self.spr.label = i
+
+ def draw_card(self):
+ setlayer(self.spr,2000)
+ draw(self.spr)
+
+ def load_image(self, file, i):
+ print "loading " + os.path.join(file + str(i) + '.svg')
+ return gtk.gdk.pixbuf_new_from_file(os.path.join(file + \
+ str(i) + "x" + \
+ '.svg'))
+
+ def rotate_ccw(self):
+ # print "rotating card " + str(self.spr.label)
+ tmp = self.north
+ self.north = self.east
+ self.east = self.south
+ self.south = self.west
+ self.west = tmp
+ self.rotate += 90
+ if self.rotate > 359:
+ self.rotate -= 360
+ tmp = self.spr.image.rotate_simple(90)
+ self.spr.image = tmp
+
+ def print_card(self):
+ print "(" + str(self.north) + "," + str(self.east) + \
+ "," + str(self.south) + "," + str(self.west) + \
+ ") " + str(self.rotate) + "ccw" + \
+ " x:" + str(self.spr.x) + " y:" + str(self.spr.y)
+
+#
+# Sugar activity
+#
+class CardSortActivity(activity.Activity):
+
+ def __init__(self, handle):
+ super(CardSortActivity,self).__init__(handle)
+
+ # Use 0.86 toolbar design
+ toolbar_box = ToolbarBox()
+
+ # Buttons added to the Activity toolbar
+ activity_button = ActivityToolbarButton(self)
+ toolbar_box.toolbar.insert(activity_button, 0)
+ activity_button.show()
+
+ # Solver button
+ self.solve_puzzle = ToolButton( "solve-off" )
+ self.solve_puzzle.set_tooltip(_('Solve it'))
+ self.solve_puzzle.props.sensitive = True
+ self.solve_puzzle.connect('clicked', self._solver_cb)
+ toolbar_box.toolbar.insert(self.solve_puzzle, -1)
+ self.solve_puzzle.show()
+
+ separator = gtk.SeparatorToolItem()
+ separator.show()
+ toolbar_box.toolbar.insert(separator, -1)
+
+ # Label for showing status
+ self.results_label = gtk.Label(_("click to rotate; drag to swap"))
+ self.results_label.show()
+ results_toolitem = gtk.ToolItem()
+ results_toolitem.add(self.results_label)
+ toolbar_box.toolbar.insert(results_toolitem,-1)
+
+ separator = gtk.SeparatorToolItem()
+ separator.props.draw = False
+ separator.set_expand(True)
+ separator.show()
+ toolbar_box.toolbar.insert(separator, -1)
+
+ # The ever-present Stop Button
+ stop_button = StopButton(self)
+ stop_button.props.accelerator = '<Ctrl>Q'
+ toolbar_box.toolbar.insert(stop_button, -1)
+ stop_button.show()
+
+ self.set_toolbar_box(toolbar_box)
+ toolbar_box.show()
+
+ # Create a canvas
+ canvas = gtk.DrawingArea()
+ canvas.set_size_request(gtk.gdk.screen_width(), \
+ gtk.gdk.screen_height())
+ self.set_canvas(canvas)
+ self.show_all()
+
+ # Initialize the canvas
+ self.tw = taWindow()
+ self.tw.window = canvas
+ canvas.set_flags(gtk.CAN_FOCUS)
+ canvas.add_events(gtk.gdk.BUTTON_PRESS_MASK)
+ canvas.add_events(gtk.gdk.BUTTON_RELEASE_MASK)
+ canvas.connect("expose-event", self._expose_cb, self.tw)
+ canvas.connect("button-press-event", self._button_press_cb, self.tw)
+ canvas.connect("button-release-event", self._button_release_cb, self.tw)
+ self.tw.width = gtk.gdk.screen_width()
+ self.tw.height = gtk.gdk.screen_height()-style.GRID_CELL_SIZE
+ self.tw.area = canvas.window
+ self.tw.gc = self.tw.area.new_gc()
+ self.tw.scale = 3
+ self.tw.cm = self.tw.gc.get_colormap()
+ self.tw.msgcolor = self.tw.cm.alloc_color('black')
+ self.tw.sprites = []
+
+ # Initialize the grid
+ self.tw.path = os.path.join(activity.get_bundle_path(),'images/card')
+ self.tw.grid = Grid(self.tw)
+
+ # Start solving the puzzle
+ self.tw.press = -1
+ self.tw.release = -1
+ self.tw.start_drag = [0,0]
+
+ #
+ # Solver
+ #
+ def _solver_cb(self, button):
+ self.solve_puzzle.set_icon("solve-on")
+ """
+ We need to write this code
+ """
+ self.results_label.set_text(_("I don't know how to solve it."))
+ self.results_label.show()
+ self.solve_puzzle.set_icon("solve-off")
+ return True
+
+
+ #
+ # Repaint
+ #
+ def _expose_cb(self, win, event, tw):
+ redrawsprites(tw)
+ return True
+
+ #
+ # Button press
+ #
+ def _button_press_cb(self, win, event, tw):
+ win.grab_focus()
+ x, y = map(int, event.get_coords())
+ tw.start_drag = [x,y]
+ spr = findsprite(tw,(x,y))
+ if spr is None:
+ tw.press = -1
+ tw.release = -1
+ return True
+ # take note of card under button press
+ tw.press = spr.label
+ return True
+
+ #
+ # Button release
+ #
+ def _button_release_cb(self, win, event, tw):
+ win.grab_focus()
+ x, y = map(int, event.get_coords())
+ spr = findsprite(tw,(x,y))
+ if spr is None:
+ tw.press = -1
+ tw.release = -1
+ return True
+ # take note of card under button release
+ tw.release = spr.label
+ # if the same card (click) then rotate
+ if tw.press == tw.release:
+ # check to see if it was an aborted move
+ if self.distance(tw.start_drag,[x,y]) < 20:
+ tw.grid.card_table[tw.press].rotate_ccw()
+ # tw.grid.card_table[tw.press].print_card()
+ # if different card (drag) then swap
+ else:
+ tw.grid.swap(tw.press,tw.release)
+ # tw.grid.print_grid()
+ inval(tw.grid.card_table[tw.press].spr)
+ inval(tw.grid.card_table[tw.release].spr)
+ redrawsprites(tw)
+ tw.press = -1
+ tw.release = -1
+ if tw.grid.test() == True:
+ self.results_label.set_text(_("You solved the puzzle."))
+ self.results_label.show()
+ else:
+ self.results_label.set_text(_("Keep trying."))
+ self.results_label.show()
+
+ return True
+
+ def distance(self,start,stop):
+ dx = start[0]-stop[0]
+ dy = start[1]-stop[1]
+ return sqrt(dx*dx+dy*dy)
diff --git a/CardSortActivity.pyc b/CardSortActivity.pyc
new file mode 100644
index 0000000..c46c8ec
--- /dev/null
+++ b/CardSortActivity.pyc
Binary files differ
diff --git a/CardSortActivity.py~ b/CardSortActivity.py~
new file mode 100644
index 0000000..3d24ad1
--- /dev/null
+++ b/CardSortActivity.py~
@@ -0,0 +1,318 @@
+#Copyright (c) 2009, Walter Bender
+
+#Permission is hereby granted, free of charge, to any person obtaining a copy
+#of this software and associated documentation files (the "Software"), to deal
+#in the Software without restriction, including without limitation the rights
+#to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+#copies of the Software, and to permit persons to whom the Software is
+#furnished to do so, subject to the following conditions:
+
+#The above copyright notice and this permission notice shall be included in
+#all copies or substantial portions of the Software.
+
+#THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+#IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+#FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+#AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+#LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+#OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+#THE SOFTWARE.
+
+import pygtk
+pygtk.require('2.0')
+import gtk
+import gobject
+
+import sugar
+from sugar.activity import activity
+from sugar.bundle.activitybundle import ActivityBundle
+from sugar.activity.widgets import ActivityToolbarButton
+from sugar.activity.widgets import StopButton
+from sugar.graphics.toolbarbox import ToolbarBox
+from sugar.graphics.toolbarbox import ToolbarButton
+from sugar.graphics.toolbutton import ToolButton
+from sugar.graphics.menuitem import MenuItem
+from sugar.graphics.icon import Icon
+from sugar.graphics import style
+from sugar.datastore import datastore
+
+from sugar import profile
+from gettext import gettext as _
+import locale
+import os.path
+from sprites import *
+from math import sqrt
+
+class taWindow: pass
+
+SERVICE = 'org.sugarlabs.CardSortActivity'
+IFACE = SERVICE
+PATH = '/org/augarlabs/CardSortActivity'
+
+CARD_DIM = 135
+CARD_DEFS = ((1,3,-2,-3),(2,3,-3,-2),(2,3,-4,-4),\
+ (2,1,-1,-4),(3,4,-4,-3),(4,2,-1,-2),\
+ (1,1,-2,-4),(4,2,-3,-4),(1,3,-1,-2))
+
+
+#
+# class for defining 3x3 matrix of cards
+#
+class Grid:
+ # 123
+ # 456
+ # 789
+ def __init__(self,tw):
+ self.grid = [1,2,3,4,5,6,7,8,9]
+ self.card_table = {}
+ # Initialize the cards
+ i = 0
+ x = (tw.width-(CARD_DIM*3))/2
+ y = (tw.height-(CARD_DIM*3))/2
+ for c in CARD_DEFS:
+ self.card_table[i] = Card(tw,c,i,x,y)
+ self.card_table[i].draw_card()
+ x += CARD_DIM
+ if x > (tw.width+(CARD_DIM*2))/2:
+ x = (tw.width-(CARD_DIM*3))/2
+ y += CARD_DIM
+ i += 1
+
+ def swap(self,a,b):
+ # swap grid elements and x,y positions of sprites
+ print "swapping cards " + str(a) + " and " + str(b)
+ tmp = self.grid[a]
+ x = self.card_table[a].spr.x
+ y = self.card_table[a].spr.y
+ self.grid[a] = self.grid[b]
+ self.card_table[a].spr.x = self.card_table[b].spr.x
+ self.card_table[a].spr.y = self.card_table[b].spr.y
+ self.grid[b] = tmp
+ self.card_table[b].spr.x = x
+ self.card_table[b].spr.y = y
+
+ def print_grid(self):
+ print self.grid
+ return
+
+ def test(self):
+ for i in (0,1,3,4,6,7):
+ if self.card_table[self.grid[i]].east + \
+ self.card_table[self.grid[i+1]].west != 0:
+ return False
+ for i in (0,1,2,3,4,5):
+ if self.card_table[self.grid[i]].south + \
+ self.card_table[self.grid[i+3]].north != 0:
+ return False
+ return True
+
+
+#
+# class for defining individual cards
+#
+class Card:
+ # Spade = 1,-1
+ # Heart = 2,-2
+ # Club = 3,-3
+ # Diamond = 4,-4
+ def __init__(self,tw,c,i,x,y):
+ self.north = c[0]
+ self.east = c[1]
+ self.south = c[2]
+ self.west = c[3]
+ self.rotate = 0
+ # create sprite from svg file
+ self.spr = sprNew(tw,x,y,self.load_image(tw.path,i))
+ self.spr.label = i
+
+ def draw_card(self):
+ setlayer(self.spr,2000)
+ draw(self.spr)
+
+ def load_image(self, file, i):
+ print "loading " + os.path.join(file + str(i) + '.svg')
+ return gtk.gdk.pixbuf_new_from_file(os.path.join(file + \
+ str(i) + "x" + \
+ '.svg'))
+
+ def rotate_ccw(self):
+ # print "rotating card " + str(self.spr.label)
+ tmp = self.north
+ self.north = self.east
+ self.east = self.south
+ self.south = self.west
+ self.west = tmp
+ self.rotate += 90
+ if self.rotate > 359:
+ self.rotate -= 360
+ tmp = self.spr.image.rotate_simple(90)
+ self.spr.image = tmp
+
+ def print_card(self):
+ print "(" + str(self.north) + "," + str(self.east) + \
+ "," + str(self.south) + "," + str(self.west) + \
+ ") " + str(self.rotate) + "ccw" + \
+ " x:" + str(self.spr.x) + " y:" + str(self.spr.y)
+
+#
+# Sugar activity
+#
+class CardSortActivity(activity.Activity):
+
+ def __init__(self, handle):
+ super(CardSortActivity,self).__init__(handle)
+
+ # Use 0.86 toolbar design
+ toolbar_box = ToolbarBox()
+
+ # Buttons added to the Activity toolbar
+ activity_button = ActivityToolbarButton(self)
+ toolbar_box.toolbar.insert(activity_button, 0)
+ activity_button.show()
+
+ # Solver button
+ self.solve_puzzle = ToolButton( "solve-off" )
+ self.solve_puzzle.set_tooltip(_('Solve it'))
+ self.solve_puzzle.props.sensitive = True
+ self.solve_puzzle.connect('clicked', self._solver_cb)
+ toolbar_box.toolbar.insert(self.solve_puzzle, -1)
+ self.solve_puzzle.show()
+
+ separator = gtk.SeparatorToolItem()
+ separator.show()
+ toolbar_box.toolbar.insert(separator, -1)
+
+ # Label for showing status
+ self.results_label = gtk.Label(_("click to rotate; drag to swap"))
+ self.results_label.show()
+ results_toolitem = gtk.ToolItem()
+ results_toolitem.add(self.results_label)
+ toolbar_box.toolbar.insert(results_toolitem,-1)
+
+ separator = gtk.SeparatorToolItem()
+ separator.props.draw = False
+ separator.set_expand(True)
+ separator.show()
+ toolbar_box.toolbar.insert(separator, -1)
+
+ # The ever-present Stop Button
+ stop_button = StopButton(self)
+ stop_button.props.accelerator = '<Ctrl>Q'
+ toolbar_box.toolbar.insert(stop_button, -1)
+ stop_button.show()
+
+ self.set_toolbar_box(toolbar_box)
+ toolbar_box.show()
+
+ # Create a canvas
+ canvas = gtk.DrawingArea()
+ canvas.set_size_request(gtk.gdk.screen_width(), \
+ gtk.gdk.screen_height())
+ self.set_canvas(canvas)
+ self.show_all()
+
+ # Initialize the canvas
+ self.tw = taWindow()
+ self.tw.window = canvas
+ canvas.set_flags(gtk.CAN_FOCUS)
+ canvas.add_events(gtk.gdk.BUTTON_PRESS_MASK)
+ canvas.add_events(gtk.gdk.BUTTON_RELEASE_MASK)
+ canvas.connect("expose-event", self._expose_cb, self.tw)
+ canvas.connect("button-press-event", self._button_press_cb, self.tw)
+ canvas.connect("button-release-event", self._button_release_cb, self.tw)
+ self.tw.width = gtk.gdk.screen_width()
+ self.tw.height = gtk.gdk.screen_height()-style.GRID_CELL_SIZE
+ self.tw.area = canvas.window
+ self.tw.gc = self.tw.area.new_gc()
+ self.tw.scale = 5
+ self.tw.cm = self.tw.gc.get_colormap()
+ self.tw.msgcolor = self.tw.cm.alloc_color('black')
+ self.tw.sprites = []
+
+ # Initialize the grid
+ self.tw.path = os.path.join(activity.get_bundle_path(),'images/card')
+ self.tw.grid = Grid(self.tw)
+
+ # Start solving the puzzle
+ self.tw.press = -1
+ self.tw.release = -1
+ self.tw.start_drag = [0,0]
+
+ #
+ # Solver
+ #
+ def _solver_cb(self, button):
+ self.solve_puzzle.set_icon("solve-on")
+ """
+ We need to write this code
+ """
+ self.results_label.set_text(_("I don't know how to solve it."))
+ self.results_label.show()
+ self.solve_puzzle.set_icon("solve-off")
+ return True
+
+
+ #
+ # Repaint
+ #
+ def _expose_cb(self, win, event, tw):
+ redrawsprites(tw)
+ return True
+
+ #
+ # Button press
+ #
+ def _button_press_cb(self, win, event, tw):
+ win.grab_focus()
+ x, y = map(int, event.get_coords())
+ tw.start_drag = [x,y]
+ spr = findsprite(tw,(x,y))
+ if spr is None:
+ tw.press = -1
+ tw.release = -1
+ return True
+ # take note of card under button press
+ tw.press = spr.label
+ return True
+
+ #
+ # Button release
+ #
+ def _button_release_cb(self, win, event, tw):
+ win.grab_focus()
+ x, y = map(int, event.get_coords())
+ spr = findsprite(tw,(x,y))
+ if spr is None:
+ tw.press = -1
+ tw.release = -1
+ return True
+ # take note of card under button release
+ tw.release = spr.label
+ # if the same card (click) then rotate
+ if tw.press == tw.release:
+ # check to see if it was an aborted move
+ if self.distance(tw.start_drag,[x,y]) < 20:
+ tw.grid.card_table[tw.press].rotate_ccw()
+ # tw.grid.card_table[tw.press].print_card()
+ # if different card (drag) then swap
+ else:
+ tw.grid.swap(tw.press,tw.release)
+ # tw.grid.print_grid()
+ inval(tw.grid.card_table[tw.press].spr)
+ inval(tw.grid.card_table[tw.release].spr)
+ redrawsprites(tw)
+ tw.press = -1
+ tw.release = -1
+ if tw.grid.test() == True:
+ self.results_label.set_text(_("You solved the puzzle."))
+ self.results_label.show()
+ else:
+ self.results_label.set_text(_("Keep trying."))
+ self.results_label.show()
+
+ return True
+
+ def distance(self,start,stop):
+ dx = start[0]-stop[0]
+ dy = start[1]-stop[1]
+ return sqrt(dx*dx+dy*dy)
diff --git a/MANIFEST b/MANIFEST
new file mode 100644
index 0000000..e06c57a
--- /dev/null
+++ b/MANIFEST
@@ -0,0 +1,31 @@
+CardSortActivity.py
+NEWS
+COPYING
+sprites.py
+setup.py
+activity/application-x-turtle-art.svg
+activity/activity-cardsort.svg
+activity/activity.info
+activity/mimetypes.xml
+images/card4.svg
+images/card3.svg
+images/card7.svg
+images/card8.svg
+images/card6.svg
+
+images/card1.svg
+images/card0.svg
+images/card2.svg
+images/card5.svg
+icons/solve-on.svg
+icons/solve-off.svg
+po/CardSort.pot
+images/card1x.svg
+images/card7x.svg
+images/card4x.svg
+images/card2x.svg
+images/card3x.svg
+images/card0x.svg
+images/card5x.svg
+images/card8x.svg
+images/card6x.svg
diff --git a/MANIFEST~ b/MANIFEST~
new file mode 100644
index 0000000..8294cf1
--- /dev/null
+++ b/MANIFEST~
@@ -0,0 +1,24 @@
+CardSortActivity.py
+NEWS
+COPYING
+sprites.py
+
+setup.py
+activity/application-x-turtle-art.svg
+activity/activity-cardsort.svg
+activity/activity.info
+activity/mimetypes.xml
+images/card4.svg
+images/card3.svg
+images/card7.svg
+images/card8.svg
+images/card6.svg
+images/cards.svg
+images/card1.svg
+images/card0.svg
+images/card2.svg
+images/card1mask.svg
+images/card5.svg
+icons/solve-on.svg
+icons/solve-off.svg
+po/CardSort.pot
diff --git a/NEWS b/NEWS
new file mode 100644
index 0000000..e27425b
--- /dev/null
+++ b/NEWS
@@ -0,0 +1,3 @@
+1
+
+Card Sorting puzzle project
diff --git a/NEWS~ b/NEWS~
new file mode 100644
index 0000000..7143277
--- /dev/null
+++ b/NEWS~
@@ -0,0 +1,350 @@
+70
+
+* new translations/artwork for vi
+* added linewrap to help label (with rgs)
+* added label to Help toolbar
+* new translations for it
+* caught some exceptions that prevented TA from running outside of Sugar
+* fixed bug preventing simple save to HTML for pre-086 systems
+
+69
+
+* chmod +x svg factory
+* added missing import gettext from talogo.py
+* renamed xo-man to xo-child
+* caught missing attribute when running from outside of Sugar
+* new translations/artwork for de, fr, es, it
+* added translator comments
+* fixed several bugs in export to Logo code
+
+68
+
+* made case consistent on tool tips
+* fixed bug re i18n in debug panel
+* new artwork for es and fr
+* fixed some problems with svg factory
+* fixed bug in Export HTML
+* fixed naming problem with all save_as functions
+* fixed bug in Export Logo in regard to start block
+
+67
+
+* added mime-type icon
+* changed keyboard shortcuts to use Ctrl instead of Alt as per guidelines
+* fixed bug re wait time (now in seconds)
+* fixed problem with fractional wait times
+* fixed i18n problem with labels in hover help
+* reorganization of extras palette
+* fixed problem of empty file with "Save as HTML" (saving screen capture)
+
+66
+
+* fixed bug preventing launch on (0.82-0.84)
+* work around Rainbow problem with Save as image
+* fixed bug re activate Stop Button on launch (thanks to rgs)
+* added open from journal button (with rgs)
+* fixed bug re Erase Button (hides status blocks)
+* cleaned up some broken sample code
+
+65
+
+* fixed problem with View Toolbar
+* moved Samples button to Help Toolbar
+
+64
+
+* major refactoring for new toolbar design
+* stop sign turns off after execution is finished
+* added preliminary support for mg and ta
+* moved hover help to help toolbar
+* adjusted artwork on Turtle palette
+
+63
+
+* more sample programs
+* consolidated samples into one directory
+* fixed mask bug that prevented palette hiding
+
+62
+
+* first pass at hover help support (thanks Raul)
+* put samples button, keep button on project toolbar
+* fixed journal icons associated with html, python, logo
+* improved compatibility with old Sugar builds
+* images centered under turtle
+* text vertically centered under turtle
+* pop blocks snap into boxes
+* improved masks for fewer block-selection errors
+
+
+61
+
+* fixed es translation
+* fixed problem with save/load on old systems
+
+60
+
+* fixed sharing bug
+* began work on 701 backward compatibility
+* added more debugging code
+
+59
+
+* fixed leading bug for OLPC XO portfolio
+* enabled box to hold strings and journal objects
+
+58
+
+* fixed unicode string compare in equal block
+* fixed journal description bug introduced in v55
+* fixed misaligned myfunc block problem
+
+
+57
+
+* lots of artwork clean up
+* elimination of lock block
+* more dead key clean ups
+* truncated strings
+
+56
+
+* more dead key cleanup
+* empty (undefined) box error message
+
+55
+
+* dead key workaround
+
+54
+
+* debug button
+* no more decimals by default for print
+
+53
+
+* es updates
+
+52
+
+* first attempt at fixing the mimetypes
+* default behavior of tamyblock.py is to draw a dotted line
+
+51
+
+* caught ISO_Level3_Shift problem on OLPC XO keyboard
+
+50
+
+* fixed some problems with taexportlogo
+* cleaned up save/load icons
+* print uses title for Journal objects
+* cleaned up movie window destroy code
+* more consistent template management internally
+* support of a sort for show in taexporthtml
+
+49
+
+* fixed character input bug
+
+48
+
+* reworking of media blocks
+* json cleanup
+
+47
+
+* image export
+* pot update
+
+46
+
+* full screen mode
+* scrolled window
+* better support for running from the command line
+
+45
+
+* alt chars for keyboard shortcuts
+* visual feedback for user-defined blocks when "loaded"
+
+44
+
+* adding user defineable block
+
+43
+
+* new de artwork
+
+42
+
+* removed unneeded Numeric dependencies
+
+41
+
+* end run around addons bug?
+
+40
+
+* improvements to it artwork
+
+39
+
+* improvements to nl and sv artwork
+
+38
+
+* improvements to de artwork
+
+37
+
+* adding de sl sv
+* cleaned up SVGs
+
+36
+
+* added el, vi, zh_TW
+
+35
+
+* updated depreciated fields in activity.info
+* added svg/*.py files to generate svgs from .po
+* added nl
+
+34
+
+* added it; cleaned up fr; converted to cjson (with help from silbe)
+
+33
+
+* merge with TAPortfolio (and elimination of Sensor and myblock features)
+
+32
+
+* rebase on TAPortfolio code
+
+31
+
+* run and step
+
+30
+
+* fixed broken POT file
+
+29
+
+* new artwork, better i18n
+
+28
+
+* added push and pop (en only)
+
+27
+
+* add named boxes and stacks
+
+26
+
+* allow new blocks to be created by clicking in addition to drag and drop
+
+25
+
+* added sensor panel from TurtleArt with Sensors
+* catch exceptions where DC Audio is not available (non-OLPC_XO-1 hardware)
+
+24
+
+* add UCB logo export
+* check for conditions where image cache needs refreshing
+
+23
+
+* caching images
+
+22
+
+* added POT file
+
+21
+
+* added ru
+* fixed errors in fr and mn
+
+20
+
+* fixed translation problem with Spanish "poner en caja"
+* PT translation
+* height = toolbox.get_size()[1]
+* setyx
+* adding po files
+
+19
+
+* removed "sugar.activity import registry"
+
+18
+
+* Finnish
+* SVG cleanup
+
+17
+
+* SVG support
+* support for non-1200x900 displays
+
+16
+
+* Mongolian
+
+15
+
+* shebang patch
+
+14
+
+* Changed more file permissions (-x)
+* Deleted some redundant files (stray myblockgroup.gif files)
+* Add #!/usr/bin/env python to taturtle.py
+
+13
+
+* Added Turkish (tr) artwork
+* Changed permissions on artwork (-x)
+
+12
+
+* Added sqrt function
+
+11
+
+* Rename activity from TurtleArt to Turtle Art (dlo trac #2663)
+* Fix pen up in arc (dlo trac #7656)
+* Point update url at a protected page.
+
+10
+
+* licensing information in activity.info (dlo trac #6340)
+* new samples
+* improved icon (dlo trac #6836)
+
+9
+
+* added french images
+* fixed a few typos
+* fixed divide by zero bug
+
+8
+
+* added license
+
+7
+
+* simple i18n
+
+6
+
+* Graphics changes
+
+5
+
+* Multi instance happy
diff --git a/activity-cardsort.png b/activity-cardsort.png
new file mode 100644
index 0000000..154c96c
--- /dev/null
+++ b/activity-cardsort.png
Binary files differ
diff --git a/activity/activity-cardsort.svg b/activity/activity-cardsort.svg
new file mode 100644
index 0000000..b6903c1
--- /dev/null
+++ b/activity/activity-cardsort.svg
@@ -0,0 +1,16 @@
+<?xml version="1.0" ?>
+<!DOCTYPE svg PUBLIC '-//W3C//DTD SVG 1.1//EN' 'http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd' [
+ <!ENTITY stroke_color "#000">
+ <!ENTITY fill_color "#eee">
+]>
+<svg height="55px" viewBox="0 0 55 55" width="55px" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" stroke-linecap="round" stroke-linejoin="round" stroke-width="3.5" stroke="&stroke_color;" fill="&fill_color;">
+ <g transform="matrix(0.35,0,0,0.35,-86,-149)">
+ <path
+ d="M 43.125,0.28125 C 38.752029,0.38960001 34.34065,7.48886 35.75,12.3125 C 36.959209,16.45113 45.59375,25.3125 45.59375,25.3125 L 45.59375,35.3125 L 0.5,35.3125 L 0.5,80.3125 L 15.5,80.3125 C 15.5,80.3125 12.01332,70.308533 20.5,70.3125 C 28.98668,70.31647 25.5,80.312497 25.5,80.3125 C 25.5,80.3125 35.462309,76.883632 35.5,85.28125 C 35.53769,93.67887 25.5,90.281249 25.5,90.28125 C 25.5,90.28125 28.09181,100.43092 20.5,100.28125 C 12.9082,100.13158 15.5,90.281249 15.5,90.28125 L 0.5,90.28125 L 0.5,135.3125 L 45.59375,135.3125 L 45.59375,125.3125 C 45.59375,125.3125 36.959209,116.45113 35.75,112.3125 C 34.34065,107.48886 38.752029,100.3896 43.125,100.28125 C 47.49798,100.17293 50.500001,105.28125 50.5,105.28125 C 50.5,105.28125 53.31129,100.28762 57.90625,100.28125 C 62.50121,100.27488 66.555577,107.45016 65.28125,112.3125 C 64.17038,116.55114 55.437499,125.3125 55.4375,125.3125 L 55.4375,135.3125 L 100.5,135.3125 L 100.5,90.28125 L 115.5,90.28125 C 115.5,90.281249 112.9082,100.13158 120.5,100.28125 C 128.09181,100.43092 125.5,90.28125 125.5,90.28125 C 125.5,90.281249 135.53769,93.67887 135.5,85.28125 C 135.4623,76.883632 125.5,80.3125 125.5,80.3125 C 125.5,80.312497 128.98668,70.31647 120.5,70.3125 C 112.01332,70.308533 115.5,80.3125 115.5,80.3125 L 100.5,80.3125 L 100.5,35.3125 L 55.4375,35.3125 L 55.4375,25.3125 C 55.437499,25.312499 64.17038,16.55114 65.28125,12.3125 C 66.555577,7.4501605 62.50121,0.27488 57.90625,0.28125 C 53.31129,0.28762001 50.5,5.28125 50.5,5.28125 C 50.500001,5.2812498 47.49798,0.17293 43.125,0.28125 z"
+ transform="translate(252.5,430.6)"
+ fill="&fill_color;"
+ stroke="&stroke_color;"
+ stroke-width="8"
+ />
+ </g>
+</svg>
diff --git a/activity/activity.info b/activity/activity.info
new file mode 100644
index 0000000..4df192a
--- /dev/null
+++ b/activity/activity.info
@@ -0,0 +1,9 @@
+
+[Activity]
+name = Card Sort
+activity_version = 1
+license = GPLv3
+bundle_id = org.sugarlabs.CardSortActivity
+exec = sugar-activity CardSortActivity.CardSortActivity
+icon = activity-cardsort
+show_launcher = yes
diff --git a/dist/CardSort-1.tar.bz2 b/dist/CardSort-1.tar.bz2
new file mode 100644
index 0000000..c17a69e
--- /dev/null
+++ b/dist/CardSort-1.tar.bz2
Binary files differ
diff --git a/dist/CardSort-1.xo b/dist/CardSort-1.xo
new file mode 100644
index 0000000..b482f18
--- /dev/null
+++ b/dist/CardSort-1.xo
Binary files differ
diff --git a/icons/solve-off.svg b/icons/solve-off.svg
new file mode 100644
index 0000000..6ba2790
--- /dev/null
+++ b/icons/solve-off.svg
@@ -0,0 +1,141 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+<svg
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ version="1.0"
+ width="55"
+ height="55"
+ id="svg2">
+ <defs
+ id="defs4" />
+ <path
+ d="M 12.3583,20.48583 C 12.3583,27.434109 10.713354,33.066802 8.6842109,33.066802 C 6.6550675,33.066802 5.0101218,27.434109 5.0101218,20.48583 C 5.0101218,13.537551 6.6550675,7.9048577 8.6842109,7.9048577 C 10.713354,7.9048577 12.3583,13.537551 12.3583,20.48583 L 12.3583,20.48583 z"
+ transform="matrix(7.4848487,0,0,2.1858407,-37.500004,-17.278762)"
+ id="path3188"
+ style="opacity:1;fill:#808080;fill-opacity:1;stroke:none;stroke-width:0.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ <g
+ transform="matrix(1.5,0,0,1.5,-13.078338,-13.158384)"
+ id="g2418">
+ <path
+ d="M 27.377856,20.343519 C 28.321,19.020469 30.286922,18.112089 30.821749,18.291101 C 31.638084,18.564336 33.456136,19.576235 33.650054,20.161715 C 34.013498,21.259028 33.209093,22.374586 32.988611,23.481022"
+ id="path3252"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.51091182px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
+ <path
+ d="M 31.312226,33.70644 C 28.236767,39.033292 23.160414,41.860147 19.973874,40.020398 C 16.787334,38.180648 16.697287,32.37097 19.772746,27.044118 C 22.848206,21.717266 27.924558,18.890411 31.111098,20.73016 C 34.297638,22.56991 34.387686,28.379588 31.312226,33.70644 L 31.312226,33.70644 z"
+ id="path3197"
+ style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:1.51091182;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ <path
+ d="M 30.640788,20.96543 C 27.28475,27.009989 27.339614,26.914963 27.339614,26.914963"
+ id="path3199"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.51091182px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
+ <path
+ d="M 23.640267,22.485322 C 24.595846,24.37818 25.974761,25.728012 27.471512,26.982445 C 27.498847,27.005355 31.460104,28.392057 33.385523,28.013934"
+ id="path3201"
+ style="fill:none;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.51091182px;stroke-linecap:butt;stroke-linejoin:round;stroke-opacity:1" />
+ <path
+ d="M 22.8141,25.484531 C 25.194146,27.945239 25.221038,27.960765 25.221038,27.960765"
+ id="path3203"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.75545591;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ <path
+ d="M 21.785315,26.831706 C 24.165361,29.292415 24.336387,29.493024 24.336387,29.493024"
+ id="path3207"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.75545591;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ <path
+ d="M 20.834693,28.29192 C 23.214739,30.752628 23.451737,31.025283 23.451737,31.025283"
+ id="path3209"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.75545591;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ <path
+ d="M 20.016015,29.896225 C 22.39606,32.356934 22.567086,32.557543 22.567086,32.557543"
+ id="path3211"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.75545591;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ <path
+ d="M 19.370877,31.63468 C 21.750923,34.095389 21.682436,34.089803 21.682436,34.089803"
+ id="path3213"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.75545591;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ <path
+ d="M 19.111902,33.697954 C 21.364647,36.254945 20.797785,35.622064 20.797785,35.622064"
+ id="path3215"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.75545591;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ <path
+ d="M 19.133652,36.330772 C 19.703029,36.897193 19.913135,37.154321 19.913135,37.154321"
+ id="path3217"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.75545591;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ <path
+ d="M 30.786085,30.087159 C 27.465026,29.256333 27.438134,29.240807 27.438134,29.240807"
+ id="path3230"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.75545591;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ <path
+ d="M 30.133789,31.6517 C 26.81273,30.820874 26.553484,30.773066 26.553484,30.773066"
+ id="path3232"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.75545591;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ <path
+ d="M 29.344518,33.20507 C 26.023459,32.374244 25.668834,32.305325 25.668834,32.305325"
+ id="path3234"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.75545591;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ <path
+ d="M 28.364488,34.716219 C 25.043429,33.885393 24.784183,33.837585 24.784183,33.837585"
+ id="path3236"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.75545591;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ <path
+ d="M 27.18151,36.144152 C 23.860451,35.313326 23.899532,35.369845 23.899532,35.369845"
+ id="path3238"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.75545591;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ <path
+ d="M 25.524151,37.400068 C 22.183359,36.727629 23.014881,36.902105 23.014881,36.902105"
+ id="path3240"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.75545591;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ <path
+ d="M 23.233189,38.697641 C 22.457965,38.487756 22.130232,38.434363 22.130232,38.434363"
+ id="path3242"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.75545591;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ <path
+ d="M 38.499043,20.363658 C 37.800794,21.573059 36.199476,21.955755 34.922399,21.218434 C 33.645322,20.481114 33.176087,18.902983 33.874335,17.693582 C 34.572584,16.48418 36.173902,16.101484 37.450979,16.838805 C 38.728056,17.576125 39.197291,19.154256 38.499043,20.363658 z"
+ id="path3244"
+ style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:0.84691685;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ <path
+ d="M 36.397626,17.843099 C 36.200351,18.18479 35.747932,18.292914 35.38712,18.084599 C 35.026308,17.876284 34.893736,17.430416 35.091011,17.088724 C 35.288287,16.747033 35.740706,16.63891 36.101518,16.847225 C 36.46233,17.05554 36.594902,17.501408 36.397626,17.843099 z"
+ id="path3246"
+ style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:0.79813904;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ <path
+ d="M 32.748117,16.754734 C 32.049869,17.964135 30.44855,18.346831 29.171473,17.60951 C 27.894396,16.87219 27.425162,15.294059 28.12341,14.084658 C 28.821659,12.875256 30.422977,12.49256 31.700054,13.229881 C 32.977131,13.967201 33.446366,15.545332 32.748117,16.754734 z"
+ id="path3248"
+ style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:0.84691685;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ <path
+ d="M 30.781161,14.311805 C 30.583886,14.653496 30.131467,14.76162 29.770655,14.553305 C 29.409842,14.34499 29.27727,13.899122 29.474546,13.55743 C 29.671821,13.215739 30.124241,13.107616 30.485053,13.315931 C 30.845865,13.524246 30.978437,13.970114 30.781161,14.311805 z"
+ id="path3250"
+ style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:0.79813904;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ <path
+ d="M 32.6771,18.762402 C 34.592724,15.340936 37.749452,14.220631 37.749452,14.220631 L 37.749452,14.220631"
+ id="path3254"
+ style="fill:none;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.75545591;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ <path
+ d="M 32.234792,18.337256 C 34.240057,14.967544 33.631905,11.673585 33.631905,11.673585 L 33.631905,11.673585"
+ id="path3258"
+ style="fill:none;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.75545591;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ <path
+ d="M 26.988213,20.231746 L 25.8722,15.229742 L 22.062204,17.274526"
+ id="path3260"
+ style="fill:none;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.51091182px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
+ <path
+ d="M 33.361036,23.684723 L 36.94565,22.754865 L 39.828331,26.456535"
+ id="path3262"
+ style="fill:none;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.51091182px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
+ <path
+ d="M 23.851158,22.042526 L 22.753536,18.975309 L 14.588602,21.731577"
+ id="path3264"
+ style="fill:none;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.51091182px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
+ <path
+ d="M 33.777334,27.207476 L 37.251354,26.779696 L 37.749256,34.197896"
+ id="path3266"
+ style="fill:none;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.51091182px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
+ <path
+ d="M 20.388485,25.668558 L 19.349188,23.00868 L 12.485021,29.515384"
+ id="path3268"
+ style="fill:none;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.51091182px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
+ <path
+ d="M 32.410841,31.851473 L 35.330898,30.934083 L 33.3031,40.346252"
+ id="path3270"
+ style="fill:none;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.51091182px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
+ </g>
+</svg>
diff --git a/icons/solve-on.svg b/icons/solve-on.svg
new file mode 100644
index 0000000..491ae78
--- /dev/null
+++ b/icons/solve-on.svg
@@ -0,0 +1,141 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+<svg
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ version="1.0"
+ width="55"
+ height="55"
+ id="svg2">
+ <defs
+ id="defs4" />
+ <path
+ d="M 12.3583,20.48583 C 12.3583,27.434109 10.713354,33.066802 8.6842109,33.066802 C 6.6550675,33.066802 5.0101218,27.434109 5.0101218,20.48583 C 5.0101218,13.537551 6.6550675,7.9048577 8.6842109,7.9048577 C 10.713354,7.9048577 12.3583,13.537551 12.3583,20.48583 L 12.3583,20.48583 z"
+ transform="matrix(7.4848487,0,0,2.1858407,-37.500004,-17.278762)"
+ id="path3188"
+ style="opacity:1;fill:#00ff00;fill-opacity:1;stroke:none;stroke-width:0.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ <g
+ transform="matrix(1.5,0,0,1.5,-13.078338,-13.158384)"
+ id="g3188">
+ <path
+ d="M 27.377856,20.343519 C 28.321,19.020469 30.286922,18.112089 30.821749,18.291101 C 31.638084,18.564336 33.456136,19.576235 33.650054,20.161715 C 34.013498,21.259028 33.209093,22.374586 32.988611,23.481022"
+ id="path3252"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.51091182px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
+ <path
+ d="M 31.312226,33.70644 C 28.236767,39.033292 23.160414,41.860147 19.973874,40.020398 C 16.787334,38.180648 16.697287,32.37097 19.772746,27.044118 C 22.848206,21.717266 27.924558,18.890411 31.111098,20.73016 C 34.297638,22.56991 34.387686,28.379588 31.312226,33.70644 L 31.312226,33.70644 z"
+ id="path3197"
+ style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:1.51091182;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ <path
+ d="M 30.640788,20.96543 C 27.28475,27.009989 27.339614,26.914963 27.339614,26.914963"
+ id="path3199"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.51091182px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
+ <path
+ d="M 23.640267,22.485322 C 24.595846,24.37818 25.974761,25.728012 27.471512,26.982445 C 27.498847,27.005355 31.460104,28.392057 33.385523,28.013934"
+ id="path3201"
+ style="fill:none;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.51091182px;stroke-linecap:butt;stroke-linejoin:round;stroke-opacity:1" />
+ <path
+ d="M 22.8141,25.484531 C 25.194146,27.945239 25.221038,27.960765 25.221038,27.960765"
+ id="path3203"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.75545591;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ <path
+ d="M 21.785315,26.831706 C 24.165361,29.292415 24.336387,29.493024 24.336387,29.493024"
+ id="path3207"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.75545591;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ <path
+ d="M 20.834693,28.29192 C 23.214739,30.752628 23.451737,31.025283 23.451737,31.025283"
+ id="path3209"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.75545591;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ <path
+ d="M 20.016015,29.896225 C 22.39606,32.356934 22.567086,32.557543 22.567086,32.557543"
+ id="path3211"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.75545591;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ <path
+ d="M 19.370877,31.63468 C 21.750923,34.095389 21.682436,34.089803 21.682436,34.089803"
+ id="path3213"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.75545591;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ <path
+ d="M 19.111902,33.697954 C 21.364647,36.254945 20.797785,35.622064 20.797785,35.622064"
+ id="path3215"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.75545591;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ <path
+ d="M 19.133652,36.330772 C 19.703029,36.897193 19.913135,37.154321 19.913135,37.154321"
+ id="path3217"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.75545591;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ <path
+ d="M 30.786085,30.087159 C 27.465026,29.256333 27.438134,29.240807 27.438134,29.240807"
+ id="path3230"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.75545591;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ <path
+ d="M 30.133789,31.6517 C 26.81273,30.820874 26.553484,30.773066 26.553484,30.773066"
+ id="path3232"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.75545591;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ <path
+ d="M 29.344518,33.20507 C 26.023459,32.374244 25.668834,32.305325 25.668834,32.305325"
+ id="path3234"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.75545591;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ <path
+ d="M 28.364488,34.716219 C 25.043429,33.885393 24.784183,33.837585 24.784183,33.837585"
+ id="path3236"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.75545591;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ <path
+ d="M 27.18151,36.144152 C 23.860451,35.313326 23.899532,35.369845 23.899532,35.369845"
+ id="path3238"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.75545591;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ <path
+ d="M 25.524151,37.400068 C 22.183359,36.727629 23.014881,36.902105 23.014881,36.902105"
+ id="path3240"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.75545591;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ <path
+ d="M 23.233189,38.697641 C 22.457965,38.487756 22.130232,38.434363 22.130232,38.434363"
+ id="path3242"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.75545591;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ <path
+ d="M 38.499043,20.363658 C 37.800794,21.573059 36.199476,21.955755 34.922399,21.218434 C 33.645322,20.481114 33.176087,18.902983 33.874335,17.693582 C 34.572584,16.48418 36.173902,16.101484 37.450979,16.838805 C 38.728056,17.576125 39.197291,19.154256 38.499043,20.363658 z"
+ id="path3244"
+ style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:0.84691685;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ <path
+ d="M 36.397626,17.843099 C 36.200351,18.18479 35.747932,18.292914 35.38712,18.084599 C 35.026308,17.876284 34.893736,17.430416 35.091011,17.088724 C 35.288287,16.747033 35.740706,16.63891 36.101518,16.847225 C 36.46233,17.05554 36.594902,17.501408 36.397626,17.843099 z"
+ id="path3246"
+ style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:0.79813904;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ <path
+ d="M 32.748117,16.754734 C 32.049869,17.964135 30.44855,18.346831 29.171473,17.60951 C 27.894396,16.87219 27.425162,15.294059 28.12341,14.084658 C 28.821659,12.875256 30.422977,12.49256 31.700054,13.229881 C 32.977131,13.967201 33.446366,15.545332 32.748117,16.754734 z"
+ id="path3248"
+ style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:0.84691685;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ <path
+ d="M 30.781161,14.311805 C 30.583886,14.653496 30.131467,14.76162 29.770655,14.553305 C 29.409842,14.34499 29.27727,13.899122 29.474546,13.55743 C 29.671821,13.215739 30.124241,13.107616 30.485053,13.315931 C 30.845865,13.524246 30.978437,13.970114 30.781161,14.311805 z"
+ id="path3250"
+ style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:0.79813904;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ <path
+ d="M 32.6771,18.762402 C 34.592724,15.340936 37.749452,14.220631 37.749452,14.220631 L 37.749452,14.220631"
+ id="path3254"
+ style="fill:none;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.75545591;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ <path
+ d="M 32.234792,18.337256 C 34.240057,14.967544 33.631905,11.673585 33.631905,11.673585 L 33.631905,11.673585"
+ id="path3258"
+ style="fill:none;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.75545591;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ <path
+ d="M 26.988213,20.231746 L 25.8722,15.229742 L 22.062204,17.274526"
+ id="path3260"
+ style="fill:none;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.51091182px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
+ <path
+ d="M 33.361036,23.684723 L 36.94565,22.754865 L 39.828331,26.456535"
+ id="path3262"
+ style="fill:none;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.51091182px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
+ <path
+ d="M 23.851158,22.042526 L 22.753536,18.975309 L 14.588602,21.731577"
+ id="path3264"
+ style="fill:none;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.51091182px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
+ <path
+ d="M 33.777334,27.207476 L 37.251354,26.779696 L 37.749256,34.197896"
+ id="path3266"
+ style="fill:none;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.51091182px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
+ <path
+ d="M 20.388485,25.668558 L 19.349188,23.00868 L 12.485021,29.515384"
+ id="path3268"
+ style="fill:none;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.51091182px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
+ <path
+ d="M 32.410841,31.851473 L 35.330898,30.934083 L 33.3031,40.346252"
+ id="path3270"
+ style="fill:none;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.51091182px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
+ </g>
+</svg>
diff --git a/images/card0.svg b/images/card0.svg
new file mode 100644
index 0000000..e3640a8
--- /dev/null
+++ b/images/card0.svg
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+<svg
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ version="1.0"
+ width="135.00011"
+ height="135.00002"
+ id="svg5406">
+ <defs
+ id="defs5408" />
+ <g
+ transform="translate(-263.64643,-426.24546)"
+ id="layer1">
+ <path
+ d="M 50,-0.90625 C 50.024832,-0.88981002 34.87376,12.57703 35,19.09375 C 35.126229,25.610489 42.15031,24.51668 45,24.09375 L 45,34.09375 L 0.5,34.09375 L 0.5,79.59375 L 15.5,79.59375 C 15.5,79.59375 12.01332,69.589779 20.5,69.59375 C 28.98668,69.59772 25.5,79.593751 25.5,79.59375 C 25.5,79.59375 35.462309,76.196128 35.5,84.59375 C 35.53769,92.99137 25.5,89.593752 25.5,89.59375 C 25.5,89.59375 28.09181,99.743416 20.5,99.59375 C 12.9082,99.44408 15.5,89.593752 15.5,89.59375 L 0.5,89.59375 L 0.5,134.09375 L 45.09375,134.09375 L 45.09375,124.09375 C 45.09375,124.09375 36.45921,115.23238 35.25,111.09375 C 33.84065,106.27011 38.252031,99.202102 42.625,99.09375 C 46.99798,98.98543 49.999999,104.09375 50,104.09375 C 50,104.09375 52.811292,99.100122 57.40625,99.09375 C 62.00121,99.08738 66.055583,106.23141 64.78125,111.09375 C 63.67038,115.33239 54.9375,124.09375 54.9375,124.09375 L 54.9375,134.09375 L 100.5,134.09375 L 100.5,89.59375 L 115.5,89.59375 C 115.5,89.593752 112.9082,99.44408 120.5,99.59375 C 128.09181,99.743416 125.5,89.59375 125.5,89.59375 C 125.5,89.593752 135.53769,92.99137 135.5,84.59375 C 135.4623,76.196128 125.5,79.59375 125.5,79.59375 C 125.5,79.593751 128.98668,69.59772 120.5,69.59375 C 112.01332,69.589779 115.5,79.59375 115.5,79.59375 L 100.5,79.59375 L 100.5,34.09375 L 55,34.09375 L 55,24.09375 C 55.000002,24.093749 64.89639,26.32091 65,19.09375 C 65.103599,11.866599 49.97517,-0.92268 50,-0.90625 z"
+ transform="translate(263.14643,427.15173)"
+ id="path2392"
+ style="fill:#ff0000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.99997878px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
+ </g>
+</svg>
diff --git a/images/card0x.svg b/images/card0x.svg
new file mode 100644
index 0000000..9777e36
--- /dev/null
+++ b/images/card0x.svg
@@ -0,0 +1,57 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+<svg
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ version="1.0"
+ width="135"
+ height="135.00002"
+ id="svg3193">
+ <defs
+ id="defs3195" />
+ <path
+ d="M 1.1368684e-13,135 L 1.1368684e-13,-2.8421709e-14 L 135,-2.8421709e-14 L 135,135 L 1.1368684e-13,135 z"
+ id="path2395"
+ style="fill:#ff0000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1.34653473px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
+ <text
+ x="-103.33984"
+ y="-9.8339842e-06"
+ transform="scale(-1,-1)"
+ id="text3172"
+ xml:space="preserve"
+ style="font-size:80px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:DejaVu Sans;-inkscape-font-specification:DejaVu Sans"><tspan
+ x="-103.33984"
+ y="-9.8339842e-06"
+ id="tspan3174">♠</tspan></text>
+ <text
+ x="-103.32032"
+ y="135"
+ transform="matrix(0,-1,1,0,0,0)"
+ id="text3176"
+ xml:space="preserve"
+ style="font-size:80px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:DejaVu Sans;-inkscape-font-specification:DejaVu Sans"><tspan
+ x="-103.32032"
+ y="135"
+ id="tspan3178">♦</tspan></text>
+ <text
+ x="38.348389"
+ y="135.00002"
+ id="text3184"
+ xml:space="preserve"
+ style="font-size:80px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:100%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:DejaVu Sans;-inkscape-font-specification:DejaVu Sans"><tspan
+ x="38.348389"
+ y="135.00002"
+ id="tspan3186"
+ style="font-size:65px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:100%;writing-mode:lr-tb;text-anchor:start;fill:#ffffff;fill-opacity:1;font-family:DejaVu Sans;-inkscape-font-specification:DejaVu Sans">♥</tspan></text>
+ <text
+ x="-103.32032"
+ y="58.281246"
+ transform="matrix(0,-1,1,0,0,0)"
+ id="text3189"
+ xml:space="preserve"
+ style="font-size:80px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:DejaVu Sans;-inkscape-font-specification:DejaVu Sans"><tspan
+ x="-103.32032"
+ y="58.281246"
+ id="tspan3191"
+ style="fill:#ffffff;fill-opacity:1">♦</tspan></text>
+</svg>
diff --git a/images/card1.svg b/images/card1.svg
new file mode 100644
index 0000000..4aa754c
--- /dev/null
+++ b/images/card1.svg
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+<svg
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ version="1.0"
+ width="135.00011"
+ height="135.00169"
+ id="svg2388">
+ <defs
+ id="defs2390" />
+ <g
+ transform="translate(-226.50357,-360.53)"
+ id="layer1">
+ <path
+ d="M 42.625,1.71875 C 38.252031,1.8271001 33.84065,8.89511 35.25,13.71875 C 36.45921,17.85738 45.09375,26.71875 45.09375,26.71875 L 45.09375,36.71875 L 0.5,36.71875 L 0.5,82.3125 L 10.5,82.3125 C 10.5,82.3125 19.36137,73.677957 23.5,72.46875 C 28.32364,71.0594 35.391649,75.470778 35.5,79.84375 C 35.60832,84.21673 30.5,87.218754 30.5,87.21875 C 30.5,87.21875 35.493629,89.998789 35.5,94.59375 C 35.50637,99.18871 28.36234,103.24308 23.5,101.96875 C 19.26136,100.85788 10.5,92.124997 10.5,92.125 L 0.5,92.125 L 0.5,136.71875 L 45,136.71875 L 45,121.71875 C 45,121.71875 34.996031,125.20543 35,116.71875 C 35.00397,108.23207 44.999999,111.71875 45,111.71875 C 45,111.71875 41.60238,101.75644 50,101.71875 C 58.39762,101.68106 55.000001,111.71875 55,111.71875 C 55,111.71875 65.149673,109.12694 65,116.71875 C 64.85033,124.31055 55.000001,121.71875 55,121.71875 L 55,136.71875 L 100.5,136.71875 L 100.5,92.21875 L 115.5,92.21875 C 115.5,92.218748 112.9082,102.06908 120.5,102.21875 C 128.0918,102.36842 125.5,92.21875 125.5,92.21875 C 125.5,92.218748 135.5377,95.61637 135.5,87.21875 C 135.46231,78.821131 125.5,82.21875 125.5,82.21875 C 125.5,82.218747 128.9866,72.22272 120.5,72.21875 C 112.0133,72.214783 115.5,82.21875 115.5,82.21875 L 100.5,82.21875 L 100.5,36.71875 L 54.9375,36.71875 L 54.9375,26.71875 C 54.9375,26.71875 63.67038,17.95739 64.78125,13.71875 C 66.055583,8.8564104 62.00121,1.71238 57.40625,1.71875 C 52.811292,1.7251201 50,6.71875 50,6.71875 C 49.999999,6.7187502 46.99798,1.61043 42.625,1.71875 z"
+ transform="translate(226.00357,358.81295)"
+ id="path2394"
+ style="fill:#ff0000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.991781px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
+ </g>
+</svg>
diff --git a/images/card1x.svg b/images/card1x.svg
new file mode 100644
index 0000000..8454f2b
--- /dev/null
+++ b/images/card1x.svg
@@ -0,0 +1,57 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+<svg
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ version="1.0"
+ width="135"
+ height="135.00002"
+ id="svg3193">
+ <defs
+ id="defs3195" />
+ <path
+ d="M 1.1368684e-13,135 L 1.1368684e-13,-2.8421709e-14 L 135,-2.8421709e-14 L 135,135 L 1.1368684e-13,135 z"
+ id="path2395"
+ style="fill:#ff0000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1.34653473px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
+ <text
+ x="-96.651611"
+ y="0"
+ transform="scale(-1,-1)"
+ id="text3172"
+ xml:space="preserve"
+ style="font-size:65px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:DejaVu Sans;-inkscape-font-specification:DejaVu Sans"><tspan
+ x="-96.651611"
+ y="0"
+ id="tspan3174">♥</tspan></text>
+ <text
+ x="-103.32032"
+ y="135"
+ transform="matrix(0,-1,1,0,0,0)"
+ id="text3176"
+ xml:space="preserve"
+ style="font-size:80px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:DejaVu Sans;-inkscape-font-specification:DejaVu Sans"><tspan
+ x="-103.32032"
+ y="135"
+ id="tspan3178">♦</tspan></text>
+ <text
+ x="31.679688"
+ y="135.00002"
+ id="text3184"
+ xml:space="preserve"
+ style="font-size:80px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:100%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:DejaVu Sans;-inkscape-font-specification:DejaVu Sans"><tspan
+ x="31.679688"
+ y="135.00002"
+ id="tspan3186"
+ style="font-size:80px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:100%;writing-mode:lr-tb;text-anchor:start;fill:#ffffff;fill-opacity:1;font-family:DejaVu Sans;-inkscape-font-specification:DejaVu Sans">♦</tspan></text>
+ <text
+ x="38.348396"
+ y="0"
+ transform="matrix(0,1,-1,0,0,0)"
+ id="text3189"
+ xml:space="preserve"
+ style="font-size:65px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:DejaVu Sans;-inkscape-font-specification:DejaVu Sans"><tspan
+ x="38.348396"
+ y="0"
+ id="tspan3191"
+ style="fill:#ffffff;fill-opacity:1">♥</tspan></text>
+</svg>
diff --git a/images/card2.svg b/images/card2.svg
new file mode 100644
index 0000000..f1489d0
--- /dev/null
+++ b/images/card2.svg
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+<svg
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ version="1.0"
+ width="135.00011"
+ height="135.00169"
+ id="svg3350">
+ <defs
+ id="defs3352" />
+ <path
+ d="M 42.125,0.0033886085 C 37.752031,0.11173722 33.34065,7.1796584 34.75,12.003238 C 35.95921,16.141816 44.59375,25.003075 44.59375,25.003075 L 44.59375,35.002949 L 0,35.002949 L 0,80.502378 L 10,80.502378 L 20,70.502504 L 35,85.502315 L 20,100.50212 L 10,90.502253 L 0,90.502253 L 0,135.00169 L 44.5,135.00169 L 44.5,125.00182 L 34.5,115.00194 L 49.5,100.00213 L 64.5,115.00194 L 54.5,125.00182 L 54.5,135.00169 L 100,135.00169 L 100,90.502253 L 115,90.502253 C 115,90.502251 112.4082,100.35246 120,100.50212 C 127.59181,100.65179 125,90.502253 125,90.502253 C 125,90.502251 135.03769,93.89983 135,85.502315 C 134.9623,77.104802 125,80.502378 125,80.502378 C 125,80.502382 128.48668,70.506474 120,70.502504 C 111.51332,70.498536 115,80.502378 115,80.502378 L 100,80.502378 L 100,35.002949 L 54.4375,35.002949 L 54.4375,25.003075 C 54.4375,25.003076 63.17038,16.241825 64.28125,12.003238 C 65.555579,7.1409589 61.50121,-0.0029813116 56.90625,0.0033886085 C 52.311288,0.0097584985 49.5,5.0033258 49.5,5.0033258 C 49.499999,5.003326 46.49798,-0.10493003 42.125,0.0033886085 z"
+ id="path2397"
+ style="fill:#ff0000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
+</svg>
diff --git a/images/card2x.svg b/images/card2x.svg
new file mode 100644
index 0000000..c6c950d
--- /dev/null
+++ b/images/card2x.svg
@@ -0,0 +1,57 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+<svg
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ version="1.0"
+ width="135"
+ height="135.00002"
+ id="svg3193">
+ <defs
+ id="defs3195" />
+ <path
+ d="M 1.1368684e-13,135 L 1.1368684e-13,-2.8421709e-14 L 135,-2.8421709e-14 L 135,135 L 1.1368684e-13,135 z"
+ id="path2395"
+ style="fill:#ff0000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1.34653473px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
+ <text
+ x="-96.651611"
+ y="0"
+ transform="scale(-1,-1)"
+ id="text3172"
+ xml:space="preserve"
+ style="font-size:65px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:DejaVu Sans;-inkscape-font-specification:DejaVu Sans"><tspan
+ x="-96.651611"
+ y="0"
+ id="tspan3174">♥</tspan></text>
+ <text
+ x="-103.32032"
+ y="135"
+ transform="matrix(0,-1,1,0,0,0)"
+ id="text3176"
+ xml:space="preserve"
+ style="font-size:80px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:DejaVu Sans;-inkscape-font-specification:DejaVu Sans"><tspan
+ x="-103.32032"
+ y="135"
+ id="tspan3178">♦</tspan></text>
+ <text
+ x="38.380127"
+ y="135.00002"
+ id="text3184"
+ xml:space="preserve"
+ style="font-size:80px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:100%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:DejaVu Sans;-inkscape-font-specification:DejaVu Sans"><tspan
+ x="38.380127"
+ y="135.00002"
+ id="tspan3186"
+ style="font-size:65px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:100%;writing-mode:lr-tb;text-anchor:start;fill:#ffffff;fill-opacity:1;font-family:DejaVu Sans;-inkscape-font-specification:DejaVu Sans">♣</tspan></text>
+ <text
+ x="38.380135"
+ y="0"
+ transform="matrix(0,1,-1,0,0,0)"
+ id="text3189"
+ xml:space="preserve"
+ style="font-size:65px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:DejaVu Sans;-inkscape-font-specification:DejaVu Sans"><tspan
+ x="38.380135"
+ y="0"
+ id="tspan3191"
+ style="fill:#ffffff;fill-opacity:1">♣</tspan></text>
+</svg>
diff --git a/images/card3.svg b/images/card3.svg
new file mode 100644
index 0000000..9a86603
--- /dev/null
+++ b/images/card3.svg
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+<svg
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ version="1.0"
+ width="135.00002"
+ height="135.00169"
+ id="svg3392">
+ <defs
+ id="defs3394" />
+ <g
+ transform="translate(-257.93214,-423.38165)"
+ id="layer1">
+ <path
+ d="M 42.25,0.8125 C 37.877001,0.92079997 33.4656,7.9889 34.875,12.8125 C 36.084199,16.9511 44.6875,25.8125 44.6875,25.8125 L 44.6875,35.8125 L 0.5,35.8125 L 0.5,81.3125 L 10.5,81.3125 L 20.5,71.3125 L 35.5,86.3125 L 20.5,101.3125 L 10.5,91.3125 L 0.5,91.3125 L 0.5,135.8125 L 45,135.8125 L 45,125.8125 C 42.1503,126.2354 35.126199,127.3292 35,120.8125 C 34.8738,114.2957 50.024901,100.8289 50,100.8125 C 49.9752,100.796 65.103596,113.5853 65,120.8125 C 64.8964,128.0396 55,125.8125 55,125.8125 L 55,135.8125 L 100.5,135.8125 L 100.5,91.3125 L 110.5,91.3125 C 110.5,91.312503 108.2729,101.2089 115.5,101.3125 C 122.7272,101.4161 135.5165,86.2877 135.5,86.3125 C 135.48361,86.337397 122.0168,71.1863 115.5,71.3125 C 108.9833,71.438703 110.0771,78.4628 110.5,81.3125 L 100.5,81.3125 L 100.5,35.8125 L 54.53125,35.8125 L 54.53125,25.8125 C 54.531249,25.812501 63.2641,17.0511 64.375,12.8125 C 65.649304,7.9502 61.595,0.8061 57,0.8125 C 52.4051,0.81879997 49.625,5.8125 49.625,5.8125 C 49.625001,5.8124999 46.623,0.7041 42.25,0.8125 z"
+ transform="translate(257.43214,422.57085)"
+ id="path2387"
+ style="fill:#ff0000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
+ </g>
+</svg>
diff --git a/images/card3x.svg b/images/card3x.svg
new file mode 100644
index 0000000..9eea220
--- /dev/null
+++ b/images/card3x.svg
@@ -0,0 +1,57 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+<svg
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ version="1.0"
+ width="135"
+ height="135.00002"
+ id="svg3193">
+ <defs
+ id="defs3195" />
+ <path
+ d="M 1.1368684e-13,135 L 1.1368684e-13,-2.8421709e-14 L 135,-2.8421709e-14 L 135,135 L 1.1368684e-13,135 z"
+ id="path2395"
+ style="fill:#ff0000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1.34653473px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
+ <text
+ x="-96.651611"
+ y="0"
+ transform="scale(-1,-1)"
+ id="text3172"
+ xml:space="preserve"
+ style="font-size:65px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:DejaVu Sans;-inkscape-font-specification:DejaVu Sans"><tspan
+ x="-96.651611"
+ y="0"
+ id="tspan3174">♥</tspan></text>
+ <text
+ x="-103.32032"
+ y="135"
+ transform="matrix(0,-1,1,0,0,0)"
+ id="text3176"
+ xml:space="preserve"
+ style="font-size:80px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:DejaVu Sans;-inkscape-font-specification:DejaVu Sans"><tspan
+ x="-103.32032"
+ y="135"
+ id="tspan3178">♠</tspan></text>
+ <text
+ x="31.660156"
+ y="135.00002"
+ id="text3184"
+ xml:space="preserve"
+ style="font-size:80px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:100%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:DejaVu Sans;-inkscape-font-specification:DejaVu Sans"><tspan
+ x="31.660156"
+ y="135.00002"
+ id="tspan3186"
+ style="font-size:80px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:100%;writing-mode:lr-tb;text-anchor:start;fill:#ffffff;fill-opacity:1;font-family:DejaVu Sans;-inkscape-font-specification:DejaVu Sans">♠</tspan></text>
+ <text
+ x="38.380135"
+ y="0"
+ transform="matrix(0,1,-1,0,0,0)"
+ id="text3189"
+ xml:space="preserve"
+ style="font-size:65px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:DejaVu Sans;-inkscape-font-specification:DejaVu Sans"><tspan
+ x="38.380135"
+ y="0"
+ id="tspan3191"
+ style="fill:#ffffff;fill-opacity:1">♣</tspan></text>
+</svg>
diff --git a/images/card4.svg b/images/card4.svg
new file mode 100644
index 0000000..0d597ae
--- /dev/null
+++ b/images/card4.svg
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+<svg
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ version="1.0"
+ width="135"
+ height="135.00011"
+ id="svg3200">
+ <defs
+ id="defs3202" />
+ <g
+ transform="translate(-29.360716,-778.80672)"
+ id="layer1">
+ <path
+ d="M 50,62.6875 C 41.602378,62.725191 45,72.6875 45,72.6875 C 45.000001,72.687501 35.00397,69.20082 35,77.6875 C 34.996029,86.174183 45,82.6875 45,82.6875 L 45,97.6875 L 0.5,97.6875 L 0.5,143.1875 L 15.5,143.1875 C 15.5,143.1875 12.01332,133.18352 20.5,133.1875 C 28.98668,133.19147 25.500001,143.1875 25.5,143.1875 C 25.5,143.1875 35.462311,139.78989 35.5,148.1875 C 35.53769,156.58512 25.500001,153.1875 25.5,153.1875 C 25.5,153.1875 28.09181,163.33718 20.5,163.1875 C 12.9082,163.03783 15.5,153.1875 15.5,153.1875 L 0.5,153.1875 L 0.5,197.6875 L 45,197.6875 L 45,187.6875 L 35,177.6875 L 50,162.6875 L 65,177.6875 L 55,187.6875 L 55,197.6875 L 100.5,197.6875 L 100.5,153.1875 L 110.5,153.1875 L 120.5,163.1875 L 135.5,148.1875 L 120.5,133.1875 L 110.5,143.1875 L 100.5,143.1875 L 100.5,97.6875 L 55,97.6875 L 55,82.6875 C 54.999999,82.687503 64.85033,85.2793 65,77.6875 C 65.149671,70.095693 55,72.6875 55,72.6875 C 54.999999,72.687501 58.39762,62.64981 50,62.6875 z"
+ transform="translate(28.860716,716.11933)"
+ id="path2387"
+ style="fill:#ff0000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
+ </g>
+</svg>
diff --git a/images/card4x.svg b/images/card4x.svg
new file mode 100644
index 0000000..3fca092
--- /dev/null
+++ b/images/card4x.svg
@@ -0,0 +1,57 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+<svg
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ version="1.0"
+ width="135"
+ height="135.00002"
+ id="svg3193">
+ <defs
+ id="defs3195" />
+ <path
+ d="M 1.1368684e-13,135 L 1.1368684e-13,-2.8421709e-14 L 135,-2.8421709e-14 L 135,135 L 1.1368684e-13,135 z"
+ id="path2395"
+ style="fill:#ff0000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1.34653473px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
+ <text
+ x="-103.32031"
+ y="0"
+ transform="scale(-1,-1)"
+ id="text3172"
+ xml:space="preserve"
+ style="font-size:80px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:DejaVu Sans;-inkscape-font-specification:DejaVu Sans"><tspan
+ x="-103.32031"
+ y="0"
+ id="tspan3174">♦</tspan></text>
+ <text
+ x="-96.619881"
+ y="135"
+ transform="matrix(0,-1,1,0,0,0)"
+ id="text3176"
+ xml:space="preserve"
+ style="font-size:65px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:DejaVu Sans;-inkscape-font-specification:DejaVu Sans"><tspan
+ x="-96.619881"
+ y="135"
+ id="tspan3178">♣</tspan></text>
+ <text
+ x="38.380127"
+ y="135.00002"
+ id="text3184"
+ xml:space="preserve"
+ style="font-size:80px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:100%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:DejaVu Sans;-inkscape-font-specification:DejaVu Sans"><tspan
+ x="38.380127"
+ y="135.00002"
+ id="tspan3186"
+ style="font-size:65px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:100%;writing-mode:lr-tb;text-anchor:start;fill:#ffffff;fill-opacity:1;font-family:DejaVu Sans;-inkscape-font-specification:DejaVu Sans">♣</tspan></text>
+ <text
+ x="31.679695"
+ y="0"
+ transform="matrix(0,1,-1,0,0,0)"
+ id="text3189"
+ xml:space="preserve"
+ style="font-size:80px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:DejaVu Sans;-inkscape-font-specification:DejaVu Sans"><tspan
+ x="31.679695"
+ y="0"
+ id="tspan3191"
+ style="fill:#ffffff;fill-opacity:1">♦</tspan></text>
+</svg>
diff --git a/images/card5.svg b/images/card5.svg
new file mode 100644
index 0000000..a632650
--- /dev/null
+++ b/images/card5.svg
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+<svg
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ version="1.0"
+ width="135.00169"
+ height="135"
+ id="svg3209">
+ <defs
+ id="defs3211" />
+ <g
+ transform="translate(-295.075,-306.24719)"
+ id="layer1">
+ <path
+ d="M 50,3.0625 L 35,18.0625 L 45,28.0625 L 45,38.0625 L 0.5,38.0625 L 0.5,83.65625 L 10.5,83.65625 C 10.5,83.65625 19.36137,75.021713 23.5,73.8125 C 28.32364,72.40315 35.391649,76.814534 35.5,81.1875 C 35.60832,85.56048 30.5,88.562501 30.5,88.5625 C 30.5,88.5625 35.493629,91.342537 35.5,95.9375 C 35.50637,100.53246 28.36234,104.58683 23.5,103.3125 C 19.26136,102.20163 10.5,93.468753 10.5,93.46875 L 0.5,93.46875 L 0.5,138.0625 L 45,138.0625 L 45,128.0625 C 42.15031,128.48543 35.126229,129.57924 35,123.0625 C 34.87376,116.54578 50.024832,103.07894 50,103.0625 C 49.97517,103.04607 65.103599,115.83535 65,123.0625 C 64.89639,130.28966 55.000002,128.0625 55,128.0625 L 55,138.0625 L 100.5,138.0625 L 100.5,93.46875 L 110.5,93.46875 C 110.5,93.468753 119.26136,102.20163 123.5,103.3125 C 128.36234,104.58683 135.50637,100.53246 135.5,95.9375 C 135.49363,91.342537 130.5,88.5625 130.5,88.5625 C 130.5,88.562501 135.60832,85.56048 135.5,81.1875 C 135.39165,76.814534 128.32364,72.40315 123.5,73.8125 C 119.36137,75.021713 110.5,83.65625 110.5,83.65625 L 100.5,83.65625 L 100.5,38.0625 L 55,38.0625 L 55,28.0625 L 65,18.0625 L 50,3.0625 z"
+ transform="translate(294.575,303.18469)"
+ id="path2387"
+ style="fill:#ff0000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
+ </g>
+</svg>
diff --git a/images/card5x.svg b/images/card5x.svg
new file mode 100644
index 0000000..f95331b
--- /dev/null
+++ b/images/card5x.svg
@@ -0,0 +1,57 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+<svg
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ version="1.0"
+ width="135"
+ height="135.00002"
+ id="svg3193">
+ <defs
+ id="defs3195" />
+ <path
+ d="M 1.1368684e-13,135 L 1.1368684e-13,-2.8421709e-14 L 135,-2.8421709e-14 L 135,135 L 1.1368684e-13,135 z"
+ id="path2395"
+ style="fill:#ff0000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1.34653473px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
+ <text
+ x="-96.619873"
+ y="0"
+ transform="scale(-1,-1)"
+ id="text3172"
+ xml:space="preserve"
+ style="font-size:65px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:DejaVu Sans;-inkscape-font-specification:DejaVu Sans"><tspan
+ x="-96.619873"
+ y="0"
+ id="tspan3174">♣</tspan></text>
+ <text
+ x="-96.651619"
+ y="135"
+ transform="matrix(0,-1,1,0,0,0)"
+ id="text3176"
+ xml:space="preserve"
+ style="font-size:65px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:DejaVu Sans;-inkscape-font-specification:DejaVu Sans"><tspan
+ x="-96.651619"
+ y="135"
+ id="tspan3178">♥</tspan></text>
+ <text
+ x="31.660156"
+ y="135.00002"
+ id="text3184"
+ xml:space="preserve"
+ style="font-size:80px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:100%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:DejaVu Sans;-inkscape-font-specification:DejaVu Sans"><tspan
+ x="31.660156"
+ y="135.00002"
+ id="tspan3186"
+ style="font-size:80px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:100%;writing-mode:lr-tb;text-anchor:start;fill:#ffffff;fill-opacity:1;font-family:DejaVu Sans;-inkscape-font-specification:DejaVu Sans">♠</tspan></text>
+ <text
+ x="38.348396"
+ y="0"
+ transform="matrix(0,1,-1,0,0,0)"
+ id="text3189"
+ xml:space="preserve"
+ style="font-size:65px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:DejaVu Sans;-inkscape-font-specification:DejaVu Sans"><tspan
+ x="38.348396"
+ y="0"
+ id="tspan3191"
+ style="fill:#ffffff;fill-opacity:1">♥</tspan></text>
+</svg>
diff --git a/images/card6.svg b/images/card6.svg
new file mode 100644
index 0000000..26888a3
--- /dev/null
+++ b/images/card6.svg
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+<svg
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ version="1.0"
+ width="135.00002"
+ height="135.00002"
+ id="svg2397">
+ <defs
+ id="defs2399" />
+ <g
+ transform="translate(-259.92143,-373.34456)"
+ id="layer1">
+ <path
+ d="M 50.5,0.6875 C 50.524832,0.70394001 35.37376,14.17078 35.5,20.6875 C 35.626229,27.204239 42.65031,26.11043 45.5,25.6875 L 45.5,35.6875 L 0.5,35.6875 L 0.5,80.6875 L 10.5,80.6875 L 20.5,70.6875 L 35.5,85.6875 L 20.5,100.6875 L 10.5,90.6875 L 0.5,90.6875 L 0.5,135.6875 L 45.59375,135.6875 L 45.59375,125.6875 C 45.59375,125.6875 36.959209,116.82613 35.75,112.6875 C 34.34065,107.86386 38.752029,100.79585 43.125,100.6875 C 47.49798,100.57918 50.500001,105.6875 50.5,105.6875 C 50.5,105.6875 53.31129,100.69387 57.90625,100.6875 C 62.50121,100.68113 66.555577,107.82516 65.28125,112.6875 C 64.17038,116.92614 55.437499,125.6875 55.4375,125.6875 L 55.4375,135.6875 L 100.5,135.6875 L 100.5,90.6875 L 110.5,90.6875 C 110.5,90.687503 108.27284,100.58389 115.5,100.6875 C 122.72715,100.7911 135.51643,85.66267 135.5,85.6875 C 135.48355,85.712329 122.01672,70.56126 115.5,70.6875 C 108.98326,70.813731 110.07707,77.83781 110.5,80.6875 L 100.5,80.6875 L 100.5,35.6875 L 55.5,35.6875 L 55.5,25.6875 C 55.500002,25.687499 65.39639,27.91466 65.5,20.6875 C 65.603599,13.460349 50.47517,0.67107 50.5,0.6875 z"
+ transform="translate(259.42143,372.65708)"
+ id="path2387"
+ style="fill:#ff0000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
+ </g>
+</svg>
diff --git a/images/card6x.svg b/images/card6x.svg
new file mode 100644
index 0000000..e4699f1
--- /dev/null
+++ b/images/card6x.svg
@@ -0,0 +1,57 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+<svg
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ version="1.0"
+ width="135"
+ height="135.00002"
+ id="svg3193">
+ <defs
+ id="defs3195" />
+ <path
+ d="M 1.1368684e-13,135 L 1.1368684e-13,-2.8421709e-14 L 135,-2.8421709e-14 L 135,135 L 1.1368684e-13,135 z"
+ id="path2395"
+ style="fill:#ff0000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1.34653473px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
+ <text
+ x="-103.33984"
+ y="0"
+ transform="scale(-1,-1)"
+ id="text3172"
+ xml:space="preserve"
+ style="font-size:80px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:DejaVu Sans;-inkscape-font-specification:DejaVu Sans"><tspan
+ x="-103.33984"
+ y="0"
+ id="tspan3174">♠</tspan></text>
+ <text
+ x="-103.33985"
+ y="135"
+ transform="matrix(0,-1,1,0,0,0)"
+ id="text3176"
+ xml:space="preserve"
+ style="font-size:80px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:DejaVu Sans;-inkscape-font-specification:DejaVu Sans"><tspan
+ x="-103.33985"
+ y="135"
+ id="tspan3178">♠</tspan></text>
+ <text
+ x="38.348389"
+ y="135.00002"
+ id="text3184"
+ xml:space="preserve"
+ style="font-size:80px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:100%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:DejaVu Sans;-inkscape-font-specification:DejaVu Sans"><tspan
+ x="38.348389"
+ y="135.00002"
+ id="tspan3186"
+ style="font-size:65px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:100%;writing-mode:lr-tb;text-anchor:start;fill:#ffffff;fill-opacity:1;font-family:DejaVu Sans;-inkscape-font-specification:DejaVu Sans">♥</tspan></text>
+ <text
+ x="38.380135"
+ y="0"
+ transform="matrix(0,1,-1,0,0,0)"
+ id="text3189"
+ xml:space="preserve"
+ style="font-size:65px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:DejaVu Sans;-inkscape-font-specification:DejaVu Sans"><tspan
+ x="38.380135"
+ y="0"
+ id="tspan3191"
+ style="fill:#ffffff;fill-opacity:1">♣</tspan></text>
+</svg>
diff --git a/images/card7.svg b/images/card7.svg
new file mode 100644
index 0000000..815e4a2
--- /dev/null
+++ b/images/card7.svg
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+<svg
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ version="1.0"
+ width="135.00169"
+ height="135"
+ id="svg4304">
+ <defs
+ id="defs4306" />
+ <g
+ transform="translate(-172.21786,-626.23612)"
+ id="layer1">
+ <path
+ d="M 50,1.25 L 35,16.25 L 45,26.25 L 45,36.25 L 0.5,36.25 L 0.5,81.75 L 10.5,81.75 L 20.5,71.75 L 35.5,86.75 L 20.5,101.75 L 10.5,91.75 L 0.5,91.75 L 0.5,136.25 L 45,136.25 L 45,121.25 C 45,121.25 34.996031,124.7367 35,116.25 C 35.00397,107.7633 44.999999,111.25 45,111.25 C 45,111.25 41.60238,101.2877 50,101.25 C 58.39762,101.2123 55.000001,111.25 55,111.25 C 55,111.25 65.149673,108.6582 65,116.25 C 64.85033,123.8418 55.000001,121.25 55,121.25 L 55,136.25 L 100.5,136.25 L 100.5,91.6875 L 110.5,91.6875 C 110.5,91.6875 119.2613,100.38913 123.5,101.5 C 128.3623,102.77433 135.5064,98.71996 135.5,94.125 C 135.49359,89.530042 130.5,86.75 130.5,86.75 C 130.49999,86.749999 135.6083,83.74798 135.5,79.375 C 135.39159,75.002031 128.3236,70.59065 123.5,72 C 119.3613,73.20921 110.5,81.84375 110.5,81.84375 L 100.5,81.84375 L 100.5,36.25 L 55,36.25 L 55,26.25 L 65,16.25 L 50,1.25 z"
+ transform="translate(171.71786,624.98612)"
+ id="path2387"
+ style="fill:#ff0000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
+ </g>
+</svg>
diff --git a/images/card7x.svg b/images/card7x.svg
new file mode 100644
index 0000000..e69eab6
--- /dev/null
+++ b/images/card7x.svg
@@ -0,0 +1,57 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+<svg
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ version="1.0"
+ width="135"
+ height="135.00002"
+ id="svg3193">
+ <defs
+ id="defs3195" />
+ <path
+ d="M 1.1368684e-13,135 L 1.1368684e-13,-2.8421709e-14 L 135,-2.8421709e-14 L 135,135 L 1.1368684e-13,135 z"
+ id="path2395"
+ style="fill:#ff0000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1.34653473px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
+ <text
+ x="-96.619873"
+ y="0"
+ transform="scale(-1,-1)"
+ id="text3172"
+ xml:space="preserve"
+ style="font-size:65px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:DejaVu Sans;-inkscape-font-specification:DejaVu Sans"><tspan
+ x="-96.619873"
+ y="0"
+ id="tspan3174">♣</tspan></text>
+ <text
+ x="-96.651619"
+ y="135"
+ transform="matrix(0,-1,1,0,0,0)"
+ id="text3176"
+ xml:space="preserve"
+ style="font-size:65px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:DejaVu Sans;-inkscape-font-specification:DejaVu Sans"><tspan
+ x="-96.651619"
+ y="135"
+ id="tspan3178">♥</tspan></text>
+ <text
+ x="31.679688"
+ y="135.00002"
+ id="text3184"
+ xml:space="preserve"
+ style="font-size:80px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:100%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:DejaVu Sans;-inkscape-font-specification:DejaVu Sans"><tspan
+ x="31.679688"
+ y="135.00002"
+ id="tspan3186"
+ style="font-size:80px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:100%;writing-mode:lr-tb;text-anchor:start;fill:#ffffff;fill-opacity:1;font-family:DejaVu Sans;-inkscape-font-specification:DejaVu Sans">♦</tspan></text>
+ <text
+ x="38.380135"
+ y="0"
+ transform="matrix(0,1,-1,0,0,0)"
+ id="text3189"
+ xml:space="preserve"
+ style="font-size:65px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:DejaVu Sans;-inkscape-font-specification:DejaVu Sans"><tspan
+ x="38.380135"
+ y="0"
+ id="tspan3191"
+ style="fill:#ffffff;fill-opacity:1">♣</tspan></text>
+</svg>
diff --git a/images/card8.svg b/images/card8.svg
new file mode 100644
index 0000000..6664656
--- /dev/null
+++ b/images/card8.svg
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+<svg
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ version="1.0"
+ width="135.00011"
+ height="135.00002"
+ id="svg4855">
+ <defs
+ id="defs4857" />
+ <g
+ transform="translate(-206.50358,-294.80223)"
+ id="layer1">
+ <path
+ d="M 50,1.78125 C 50.024832,1.79769 34.87376,15.26453 35,21.78125 C 35.126229,28.29799 42.15031,27.20418 45,26.78125 L 45,36.78125 L 0.5,36.78125 L 0.5,82.375 L 10.5,82.375 C 10.5,82.375 19.36137,73.77171 23.5,72.5625 C 28.32364,71.15315 35.391649,75.564531 35.5,79.9375 C 35.60832,84.31048 30.5,87.312499 30.5,87.3125 C 30.5,87.3125 35.493629,90.092542 35.5,94.6875 C 35.50637,99.28246 28.36234,103.33683 23.5,102.0625 C 19.26136,100.95163 10.5,92.21875 10.5,92.21875 L 0.5,92.21875 L 0.5,136.78125 L 48.75,136.78125 L 48.75,126.78125 C 45.90031,127.20418 38.87623,128.29799 38.75,121.78125 C 38.62376,115.26453 53.774828,101.79769 53.75,101.78125 C 53.72517,101.76482 68.853599,114.5541 68.75,121.78125 C 68.64639,129.00841 58.749998,126.78125 58.75,126.78125 L 58.75,136.78125 L 100.5,136.78125 L 100.5,92.28125 L 115.5,92.28125 C 115.5,92.281251 112.9082,102.13158 120.5,102.28125 C 128.09181,102.43092 125.5,92.28125 125.5,92.28125 C 125.5,92.281251 135.53769,95.67887 135.5,87.28125 C 135.4623,78.883626 125.5,82.28125 125.5,82.28125 C 125.5,82.281249 128.98668,72.28522 120.5,72.28125 C 112.01332,72.277278 115.5,82.28125 115.5,82.28125 L 100.5,82.28125 L 100.5,36.78125 L 55,36.78125 L 55,26.78125 C 55.000002,26.78125 64.89639,29.00841 65,21.78125 C 65.103599,14.5541 49.97517,1.76482 50,1.78125 z"
+ transform="translate(206.00358,293.021)"
+ id="path2392"
+ style="fill:#ff0000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.99997878px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
+ </g>
+</svg>
diff --git a/images/card8x.svg b/images/card8x.svg
new file mode 100644
index 0000000..0a9b27d
--- /dev/null
+++ b/images/card8x.svg
@@ -0,0 +1,57 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+<svg
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ version="1.0"
+ width="135"
+ height="135.00002"
+ id="svg3193">
+ <defs
+ id="defs3195" />
+ <path
+ d="M 1.1368684e-13,135 L 1.1368684e-13,-2.8421709e-14 L 135,-2.8421709e-14 L 135,135 L 1.1368684e-13,135 z"
+ id="path2395"
+ style="fill:#ff0000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1.34653473px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
+ <text
+ x="-103.33984"
+ y="0"
+ transform="scale(-1,-1)"
+ id="text3172"
+ xml:space="preserve"
+ style="font-size:80px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:DejaVu Sans;-inkscape-font-specification:DejaVu Sans"><tspan
+ x="-103.33984"
+ y="0"
+ id="tspan3174">♠</tspan></text>
+ <text
+ x="-103.32032"
+ y="135"
+ transform="matrix(0,-1,1,0,0,0)"
+ id="text3176"
+ xml:space="preserve"
+ style="font-size:80px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:DejaVu Sans;-inkscape-font-specification:DejaVu Sans"><tspan
+ x="-103.32032"
+ y="135"
+ id="tspan3178">♦</tspan></text>
+ <text
+ x="31.660156"
+ y="135.00002"
+ id="text3184"
+ xml:space="preserve"
+ style="font-size:80px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:100%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:DejaVu Sans;-inkscape-font-specification:DejaVu Sans"><tspan
+ x="31.660156"
+ y="135.00002"
+ id="tspan3186"
+ style="font-size:80px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:100%;writing-mode:lr-tb;text-anchor:start;fill:#ffffff;fill-opacity:1;font-family:DejaVu Sans;-inkscape-font-specification:DejaVu Sans">♠</tspan></text>
+ <text
+ x="38.348396"
+ y="0"
+ transform="matrix(0,1,-1,0,0,0)"
+ id="text3189"
+ xml:space="preserve"
+ style="font-size:65px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:DejaVu Sans;-inkscape-font-specification:DejaVu Sans"><tspan
+ x="38.348396"
+ y="0"
+ id="tspan3191"
+ style="fill:#ffffff;fill-opacity:1">♥</tspan></text>
+</svg>
diff --git a/po/CardSort.pot b/po/CardSort.pot
new file mode 100644
index 0000000..ef777a7
--- /dev/null
+++ b/po/CardSort.pot
@@ -0,0 +1,44 @@
+# SOME DESCRIPTIVE TITLE.
+# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
+# This file is distributed under the same license as the PACKAGE package.
+# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
+#
+#, fuzzy
+msgid ""
+msgstr ""
+"Project-Id-Version: PACKAGE VERSION\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2009-10-02 21:08+0000\n"
+"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
+"Language-Team: LANGUAGE <LL@li.org>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=CHARSET\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+#: activity/activity.info:2
+msgid "Card Sort"
+msgstr ""
+
+#: /home/walter/Desktop/cardsort/CardSortActivity.py:175
+msgid "Solve it"
+msgstr ""
+
+#: /home/walter/Desktop/cardsort/CardSortActivity.py:186
+#: /home/walter/Desktop/cardsort/CardSortActivity.bu.py:145
+msgid "click to rotate; drag to swap"
+msgstr ""
+
+#: /home/walter/Desktop/cardsort/CardSortActivity.py:249
+msgid "I don't know how to solve it."
+msgstr ""
+
+#: /home/walter/Desktop/cardsort/CardSortActivity.py:307
+#: /home/walter/Desktop/cardsort/CardSortActivity.bu.py:284
+msgid "You solved the puzzle."
+msgstr ""
+
+#: /home/walter/Desktop/cardsort/CardSortActivity.py:310
+#: /home/walter/Desktop/cardsort/CardSortActivity.bu.py:287
+msgid "Keep trying."
+msgstr ""
diff --git a/setup.py b/setup.py
new file mode 100755
index 0000000..bd1e319
--- /dev/null
+++ b/setup.py
@@ -0,0 +1,5 @@
+#!/usr/bin/env python
+from sugar.activity import bundlebuilder
+if __name__ == "__main__":
+ bundlebuilder.start()
+
diff --git a/sprites.py b/sprites.py
new file mode 100644
index 0000000..2a369a8
--- /dev/null
+++ b/sprites.py
@@ -0,0 +1,161 @@
+# -*- coding: utf-8 -*-
+
+#Copyright (c) 2007-8, Playful Invention Company.
+#Copyright (c) 2008-9, Walter Bender
+
+#Permission is hereby granted, free of charge, to any person obtaining a copy
+#of this software and associated documentation files (the "Software"), to deal
+#in the Software without restriction, including without limitation the rights
+#to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+#copies of the Software, and to permit persons to whom the Software is
+#furnished to do so, subject to the following conditions:
+
+#The above copyright notice and this permission notice shall be included in
+#all copies or substantial portions of the Software.
+
+#THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+#IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+#FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+#AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+#LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+#OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+#THE SOFTWARE.
+
+import pygtk
+pygtk.require('2.0')
+import gtk
+import gobject
+import pango
+class taSprite: pass
+
+def findsprite(tw,pos):
+ list = tw.sprites[:]
+ list.reverse()
+ for s in list:
+ if hit(s,pos): return s
+ return None
+
+def redrawsprites(tw):
+ for s in tw.sprites: draw(s)
+
+def sprNew(tw,x,y,image,altlabel=False):
+ spr = taSprite()
+ spr.tw, spr.x, spr.y = tw,x,y
+ setimage(spr,image)
+ spr.label = None
+ spr.ds_id = None
+ if altlabel:
+ spr.draw_label = draw_label2
+ else: spr.draw_label = draw_label1
+ return spr
+
+def setimage(spr,image):
+ spr.image = image
+ if isinstance(image,gtk.gdk.Pixbuf):
+ spr.width = image.get_width()
+ spr.height = image.get_height()
+ else: spr.width,spr.height=image.get_size()
+
+def move(spr,pos):
+ inval(spr)
+ spr.x,spr.y = pos
+ inval(spr)
+
+def setshape(spr,image):
+ inval(spr)
+ setimage(spr,image)
+ inval(spr)
+
+def setshapex(spr):
+ inval(spr)
+
+def setlayer(spr, layer):
+ sprites = spr.tw.sprites
+ if spr in sprites: sprites.remove(spr)
+ spr.layer = layer
+ for i in range(len(sprites)):
+ if layer < sprites[i].layer:
+ sprites.insert(i, spr)
+ inval(spr)
+ return
+ sprites.append(spr)
+ inval(spr)
+
+def hide(spr):
+ if spr not in spr.tw.sprites: return
+ inval(spr)
+ spr.tw.sprites.remove(spr)
+
+def setlabel(spr,label):
+ spr.label = label
+ inval(spr)
+
+def inval(spr):
+ spr.tw.area.invalidate_rect(gtk.gdk.Rectangle(spr.x,spr.y,spr.width, \
+ spr.height), False)
+
+def draw(spr):
+ if isinstance(spr.image,gtk.gdk.Pixbuf):
+ spr.tw.area.draw_pixbuf(spr.tw.gc, spr.image, 0, 0, spr.x, spr.y)
+ else:
+ spr.tw.area.draw_drawable(spr.tw.gc,spr.image,0,0,spr.x,spr.y,-1,-1)
+ if spr.label!=None:
+ if hasattr(spr, 'proto') and hasattr(spr.proto, 'name'):
+ name = spr.proto.name
+ else:
+ name = ""
+ spr.draw_label(spr,str(spr.label))
+
+def hit(spr,pos):
+ x,y = pos
+ if x<spr.x: return False
+ if x>spr.x+spr.width: return False
+ if y<spr.y: return False
+ if y>spr.y+spr.height: return False
+ if isinstance(spr.image,gtk.gdk.Pixmap): return True
+ if hasattr(spr, 'proto') and hasattr(spr.proto, 'name') and \
+ spr.proto.name == 'journal':
+ return True
+ dx,dy = x-spr.x, y-spr.y
+ try:
+ return ord(spr.image.get_pixels()[(dy*spr.width+dx)*4+3]) == 255
+ except IndexError:
+ if hasattr(spr, 'proto') and hasattr(spr.proto, 'name'):
+ print spr.proto.name
+ print "IndexError: string index out of range" + str(dx) + " " \
+ + str(dy) + " " + str(spr.width) + " " + str(spr.height)
+ return True
+
+def draw_label(spr, label, myscale, center_flag, truncate_flag):
+ fd = pango.FontDescription('Sans')
+ fd.set_size(int(myscale*spr.tw.scale*pango.SCALE))
+ if type(label) == str or type(label) == unicode:
+ mylabel = label.replace("\0"," ")
+ l = len(mylabel)
+ if truncate_flag and l > 8:
+ pl = spr.tw.window.create_pango_layout("..."+mylabel[l-8:])
+ else:
+ pl = spr.tw.window.create_pango_layout(mylabel)
+ pl.set_font_description(fd)
+ if center_flag:
+ swidth = pl.get_size()[0]/pango.SCALE
+ centerx = spr.x+spr.width/2
+ x = int(centerx-swidth/2)
+ else:
+ x = spr.x+70
+ sheight = pl.get_size()[1]/pango.SCALE
+ centery = spr.y+spr.height/2
+ y = int(centery-sheight/2)
+ spr.tw.gc.set_foreground(spr.tw.msgcolor)
+ spr.tw.area.draw_layout(spr.tw.gc, x, y, pl)
+ else:
+ print type(label)
+
+# used for most things
+def draw_label1(spr, label):
+ draw_label(spr, label, 7, True, True)
+
+# used for status blocks
+def draw_label2(spr, label):
+ draw_label(spr, str(label), 9, False, False)
+
diff --git a/sprites.pyc b/sprites.pyc
new file mode 100644
index 0000000..eba2b52
--- /dev/null
+++ b/sprites.pyc
Binary files differ
diff --git a/sprites.py~ b/sprites.py~
new file mode 100644
index 0000000..85993bc
--- /dev/null
+++ b/sprites.py~
@@ -0,0 +1,174 @@
+# -*- coding: utf-8 -*-
+
+#Copyright (c) 2007-8, Playful Invention Company.
+#Copyright (c) 2008-9, Walter Bender
+
+#Permission is hereby granted, free of charge, to any person obtaining a copy
+#of this software and associated documentation files (the "Software"), to deal
+#in the Software without restriction, including without limitation the rights
+#to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+#copies of the Software, and to permit persons to whom the Software is
+#furnished to do so, subject to the following conditions:
+
+#The above copyright notice and this permission notice shall be included in
+#all copies or substantial portions of the Software.
+
+#THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+#IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+#FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+#AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+#LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+#OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+#THE SOFTWARE.
+
+import pygtk
+pygtk.require('2.0')
+import gtk
+import gobject
+import pango
+class taSprite: pass
+
+# Don't display the label for these blocks
+nolabel = ['audiooff', 'descriptionoff','journal']
+
+def findsprite(tw,pos):
+ list = tw.sprites[:]
+ list.reverse()
+ for s in list:
+ if hit(s,pos): return s
+ return None
+
+def redrawsprites(tw):
+ for s in tw.sprites: draw(s)
+
+def sprNew(tw,x,y,image,altlabel=False):
+ spr = taSprite()
+ spr.tw, spr.x, spr.y = tw,x,y
+ setimage(spr,image)
+ spr.label = None
+ spr.ds_id = None
+ if altlabel:
+ spr.draw_label = draw_label2
+ else: spr.draw_label = draw_label1
+ return spr
+
+def setimage(spr,image):
+ spr.image = image
+ if isinstance(image,gtk.gdk.Pixbuf):
+ spr.width = image.get_width()
+ spr.height = image.get_height()
+ else: spr.width,spr.height=image.get_size()
+
+def move(spr,pos):
+ inval(spr)
+ spr.x,spr.y = pos
+ inval(spr)
+
+def setshape(spr,image):
+ inval(spr)
+ setimage(spr,image)
+ inval(spr)
+
+def setshapex(spr):
+ inval(spr)
+
+def setlayer(spr, layer):
+ sprites = spr.tw.sprites
+ if spr in sprites: sprites.remove(spr)
+ spr.layer = layer
+ for i in range(len(sprites)):
+ if layer < sprites[i].layer:
+ sprites.insert(i, spr)
+ inval(spr)
+ return
+ sprites.append(spr)
+ inval(spr)
+
+def hide(spr):
+ if spr not in spr.tw.sprites: return
+ inval(spr)
+ spr.tw.sprites.remove(spr)
+
+def setlabel(spr,label):
+ spr.label = label
+ inval(spr)
+
+def inval(spr):
+ spr.tw.area.invalidate_rect(gtk.gdk.Rectangle(spr.x,spr.y,spr.width, \
+ spr.height), False)
+
+def draw(spr):
+ if isinstance(spr.image,gtk.gdk.Pixbuf):
+ spr.tw.area.draw_pixbuf(spr.tw.gc, spr.image, 0, 0, spr.x, spr.y)
+ else:
+ spr.tw.area.draw_drawable(spr.tw.gc,spr.image,0,0,spr.x,spr.y,-1,-1)
+ if spr.label!=None:
+ if hasattr(spr, 'proto') and hasattr(spr.proto, 'name'):
+ name = spr.proto.name
+ else:
+ name = ""
+ if name not in nolabel:
+ spr.draw_label(spr,str(spr.label))
+
+def hit(spr,pos):
+ x,y = pos
+ if x<spr.x: return False
+ if x>spr.x+spr.width: return False
+ if y<spr.y: return False
+ if y>spr.y+spr.height: return False
+ if isinstance(spr.image,gtk.gdk.Pixmap): return True
+ if hasattr(spr, 'proto') and hasattr(spr.proto, 'name') and \
+ spr.proto.name == 'journal':
+ return True
+ dx,dy = x-spr.x, y-spr.y
+ try:
+ return ord(spr.image.get_pixels()[(dy*spr.width+dx)*4+3]) == 255
+ except IndexError:
+ if hasattr(spr, 'proto') and hasattr(spr.proto, 'name'):
+ print spr.proto.name
+ print "IndexError: string index out of range" + str(dx) + " " \
+ + str(dy) + " " + str(spr.width) + " " + str(spr.height)
+ return True
+
+def draw_label(spr, label, myscale, center_flag, truncate_flag):
+ fd = pango.FontDescription('Sans')
+ fd.set_size(int(myscale*spr.tw.scale*pango.SCALE))
+ if type(label) == str or type(label) == unicode:
+ mylabel = label.replace("\0"," ")
+ l = len(mylabel)
+ if truncate_flag and l > 8:
+ pl = spr.tw.window.create_pango_layout("..."+mylabel[l-8:])
+ else:
+ pl = spr.tw.window.create_pango_layout(mylabel)
+ pl.set_font_description(fd)
+ if center_flag:
+ swidth = pl.get_size()[0]/pango.SCALE
+ centerx = spr.x+spr.width/2
+ x = int(centerx-swidth/2)
+ else:
+ x = spr.x+70
+ sheight = pl.get_size()[1]/pango.SCALE
+ centery = spr.y+spr.height/2
+ y = int(centery-sheight/2)
+ spr.tw.gc.set_foreground(spr.tw.msgcolor)
+ spr.tw.area.draw_layout(spr.tw.gc, x, y, pl)
+ else:
+ print type(label)
+
+# used for most things
+def draw_label1(spr, label):
+ draw_label(spr, label, 7, True, True)
+
+# used for status blocks
+def draw_label2(spr, label):
+ draw_label(spr, str(label), 9, False, False)
+
+# used to get pixel value from mask for category selector
+def getpixel(image,x,y):
+ array = image.get_pixels()
+ offset = (y*image.get_width()+x)*4
+ r,g,b,a = ord(array[offset]),ord(array[offset+1]),ord(array[offset+2]), \
+ ord(array[offset+3])
+ return (a<<24)+(b<<16)+(g<<8)+r
+
+